Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
20 commits
Select commit Hold shift + click to select a range
7a8f48b
docs: plugin overview
Nov 11, 2025
57f74c5
refactor(di): migrate to Stage 3 decorators and improve test coverage
sealday Nov 12, 2025
da13d99
feat(core): create module-standard-core plugin and define core interf…
sealday Nov 12, 2025
9ff604c
feat(core): refactor IPC communication for single Tego instance
sealday Nov 12, 2025
d8b28ba
feat(core): rename Application to Tego and update Plugin base class
sealday Nov 12, 2025
eb7e147
feat(core): implement EventBus and standardize event naming
sealday Nov 12, 2025
02ddcda
feat(core): integrate EventBus into Tego class
sealday Nov 12, 2025
613774b
feat(core): add DI container to Tego and document Phase 5 migration
sealday Nov 12, 2025
bfda0bb
feat(core): implement StandardCorePlugin and document Phase 5 completion
sealday Nov 12, 2025
0478d4b
docs(core): add comprehensive implementation status document
sealday Nov 12, 2025
47f0c6d
refactor(core): create minimal Tego class, remove all service depende…
sealday Nov 12, 2025
cf55fc6
feat(module-standard-core): add service structure and comprehensive d…
sealday Nov 12, 2025
9958972
docs(core): add comprehensive refactoring completion summary
sealday Nov 12, 2025
729b24e
refactor(core): migrate pub-sub/cache/cron services to module-standar…
sealday Nov 12, 2025
613927f
refactor(core): keep minimal console logger and move advanced logger …
sealday Nov 12, 2025
a5d9bd4
feat(module-standard-core): register migrated services during beforeLoad
sealday Nov 12, 2025
5995688
refactor(commands): move CLI registrations to module-standard-core pl…
sealday Nov 12, 2025
46939a9
feat(core-plugin): register gateway, supervisor, middlewares via modu…
sealday Nov 12, 2025
76f6b2f
refactor(core): drop legacy application implementation
sealday Nov 12, 2025
4d51422
fix: a
sealday Nov 12, 2025
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
194 changes: 194 additions & 0 deletions packages/core/docs/app-supervisor-analysis.en.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,194 @@
# AppSupervisor Analysis & Removal Feasibility

## Overview

`AppSupervisor` is TachyBase Core's built-in **multi-application instance manager**, implemented as a singleton. It coordinates the lifecycle, state synchronisation, and error handling of multiple `Application` instances within a single process. It primarily serves "multi-tenant" or "sub-application" scenarios, enabling a Gateway to route requests to different application instances.

## Core Responsibilities

1. **Application Registration & Lookup**
- `addApp(app)`: Registers an Application instance with the Supervisor.
- `getApp(appName)`: Retrieves an application by name, supporting lazy bootstrapping (via `appBootstrapper`).
- `hasApp(appName)`: Checks if an application is registered.
- `removeApp(appName)`: Destroys and removes an application.

2. **State Management**
- Maintains state for each application: `initializing | initialized | running | commanding | stopped | error | not_found`.
- Listens to application events (`maintaining`, `__started`, `afterStop`, `afterDestroy`) and syncs state to the Supervisor.
- Provides `setAppStatus()` / `getAppStatus()` for external queries.

3. **Error Tracking**
- `setAppError()` / `hasAppError()` / `clearAppError()`: Records application-level errors and emits `appError` events.

4. **Running Mode Control**
- Supports `single` mode (via `STARTUP_SUBAPP` env var for a specific sub-app) and `multiple` mode.
- `blockApps`: Prevents specific applications from being auto-bootstrapped.

5. **Bootstrapping & Mutual Exclusion**
- `setAppBootstrapper()`: Registers an application factory function for lazy instantiation.
- `bootStrapApp()`: Uses a Mutex to ensure each application is bootstrapped only once.

6. **Heartbeat & Activity**
- `touchApp()` / `lastSeenAt`: Records the last access time of an application to determine activity.

7. **Event Broadcasting**
- Emits `afterAppAdded`, `appStatusChanged`, `appMaintainingMessageChanged`, `appMaintainingStatusChanged`, `appError` for external subscribers.

## Use Cases

