forked from datawhale/whale-town-end
- Add ZulipAccountsEntity, repository, and module for persistent Zulip account storage - Create ZulipAccountService in core layer for managing Zulip account lifecycle - Integrate Zulip account creation into login flow via LoginService - Add comprehensive test suite for Zulip account creation during user registration - Create quick test script for validating registered user Zulip integration - Update UsersEntity to support Zulip account associations - Update auth module to include Zulip and ZulipAccounts dependencies - Fix WebSocket connection protocol from ws:// to wss:// in API documentation - Enhance LoginCoreService to coordinate Zulip account provisioning during authentication
Zulip集成业务模块
架构重构说明
本模块已按照项目的分层架构要求进行重构,将技术实现细节移动到核心服务层,业务逻辑保留在业务层。
重构前后对比
重构前(❌ 违反架构原则)
src/business/zulip/services/
├── zulip_client.service.ts # 技术实现:API调用
├── zulip_client_pool.service.ts # 技术实现:连接池管理
├── config_manager.service.ts # 技术实现:配置管理
├── zulip_event_processor.service.ts # 技术实现:事件处理
├── session_manager.service.ts # ✅ 业务逻辑:会话管理
└── message_filter.service.ts # ✅ 业务逻辑:消息过滤
重构后(✅ 符合架构原则)
# 业务逻辑层
src/business/zulip/
├── zulip.service.ts # 业务协调服务
├── zulip_websocket.gateway.ts # WebSocket业务网关
└── services/
├── session_manager.service.ts # 会话业务逻辑
└── message_filter.service.ts # 消息过滤业务规则
# 核心服务层
src/core/zulip/
├── interfaces/
│ └── zulip-core.interfaces.ts # 核心服务接口定义
├── services/
│ ├── zulip_client.service.ts # Zulip API封装
│ ├── zulip_client_pool.service.ts # 客户端池管理
│ ├── config_manager.service.ts # 配置管理
│ ├── zulip_event_processor.service.ts # 事件处理
│ └── ... # 其他技术服务
└── zulip-core.module.ts # 核心服务模块
架构优势
1. 单一职责原则
- 业务层:只关注游戏相关的业务逻辑和规则
- 核心层:只处理技术实现和第三方API调用
2. 依赖注入和接口抽象
// 业务层通过接口依赖核心服务
constructor(
@Inject('ZULIP_CLIENT_POOL_SERVICE')
private readonly zulipClientPool: IZulipClientPoolService,
@Inject('ZULIP_CONFIG_SERVICE')
private readonly configManager: IZulipConfigService,
) {}
3. 易于测试和维护
- 业务逻辑可以独立测试,不依赖具体的技术实现
- 核心服务可以独立替换,不影响业务逻辑
- 接口定义清晰,便于理解和维护
服务职责划分
业务逻辑层服务
| 服务 | 职责 | 业务价值 |
|---|---|---|
ZulipService |
游戏登录/登出业务流程协调 | 处理玩家生命周期管理 |
SessionManagerService |
游戏会话状态和上下文管理 | 维护玩家位置和聊天上下文 |
MessageFilterService |
消息过滤和业务规则控制 | 实现内容审核和权限验证 |
ZulipWebSocketGateway |
WebSocket业务协议处理 | 游戏协议转换和路由 |
核心服务层服务
| 服务 | 职责 | 技术价值 |
|---|---|---|
ZulipClientService |
Zulip REST API封装 | 第三方API调用抽象 |
ZulipClientPoolService |
客户端连接池管理 | 资源管理和性能优化 |
ConfigManagerService |
配置文件管理和热重载 | 系统配置和运维支持 |
ZulipEventProcessorService |
事件队列处理和消息转换 | 异步消息处理机制 |
使用示例
业务层调用核心服务
@Injectable()
export class ZulipService {
constructor(
@Inject('ZULIP_CLIENT_POOL_SERVICE')
private readonly zulipClientPool: IZulipClientPoolService,
) {}
async sendChatMessage(request: ChatMessageRequest): Promise<ChatMessageResponse> {
// 业务逻辑:验证和处理
const session = await this.sessionManager.getSession(request.socketId);
const context = await this.sessionManager.injectContext(request.socketId);
// 调用核心服务:技术实现
const result = await this.zulipClientPool.sendMessage(
session.userId,
context.stream,
context.topic,
request.content,
);
return { success: result.success, messageId: result.messageId };
}
}
迁移指南
如果你的代码中直接导入了已移动的服务,请按以下方式更新:
更新导入路径
// ❌ 旧的导入方式
import { ZulipClientPoolService } from './services/zulip_client_pool.service';
// ✅ 新的导入方式(通过依赖注入)
import { IZulipClientPoolService } from '../../core/zulip/interfaces/zulip-core.interfaces';
constructor(
@Inject('ZULIP_CLIENT_POOL_SERVICE')
private readonly zulipClientPool: IZulipClientPoolService,
) {}
更新模块导入
// ✅ 业务模块自动导入核心模块
@Module({
imports: [
ZulipCoreModule, // 自动提供所有核心服务
// ...
],
})
export class ZulipModule {}
测试策略
业务逻辑测试
// 使用Mock核心服务测试业务逻辑
const mockZulipClientPool: IZulipClientPoolService = {
sendMessage: jest.fn().mockResolvedValue({ success: true }),
// ...
};
const module = await Test.createTestingModule({
providers: [
ZulipService,
{ provide: 'ZULIP_CLIENT_POOL_SERVICE', useValue: mockZulipClientPool },
],
}).compile();
核心服务测试
// 独立测试技术实现
describe('ZulipClientService', () => {
it('should call Zulip API correctly', async () => {
// 测试API调用逻辑
});
});
这种架构设计确保了业务逻辑与技术实现的清晰分离,提高了代码的可维护性和可测试性。