feat: 完成PHP到NestJS的100%功能迁移

- 迁移25个模块,包含95个控制器和160个服务
- 新增验证码管理、登录配置、云编译等模块
- 完善认证授权、会员管理、支付系统等核心功能
- 实现完整的队列系统、配置管理、监控体系
- 确保100%功能对齐和命名一致性
- 支持生产环境部署
This commit is contained in:
万物街
2025-09-10 08:04:28 +08:00
parent a2d6a47601
commit 7a20a0c50a
551 changed files with 35628 additions and 2025 deletions

View File

@@ -22,8 +22,11 @@ describe('Queue System (e2e)', () => {
await app.init();
testService = moduleFixture.get<TestService>(TestService);
unifiedQueueService = moduleFixture.get<UnifiedQueueService>(UnifiedQueueService);
databaseQueueProvider = moduleFixture.get<DatabaseQueueProvider>(DatabaseQueueProvider);
unifiedQueueService =
moduleFixture.get<UnifiedQueueService>(UnifiedQueueService);
databaseQueueProvider = moduleFixture.get<DatabaseQueueProvider>(
DatabaseQueueProvider,
);
});
afterAll(async () => {
@@ -92,7 +95,7 @@ describe('Queue System (e2e)', () => {
it('should process task from queue', async () => {
let processedData: any = null;
await unifiedQueueService.processTask('test-queue', async (job: any) => {
processedData = job.data;
return { success: true };
@@ -105,8 +108,8 @@ describe('Queue System (e2e)', () => {
});
// Wait a bit for processing
await new Promise(resolve => setTimeout(resolve, 1000));
await new Promise((resolve) => setTimeout(resolve, 1000));
expect(processedData).toBeDefined();
});
@@ -123,7 +126,9 @@ describe('Queue System (e2e)', () => {
data: { test: 'event-data' },
};
await expect(unifiedQueueService.publishEvent(event)).resolves.not.toThrow();
await expect(
unifiedQueueService.publishEvent(event),
).resolves.not.toThrow();
});
});
@@ -143,7 +148,12 @@ describe('Queue System (e2e)', () => {
},
};
const result = await databaseQueueProvider.add('test-db-queue', jobData.type, jobData.payload, jobData.options);
const result = await databaseQueueProvider.add(
'test-db-queue',
jobData.type,
jobData.payload,
jobData.options,
);
expect(result).toBeDefined();
});
@@ -176,7 +186,7 @@ describe('Queue System (e2e)', () => {
it('should handle complete queue workflow', async () => {
// Test the complete workflow: add task -> process task -> publish event
const taskData = { workflow: 'test', step: 1 };
// Add task
const taskResult = await unifiedQueueService.addTask('workflow-queue', {
data: taskData,
@@ -185,25 +195,28 @@ describe('Queue System (e2e)', () => {
expect(taskResult).toBeDefined();
// Process task and publish event
await unifiedQueueService.processTask('workflow-queue', async (job: any) => {
const event = {
eventType: 'workflow.completed',
aggregateId: 'workflow-123',
aggregateType: 'Workflow',
version: '1.0',
occurredAt: new Date().toISOString(),
tenantId: 'tenant-1',
idempotencyKey: 'workflow-key-123',
traceId: 'workflow-trace-123',
data: job.data,
};
await unifiedQueueService.processTask(
'workflow-queue',
async (job: any) => {
const event = {
eventType: 'workflow.completed',
aggregateId: 'workflow-123',
aggregateType: 'Workflow',
version: '1.0',
occurredAt: new Date().toISOString(),
tenantId: 'tenant-1',
idempotencyKey: 'workflow-key-123',
traceId: 'workflow-trace-123',
data: job.data,
};
await unifiedQueueService.publishEvent(event);
return { success: true, processed: job.data };
});
await unifiedQueueService.publishEvent(event);
return { success: true, processed: job.data };
},
);
// Wait for processing
await new Promise(resolve => setTimeout(resolve, 1000));
await new Promise((resolve) => setTimeout(resolve, 1000));
});
it('should handle error scenarios gracefully', async () => {
@@ -223,10 +236,10 @@ describe('Queue System (e2e)', () => {
});
// Wait for processing attempt
await new Promise(resolve => setTimeout(resolve, 1000));
await new Promise((resolve) => setTimeout(resolve, 1000));
// The test passes if no unhandled errors are thrown
expect(true).toBe(true);
});
});
});
});

View File

@@ -6,7 +6,10 @@ import { getRepositoryToken } from '@nestjs/typeorm';
import { Repository } from 'typeorm';
import { JobEntity } from '../../src/core/queue/entities/job.entity';
import { EventEntity } from '../../src/core/queue/entities/event.entity';
import { TASK_QUEUE_PROVIDER, EVENT_BUS_PROVIDER } from '../../src/core/interfaces/queue.interface';
import {
TASK_QUEUE_PROVIDER,
EVENT_BUS_PROVIDER,
} from '../../src/core/interfaces/queue.interface';
describe('Queue System Unit Tests', () => {
let unifiedQueueService: UnifiedQueueService;
@@ -69,7 +72,9 @@ describe('Queue System Unit Tests', () => {
}).compile();
unifiedQueueService = module.get<UnifiedQueueService>(UnifiedQueueService);
databaseQueueProvider = module.get<DatabaseQueueProvider>(DatabaseQueueProvider);
databaseQueueProvider = module.get<DatabaseQueueProvider>(
DatabaseQueueProvider,
);
});
describe('UnifiedQueueService', () => {
@@ -170,11 +175,16 @@ describe('Queue System Unit Tests', () => {
mockJobRepository.create.mockReturnValue(mockJob as any);
mockJobRepository.save.mockResolvedValue(mockJob as any);
const result = await databaseQueueProvider.add('test-queue', 'test-job', { test: 'data' }, {
priority: 1,
delay: 0,
attempts: 3,
});
const result = await databaseQueueProvider.add(
'test-queue',
'test-job',
{ test: 'data' },
{
priority: 1,
delay: 0,
attempts: 3,
},
);
expect(mockJobRepository.create).toHaveBeenCalled();
expect(mockJobRepository.save).toHaveBeenCalled();
@@ -227,14 +237,21 @@ describe('Queue System Unit Tests', () => {
describe('Error Handling', () => {
it('should handle database connection errors gracefully', async () => {
mockJobRepository.save.mockRejectedValue(new Error('Database connection failed'));
mockJobRepository.save.mockRejectedValue(
new Error('Database connection failed'),
);
try {
await databaseQueueProvider.add('test-queue', 'test-job', { test: 'data' }, {
priority: 1,
delay: 0,
attempts: 3,
});
await databaseQueueProvider.add(
'test-queue',
'test-job',
{ test: 'data' },
{
priority: 1,
delay: 0,
attempts: 3,
},
);
} catch (error) {
expect(error).toBeInstanceOf(Error);
expect(error.message).toBe('Database connection failed');
@@ -257,7 +274,7 @@ describe('Queue System Unit Tests', () => {
expect(invalidEvent.version).toBeDefined();
expect(invalidEvent.occurredAt).toBeDefined();
expect(invalidEvent.data).toBeDefined();
// These should be undefined, indicating invalid event
expect((invalidEvent as any).aggregateId).toBeUndefined();
expect((invalidEvent as any).aggregateType).toBeUndefined();
@@ -281,7 +298,7 @@ describe('Queue System Unit Tests', () => {
describe('Performance and Scalability', () => {
it('should handle multiple concurrent operations', async () => {
const operations = [];
// Simulate multiple concurrent task additions
for (let i = 0; i < 10; i++) {
mockJobRepository.save.mockResolvedValueOnce({
@@ -293,11 +310,16 @@ describe('Queue System Unit Tests', () => {
} as any);
operations.push(
databaseQueueProvider.add('concurrent-queue', 'concurrent-job', { index: i }, {
priority: 1,
delay: 0,
attempts: 3,
})
databaseQueueProvider.add(
'concurrent-queue',
'concurrent-job',
{ index: i },
{
priority: 1,
delay: 0,
attempts: 3,
},
),
);
}
@@ -308,7 +330,7 @@ describe('Queue System Unit Tests', () => {
it('should handle batch event publishing', async () => {
const events = [];
for (let i = 0; i < 5; i++) {
events.push({
eventType: 'batch.event',
@@ -331,10 +353,12 @@ describe('Queue System Unit Tests', () => {
}
// Test batch publishing
const publishPromises = events.map(event => databaseQueueProvider.publish(event));
const publishPromises = events.map((event) =>
databaseQueueProvider.publish(event),
);
await Promise.all(publishPromises);
expect(mockEventRepository.save).toHaveBeenCalledTimes(5);
});
});
});
});