### 1. Gateway Routing to Multiple Apps
- `Gateway.requestHandler()` parses the target application name from request headers or query params (`x-app`, `__appName`).
- Calls `AppSupervisor.getInstance().getApp(appName)` to retrieve or bootstrap the application instance.
- Decides whether to forward the request, return an error, or trigger startup based on application state.

### 2. Multi-Tenant Architecture
- Each tenant corresponds to an independent `Application` instance (with shared or isolated databases).
- Supervisor manages tenant application lifecycles, avoiding duplicate creation.

### 3. Sub-Application Isolation
- In test or development environments, use `STARTUP_SUBAPP` to start only a specific sub-app, speeding up startup.

### 4. State Monitoring & Admin UI
- Admin dashboards can subscribe to Supervisor events to display real-time application status, errors, and maintenance messages.

## Dependencies

- **Depended Upon By**:
- `Application` automatically calls `AppSupervisor.getInstance().addApp(this)` during construction.
- `Gateway` frequently calls Supervisor methods in request handling and startup flows.
- `WSServer` and `IPCSocketServer` retrieve application instances via Supervisor.
- Test code (`__tests__/multiple-application.test.ts`, `__tests__/gateway.test.ts`) validates multi-app scenarios.

- **Dependencies**:
- `async-mutex`: Ensures mutual exclusion during application bootstrapping.
- `Application` events: Listens to lifecycle hooks to sync state.

## Removal Feasibility Analysis

### Scenario 1: Single-App Deployment (No Multi-Tenant Needs)
- **Feasibility**: ✅ **Highly Feasible**
- **Conditions**:
- Application always has only one `main` instance.
- Gateway does not need to route to multiple applications.
- **Refactor Plan**:
- Remove `AppSupervisor` singleton.
- `Application` no longer registers with Supervisor during construction.
- `Gateway` directly holds a `mainApp` reference instead of looking up via Supervisor.
- State management simplified to internal `Application` properties.
- **Benefits**:
- Reduces global singleton dependencies, lowering coupling.
- Simplifies code paths, improving testability.
- Reduces memory overhead (no application registry or state maps).

### Scenario 2: Multi-App Deployment (Multi-Tenant or Sub-Apps)
- **Feasibility**: ⚠️ **Requires Alternative Solution**
- **Conditions**:
- Need to manage multiple application instances within the same process.
- Gateway needs to dynamically route requests to different applications.
- **Refactor Plan**:
- Transform `AppSupervisor` into a container-registered service (not a global singleton).
- Inject via DI container into `Gateway` and plugins requiring multi-app management.
- State management can optionally persist to Redis (for cluster mode) or remain in-process.
- **Benefits**:
- Eliminates global singleton dependency, supporting multi-instance testing.
- More flexible lifecycle management (multi-app capability can be enabled/disabled as needed).
- Provides extension points for application state sharing in cluster mode.

### Scenario 3: Cluster Mode
- **Feasibility**: ⚠️ **Requires Redesign**
- **Issues**:
- Current `AppSupervisor` is a process-local singleton, unable to share state across processes.
- Multiple worker processes each maintain independent application registries, potentially causing state inconsistencies.
- **Refactor Plan**:
- Store application state in Redis or a shared database.
- Transform Supervisor into a "state proxy" that reads application state from shared storage.
- Coordinate application bootstrapping and state changes via distributed locks or a leader process.
- **Benefits**:
- Supports true multi-process deployment.
- Application state remains consistent across all workers.

## Potential Benefits of Removal

1. **Reduced Complexity**
- Eliminates global singleton, reducing implicit dependencies.
- Simplifies `Application` construction logic (no automatic registration).

2. **Improved Testability**
- No longer relies on global state; test isolation is more thorough.
- Different application manager implementations can be injected for different test scenarios.

3. **Better DI Integration**
- Registers application management capability in the container, aligning with 2.0 architecture direction.
- Plugins can depend on application management services as needed, rather than being forced to use a global singleton.

4. **Flexible Deployment Modes**
- Single-app scenarios avoid multi-app management overhead.
- Multi-app scenarios can choose in-process or distributed implementations.

## Potential Risks of Removal

1. **Breaks Existing Multi-Tenant Architecture**
- If the product relies on multi-app routing, removing Supervisor requires an alternative solution.

2. **Gateway Refactor Cost**
- `Gateway.requestHandler()` heavily depends on Supervisor; routing logic needs rewriting.

3. **State Sync Complexity**
- Currently, state changes are uniformly managed via Supervisor events; removal requires a new mechanism.

4. **Test Case Invalidation**
- Tests like `__tests__/multiple-application.test.ts` need rewriting.

## Recommended Approach

### Short-Term (TachyBase 2.0 Alpha)
1. **Keep AppSupervisor, but as a Container Service**
- No longer use global singleton; register and resolve via container.
- `Application` retrieves Supervisor from container and registers itself during construction.
- `Gateway` resolves Supervisor via container.

2. **Abstract Application Management Interface**
- Define `IApplicationRegistry` interface with `register/get/remove/getStatus` methods.
- `AppSupervisor` as default implementation; support lightweight implementation for single-app scenarios (e.g., `SingleAppRegistry`).

3. **Configurable Multi-App Support**
- Use config option `multiApp: boolean` to decide whether to enable multi-app management.
- Single-app mode automatically uses simplified implementation.

### Mid-Term (TachyBase 2.0 Beta)
1. **Implement Distributed Application Management**
- Provide `RedisApplicationRegistry` implementation for cluster mode.
- Store application state in Redis, using distributed locks to coordinate bootstrapping.

2. **Pluginise Gateway Routing**
- Extract multi-app routing logic into a plugin (e.g., `@tego/plugin-multi-app-router`).
- Core Gateway only handles basic HTTP serving; routing strategy provided by plugins.

### Long-Term (TachyBase 2.x Stable)
1. **Fully Remove AppSupervisor**
- Single-app scenarios no longer need an application manager.
- Multi-app scenarios provided by dedicated plugins; core no longer includes it.

2. **Standardise Application Lifecycle Protocol**
- Define cross-process application state sync protocol (based on Pub/Sub or gRPC).
- Support application instances running in different processes or even different machines.

## Conclusion

- **AppSupervisor is a built-in multi-app management capability**, supporting multi-tenant and sub-application scenarios.
- **Can be removed in single-app scenarios**, with benefits including reduced complexity, improved testability, and better DI integration.
- **Multi-app scenarios require an alternative solution**; recommend first converting to a container service, then gradually pluginising.
- **Cluster mode requires redesign**; current implementation cannot share state across processes.
- **Recommended roadmap**: Containerise → Interface abstraction → Pluginise → Eventually remove core dependency.

## Migration Checklist

- [ ] Identify all code paths calling `AppSupervisor.getInstance()`.
- [ ] Define `IApplicationRegistry` interface and default implementation.
- [ ] Register Supervisor in container, modify `Application` and `Gateway` dependency methods.
- [ ] Provide simplified implementation for single-app mode (`SingleAppRegistry`).
- [ ] Write integration tests for multi-app scenarios to verify consistent behaviour after containerisation.
- [ ] Implement Redis or other distributed storage for application state management.
- [ ] Update documentation to explain multi-app configuration and deployment.
- [ ] Evaluate before 2.0 GA whether to fully remove or retain as an optional plugin.

194 changes: 194 additions & 0 deletions packages/core/docs/app-supervisor-analysis.zh.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,194 @@
# AppSupervisor 分析与移除可行性评估

## 概述

`AppSupervisor` 是 TachyBase Core 内置的**多应用实例管理器**,采用单例模式,负责在同一进程内协调多个 `Application` 实例的生命周期、状态同步与错误处理。它主要服务于"多租户"或"多子应用"场景,允许一个 Gateway 根据请求路由到不同的应用实例。

## 核心职责

1. **应用注册与查找**
- `addApp(app)`: 将 Application 实例注册到 Supervisor。
- `getApp(appName)`: 按名称获取应用实例,支持延迟引导(通过 `appBootstrapper`)。
- `hasApp(appName)`: 检查应用是否已注册。
- `removeApp(appName)`: 销毁并移除应用。

2. **状态管理**
- 维护每个应用的状态:`initializing | initialized | running | commanding | stopped | error | not_found`。
- 监听应用事件(`maintaining`, `__started`, `afterStop`, `afterDestroy`)并同步状态到 Supervisor。
- 提供 `setAppStatus()` / `getAppStatus()` 供外部查询。

3. **错误追踪**
- `setAppError()` / `hasAppError()` / `clearAppError()`: 记录应用级错误并触发 `appError` 事件。

4. **运行模式控制**
- 支持 `single` 模式(通过 `STARTUP_SUBAPP` 环境变量指定单一子应用)和 `multiple` 模式。
- `blockApps`: 阻止特定应用被自动引导。

5. **引导与互斥**
- `setAppBootstrapper()`: 注册应用工厂函数,用于延迟创建应用实例。
- `bootStrapApp()`: 使用 Mutex 保证同一应用只被引导一次。

6. **心跳与活跃度**
- `touchApp()` / `lastSeenAt`: 记录应用最后访问时间,用于判断应用是否活跃。

7. **事件广播**
- 发出 `afterAppAdded`, `appStatusChanged`, `appMaintainingMessageChanged`, `appMaintainingStatusChanged`, `appError` 等事件供外部订阅。

## 使用场景

### 1. Gateway 路由多应用
- `Gateway.requestHandler()` 根据请求头或查询参数(`x-app`, `__appName`)解析目标应用名称。
- 调用 `AppSupervisor.getInstance().getApp(appName)` 获取或引导应用实例。
- 根据应用状态决定是否转发请求、返回错误或触发启动。

### 2. 多租户架构
- 每个租户对应一个独立的 `Application` 实例(可能共享或独立数据库)。
- Supervisor 管理租户应用的生命周期,避免重复创建。

### 3. 子应用隔离
- 在测试或开发环境中,通过 `STARTUP_SUBAPP` 只启动特定子应用,加快启动速度。

### 4. 状态监控与管理界面
- 管理后台可订阅 Supervisor 事件,实时展示各应用状态、错误、维护消息。

## 依赖关系

- **被依赖方**:
- `Application` 构造时自动调用 `AppSupervisor.getInstance().addApp(this)`。
- `Gateway` 在请求处理和启动流程中频繁调用 Supervisor 方法。
- `WSServer` 和 `IPCSocketServer` 通过 Supervisor 获取应用实例。
- 测试代码(`__tests__/multiple-application.test.ts`, `__tests__/gateway.test.ts`)验证多应用场景。

- **依赖项**:
- `async-mutex`: 保证应用引导的互斥性。
- `Application` 事件:监听生命周期钩子同步状态。

## 移除可行性分析

### 场景 1:单应用部署(无多租户需求)
- **可行性**:✅ **高度可行**
- **条件**:
- 应用始终只有一个 `main` 实例。
- Gateway 不需要路由到多个应用。
- **改造方案**:
- 移除 `AppSupervisor` 单例。
- `Application` 构造时不再注册到 Supervisor。
- `Gateway` 直接持有 `mainApp` 引用,不再通过 Supervisor 查找。
- 状态管理简化为 `Application` 内部属性。
- **收益**:
- 减少全局单例依赖,降低耦合。
- 简化代码路径,提升可测试性。
- 减少内存开销(不再维护应用注册表、状态映射)。

### 场景 2:多应用部署(多租户或子应用)
- **可行性**:⚠️ **需要替代方案**
- **条件**:
- 需要在同一进程内管理多个应用实例。
- Gateway 需要根据请求动态路由到不同应用。
- **改造方案**:
- 将 `AppSupervisor` 改造为容器注册的服务(非全局单例)。
- 通过 DI 容器注入到 `Gateway` 和需要多应用管理的插件中。
- 状态管理可选持久化到 Redis(支持 cluster 模式)或保持进程内。
- **收益**:
- 解除全局单例依赖,支持多实例测试。
- 更灵活的生命周期管理(可按需启用/禁用多应用能力)。
- 为 cluster 模式下的应用状态共享提供扩展点。

### 场景 3:Cluster 模式
- **可行性**:⚠️ **需要重新设计**
- **问题**:
- 当前 `AppSupervisor` 是进程内单例,无法跨进程共享状态。
- 多个 worker 进程各自维护独立的应用注册表,可能导致状态不一致。
- **改造方案**:
- 将应用状态存储到 Redis 或共享数据库。
- Supervisor 改为"状态代理",从共享存储读取应用状态。
- 应用引导和状态变更通过分布式锁或主进程协调。
- **收益**:
- 支持真正的多进程部署。
- 应用状态在所有 worker 间保持一致。

## 移除的潜在收益

1. **降低复杂度**
- 移除全局单例,减少隐式依赖。
- 简化 `Application` 构造逻辑(不再自动注册)。

2. **提升可测试性**
- 不再依赖全局状态,测试隔离更彻底。
- 可以为不同测试场景注入不同的应用管理器实现。

3. **更好的 DI 集成**
- 将应用管理能力注册到容器,符合 2.0 架构方向。
- 插件可按需依赖应用管理服务,而非强制使用全局单例。

4. **灵活的部署模式**
- 单应用场景无需引入多应用管理开销。
- 多应用场景可选择进程内或分布式实现。

## 移除的潜在风险

1. **破坏现有多租户架构**
- 如果产品依赖多应用路由,移除 Supervisor 需要提供替代方案。

2. **Gateway 重构成本**
- `Gateway.requestHandler()` 深度依赖 Supervisor,需要重写路由逻辑。

3. **状态同步复杂化**
- 当前通过 Supervisor 事件统一管理状态变更,移除后需要新的机制。

4. **测试用例失效**
- `__tests__/multiple-application.test.ts` 等测试需要重写。

## 推荐方案

### 短期(TachyBase 2.0 Alpha)
1. **保留 AppSupervisor,但改为容器服务**
- 不再使用全局单例,改为通过容器注册和解析。
- `Application` 构造时通过容器获取 Supervisor 并注册自身。
- `Gateway` 通过容器解析 Supervisor。

2. **抽象应用管理接口**
- 定义 `IApplicationRegistry` 接口,提供 `register/get/remove/getStatus` 等方法。
- `AppSupervisor` 作为默认实现,支持单应用场景下的轻量级实现(如 `SingleAppRegistry`)。

3. **配置化多应用支持**
- 通过配置项 `multiApp: boolean` 决定是否启用多应用管理。
- 单应用模式下自动使用简化实现。

### 中期(TachyBase 2.0 Beta)
1. **实现分布式应用管理**
- 提供 `RedisApplicationRegistry` 实现,支持 cluster 模式。
- 应用状态存储到 Redis,使用分布式锁协调引导。

2. **插件化 Gateway 路由**
- 将多应用路由逻辑抽取为插件(如 `@tego/plugin-multi-app-router`)。
- 核心 Gateway 只负责基础 HTTP 服务,路由策略由插件提供。

### 长期(TachyBase 2.x 稳定版)
1. **完全移除 AppSupervisor**
- 单应用场景下无需应用管理器。
- 多应用场景由专门的插件提供,核心不再内置。

2. **标准化应用生命周期协议**
- 定义跨进程的应用状态同步协议(基于 Pub/Sub 或 gRPC)。
- 支持应用实例在不同进程甚至不同机器上运行。

## 结论

- **AppSupervisor 是内置的多应用管理能力**,为多租户和子应用场景提供支持。
- **单应用场景下可以移除**,收益包括降低复杂度、提升可测试性、更好的 DI 集成。
- **多应用场景下需要替代方案**,建议先改为容器服务,再逐步插件化。
- **Cluster 模式需要重新设计**,当前实现无法跨进程共享状态。
- **推荐路线**:容器化 → 接口抽象 → 插件化 → 最终移除核心依赖。

## 迁移检查清单

- [ ] 梳理所有调用 `AppSupervisor.getInstance()` 的代码路径。
- [ ] 定义 `IApplicationRegistry` 接口及默认实现。
- [ ] 将 Supervisor 注册到容器,修改 `Application` 和 `Gateway` 的依赖方式。
- [ ] 提供单应用模式的简化实现(`SingleAppRegistry`)。
- [ ] 编写多应用场景的集成测试,验证容器化后的行为一致性。
- [ ] 实现 Redis 或其他分布式存储的应用状态管理。
- [ ] 更新文档,说明多应用配置和部署方式。
- [ ] 在 2.0 正式版前评估是否完全移除或保留为可选插件。

Loading
Loading