llm-content-creator 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +309 -0
- package/dist/application/workflow/SyncExecutor.d.ts +75 -0
- package/dist/application/workflow/SyncExecutor.d.ts.map +1 -0
- package/dist/application/workflow/SyncExecutor.js +370 -0
- package/dist/application/workflow/SyncExecutor.js.map +1 -0
- package/dist/application/workflow/types.d.ts +46 -0
- package/dist/application/workflow/types.d.ts.map +1 -0
- package/dist/application/workflow/types.js +7 -0
- package/dist/application/workflow/types.js.map +1 -0
- package/dist/config/index.d.ts +173 -0
- package/dist/config/index.d.ts.map +1 -0
- package/dist/config/index.js +288 -0
- package/dist/config/index.js.map +1 -0
- package/dist/domain/entities/QualityCheck.d.ts +181 -0
- package/dist/domain/entities/QualityCheck.d.ts.map +1 -0
- package/dist/domain/entities/QualityCheck.js +39 -0
- package/dist/domain/entities/QualityCheck.js.map +1 -0
- package/dist/domain/entities/Result.d.ts +103 -0
- package/dist/domain/entities/Result.d.ts.map +1 -0
- package/dist/domain/entities/Result.js +15 -0
- package/dist/domain/entities/Result.js.map +1 -0
- package/dist/domain/entities/Task.d.ts +130 -0
- package/dist/domain/entities/Task.d.ts.map +1 -0
- package/dist/domain/entities/Task.js +64 -0
- package/dist/domain/entities/Task.js.map +1 -0
- package/dist/domain/entities/TaskStep.d.ts +160 -0
- package/dist/domain/entities/TaskStep.d.ts.map +1 -0
- package/dist/domain/entities/TaskStep.js +30 -0
- package/dist/domain/entities/TaskStep.js.map +1 -0
- package/dist/domain/entities/TokenUsage.d.ts +70 -0
- package/dist/domain/entities/TokenUsage.d.ts.map +1 -0
- package/dist/domain/entities/TokenUsage.js +42 -0
- package/dist/domain/entities/TokenUsage.js.map +1 -0
- package/dist/domain/entities/index.d.ts +11 -0
- package/dist/domain/entities/index.d.ts.map +1 -0
- package/dist/domain/entities/index.js +16 -0
- package/dist/domain/entities/index.js.map +1 -0
- package/dist/domain/repositories/QualityCheckRepository.d.ts +49 -0
- package/dist/domain/repositories/QualityCheckRepository.d.ts.map +1 -0
- package/dist/domain/repositories/QualityCheckRepository.js +5 -0
- package/dist/domain/repositories/QualityCheckRepository.js.map +1 -0
- package/dist/domain/repositories/ResultRepository.d.ts +43 -0
- package/dist/domain/repositories/ResultRepository.d.ts.map +1 -0
- package/dist/domain/repositories/ResultRepository.js +5 -0
- package/dist/domain/repositories/ResultRepository.js.map +1 -0
- package/dist/domain/repositories/TaskRepository.d.ts +240 -0
- package/dist/domain/repositories/TaskRepository.d.ts.map +1 -0
- package/dist/domain/repositories/TaskRepository.js +7 -0
- package/dist/domain/repositories/TaskRepository.js.map +1 -0
- package/dist/domain/workflow/CheckpointManager.d.ts +94 -0
- package/dist/domain/workflow/CheckpointManager.d.ts.map +1 -0
- package/dist/domain/workflow/CheckpointManager.js +224 -0
- package/dist/domain/workflow/CheckpointManager.js.map +1 -0
- package/dist/domain/workflow/ContentCreatorGraph.d.ts +17 -0
- package/dist/domain/workflow/ContentCreatorGraph.d.ts.map +1 -0
- package/dist/domain/workflow/ContentCreatorGraph.js +381 -0
- package/dist/domain/workflow/ContentCreatorGraph.js.map +1 -0
- package/dist/domain/workflow/State.d.ts +172 -0
- package/dist/domain/workflow/State.d.ts.map +1 -0
- package/dist/domain/workflow/State.js +184 -0
- package/dist/domain/workflow/State.js.map +1 -0
- package/dist/domain/workflow/index.d.ts +11 -0
- package/dist/domain/workflow/index.d.ts.map +1 -0
- package/dist/domain/workflow/index.js +15 -0
- package/dist/domain/workflow/index.js.map +1 -0
- package/dist/domain/workflow/nodes/BaseNode.d.ts +134 -0
- package/dist/domain/workflow/nodes/BaseNode.d.ts.map +1 -0
- package/dist/domain/workflow/nodes/BaseNode.js +253 -0
- package/dist/domain/workflow/nodes/BaseNode.js.map +1 -0
- package/dist/domain/workflow/nodes/CheckImageNode.d.ts +43 -0
- package/dist/domain/workflow/nodes/CheckImageNode.d.ts.map +1 -0
- package/dist/domain/workflow/nodes/CheckImageNode.js +254 -0
- package/dist/domain/workflow/nodes/CheckImageNode.js.map +1 -0
- package/dist/domain/workflow/nodes/CheckTextNode.d.ts +66 -0
- package/dist/domain/workflow/nodes/CheckTextNode.d.ts.map +1 -0
- package/dist/domain/workflow/nodes/CheckTextNode.js +530 -0
- package/dist/domain/workflow/nodes/CheckTextNode.js.map +1 -0
- package/dist/domain/workflow/nodes/GenerateImageNode.d.ts +44 -0
- package/dist/domain/workflow/nodes/GenerateImageNode.d.ts.map +1 -0
- package/dist/domain/workflow/nodes/GenerateImageNode.js +272 -0
- package/dist/domain/workflow/nodes/GenerateImageNode.js.map +1 -0
- package/dist/domain/workflow/nodes/OrganizeNode.d.ts +49 -0
- package/dist/domain/workflow/nodes/OrganizeNode.d.ts.map +1 -0
- package/dist/domain/workflow/nodes/OrganizeNode.js +241 -0
- package/dist/domain/workflow/nodes/OrganizeNode.js.map +1 -0
- package/dist/domain/workflow/nodes/SearchNode.d.ts +48 -0
- package/dist/domain/workflow/nodes/SearchNode.d.ts.map +1 -0
- package/dist/domain/workflow/nodes/SearchNode.js +151 -0
- package/dist/domain/workflow/nodes/SearchNode.js.map +1 -0
- package/dist/domain/workflow/nodes/WriteNode.d.ts +68 -0
- package/dist/domain/workflow/nodes/WriteNode.d.ts.map +1 -0
- package/dist/domain/workflow/nodes/WriteNode.js +431 -0
- package/dist/domain/workflow/nodes/WriteNode.js.map +1 -0
- package/dist/domain/workflow/nodes/config/index.js +287 -0
- package/dist/domain/workflow/nodes/domain/entities/Task.js +68 -0
- package/dist/domain/workflow/nodes/domain/workflow/State.js +200 -0
- package/dist/domain/workflow/nodes/domain/workflow/nodes/BaseNode.js +328 -0
- package/dist/domain/workflow/nodes/domain/workflow/nodes/CheckTextNode.js +500 -0
- package/dist/domain/workflow/nodes/index.d.ts +13 -0
- package/dist/domain/workflow/nodes/index.d.ts.map +1 -0
- package/dist/domain/workflow/nodes/index.js +13 -0
- package/dist/domain/workflow/nodes/index.js.map +1 -0
- package/dist/domain/workflow/nodes/infrastructure/logging/logger.js +275 -0
- package/dist/domain/workflow/nodes/services/llm/EnhancedLLMService.js +559 -0
- package/dist/index.d.ts +24 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +34 -0
- package/dist/index.js.map +1 -0
- package/dist/infrastructure/cache/CacheService.d.ts +139 -0
- package/dist/infrastructure/cache/CacheService.d.ts.map +1 -0
- package/dist/infrastructure/cache/CacheService.js +419 -0
- package/dist/infrastructure/cache/CacheService.js.map +1 -0
- package/dist/infrastructure/cache/index.d.ts +5 -0
- package/dist/infrastructure/cache/index.d.ts.map +1 -0
- package/dist/infrastructure/cache/index.js +6 -0
- package/dist/infrastructure/cache/index.js.map +1 -0
- package/dist/infrastructure/database/BaseRepository.d.ts +98 -0
- package/dist/infrastructure/database/BaseRepository.d.ts.map +1 -0
- package/dist/infrastructure/database/BaseRepository.js +178 -0
- package/dist/infrastructure/database/BaseRepository.js.map +1 -0
- package/dist/infrastructure/database/MemoryTaskRepository.d.ts +77 -0
- package/dist/infrastructure/database/MemoryTaskRepository.d.ts.map +1 -0
- package/dist/infrastructure/database/MemoryTaskRepository.js +309 -0
- package/dist/infrastructure/database/MemoryTaskRepository.js.map +1 -0
- package/dist/infrastructure/database/PostgresQualityCheckRepository.d.ts +36 -0
- package/dist/infrastructure/database/PostgresQualityCheckRepository.d.ts.map +1 -0
- package/dist/infrastructure/database/PostgresQualityCheckRepository.js +89 -0
- package/dist/infrastructure/database/PostgresQualityCheckRepository.js.map +1 -0
- package/dist/infrastructure/database/PostgresTaskRepository.d.ts +94 -0
- package/dist/infrastructure/database/PostgresTaskRepository.d.ts.map +1 -0
- package/dist/infrastructure/database/PostgresTaskRepository.js +364 -0
- package/dist/infrastructure/database/PostgresTaskRepository.js.map +1 -0
- package/dist/infrastructure/database/ResultRepository.d.ts +41 -0
- package/dist/infrastructure/database/ResultRepository.d.ts.map +1 -0
- package/dist/infrastructure/database/ResultRepository.js +86 -0
- package/dist/infrastructure/database/ResultRepository.js.map +1 -0
- package/dist/infrastructure/database/SQLiteTaskRepository.d.ts +101 -0
- package/dist/infrastructure/database/SQLiteTaskRepository.d.ts.map +1 -0
- package/dist/infrastructure/database/SQLiteTaskRepository.js +548 -0
- package/dist/infrastructure/database/SQLiteTaskRepository.js.map +1 -0
- package/dist/infrastructure/database/index.d.ts +32 -0
- package/dist/infrastructure/database/index.d.ts.map +1 -0
- package/dist/infrastructure/database/index.js +72 -0
- package/dist/infrastructure/database/index.js.map +1 -0
- package/dist/infrastructure/logging/logger.d.ts +69 -0
- package/dist/infrastructure/logging/logger.d.ts.map +1 -0
- package/dist/infrastructure/logging/logger.js +169 -0
- package/dist/infrastructure/logging/logger.js.map +1 -0
- package/dist/infrastructure/monitoring/LoggingService.d.ts +109 -0
- package/dist/infrastructure/monitoring/LoggingService.d.ts.map +1 -0
- package/dist/infrastructure/monitoring/LoggingService.js +198 -0
- package/dist/infrastructure/monitoring/LoggingService.js.map +1 -0
- package/dist/infrastructure/monitoring/MetricsService.d.ts +112 -0
- package/dist/infrastructure/monitoring/MetricsService.d.ts.map +1 -0
- package/dist/infrastructure/monitoring/MetricsService.js +362 -0
- package/dist/infrastructure/monitoring/MetricsService.js.map +1 -0
- package/dist/infrastructure/monitoring/SentryService.d.ts +108 -0
- package/dist/infrastructure/monitoring/SentryService.d.ts.map +1 -0
- package/dist/infrastructure/monitoring/SentryService.js +282 -0
- package/dist/infrastructure/monitoring/SentryService.js.map +1 -0
- package/dist/infrastructure/monitoring/index.d.ts +7 -0
- package/dist/infrastructure/monitoring/index.d.ts.map +1 -0
- package/dist/infrastructure/monitoring/index.js +10 -0
- package/dist/infrastructure/monitoring/index.js.map +1 -0
- package/dist/infrastructure/queue/TaskQueue.d.ts +110 -0
- package/dist/infrastructure/queue/TaskQueue.d.ts.map +1 -0
- package/dist/infrastructure/queue/TaskQueue.js +363 -0
- package/dist/infrastructure/queue/TaskQueue.js.map +1 -0
- package/dist/infrastructure/queue/index.d.ts +5 -0
- package/dist/infrastructure/queue/index.d.ts.map +1 -0
- package/dist/infrastructure/queue/index.js +5 -0
- package/dist/infrastructure/queue/index.js.map +1 -0
- package/dist/infrastructure/redis/connection.d.ts +61 -0
- package/dist/infrastructure/redis/connection.d.ts.map +1 -0
- package/dist/infrastructure/redis/connection.js +184 -0
- package/dist/infrastructure/redis/connection.js.map +1 -0
- package/dist/infrastructure/redis/index.d.ts +5 -0
- package/dist/infrastructure/redis/index.d.ts.map +1 -0
- package/dist/infrastructure/redis/index.js +5 -0
- package/dist/infrastructure/redis/index.js.map +1 -0
- package/dist/infrastructure/security/ApiKeyService.d.ts +103 -0
- package/dist/infrastructure/security/ApiKeyService.d.ts.map +1 -0
- package/dist/infrastructure/security/ApiKeyService.js +250 -0
- package/dist/infrastructure/security/ApiKeyService.js.map +1 -0
- package/dist/infrastructure/security/QuotaService.d.ts +87 -0
- package/dist/infrastructure/security/QuotaService.d.ts.map +1 -0
- package/dist/infrastructure/security/QuotaService.js +303 -0
- package/dist/infrastructure/security/QuotaService.js.map +1 -0
- package/dist/infrastructure/security/RateLimiter.d.ts +104 -0
- package/dist/infrastructure/security/RateLimiter.d.ts.map +1 -0
- package/dist/infrastructure/security/RateLimiter.js +331 -0
- package/dist/infrastructure/security/RateLimiter.js.map +1 -0
- package/dist/infrastructure/security/index.d.ts +7 -0
- package/dist/infrastructure/security/index.d.ts.map +1 -0
- package/dist/infrastructure/security/index.js +10 -0
- package/dist/infrastructure/security/index.js.map +1 -0
- package/dist/monitoring/index.d.ts +5 -0
- package/dist/monitoring/index.d.ts.map +1 -0
- package/dist/monitoring/index.js +5 -0
- package/dist/monitoring/index.js.map +1 -0
- package/dist/monitoring/server.d.ts +14 -0
- package/dist/monitoring/server.d.ts.map +1 -0
- package/dist/monitoring/server.js +99 -0
- package/dist/monitoring/server.js.map +1 -0
- package/dist/presentation/cli/commands/cancel.d.ts +8 -0
- package/dist/presentation/cli/commands/cancel.d.ts.map +1 -0
- package/dist/presentation/cli/commands/cancel.js +57 -0
- package/dist/presentation/cli/commands/cancel.js.map +1 -0
- package/dist/presentation/cli/commands/create.d.ts +8 -0
- package/dist/presentation/cli/commands/create.d.ts.map +1 -0
- package/dist/presentation/cli/commands/create.js +368 -0
- package/dist/presentation/cli/commands/create.js.map +1 -0
- package/dist/presentation/cli/commands/result.d.ts +8 -0
- package/dist/presentation/cli/commands/result.d.ts.map +1 -0
- package/dist/presentation/cli/commands/result.js +121 -0
- package/dist/presentation/cli/commands/result.js.map +1 -0
- package/dist/presentation/cli/commands/status.d.ts +8 -0
- package/dist/presentation/cli/commands/status.d.ts.map +1 -0
- package/dist/presentation/cli/commands/status.js +92 -0
- package/dist/presentation/cli/commands/status.js.map +1 -0
- package/dist/presentation/cli/index.d.ts +8 -0
- package/dist/presentation/cli/index.d.ts.map +1 -0
- package/dist/presentation/cli/index.js +32 -0
- package/dist/presentation/cli/index.js.map +1 -0
- package/dist/presentation/cli/utils/cleanup.d.ts +14 -0
- package/dist/presentation/cli/utils/cleanup.d.ts.map +1 -0
- package/dist/presentation/cli/utils/cleanup.js +62 -0
- package/dist/presentation/cli/utils/cleanup.js.map +1 -0
- package/dist/presentation/cli/utils/formatter.d.ts +28 -0
- package/dist/presentation/cli/utils/formatter.d.ts.map +1 -0
- package/dist/presentation/cli/utils/formatter.js +68 -0
- package/dist/presentation/cli/utils/formatter.js.map +1 -0
- package/dist/presentation/cli.d.ts +7 -0
- package/dist/presentation/cli.d.ts.map +1 -0
- package/dist/presentation/cli.js +8 -0
- package/dist/presentation/cli.js.map +1 -0
- package/dist/presentation/monitor-cli.d.ts +8 -0
- package/dist/presentation/monitor-cli.d.ts.map +1 -0
- package/dist/presentation/monitor-cli.js +44 -0
- package/dist/presentation/monitor-cli.js.map +1 -0
- package/dist/presentation/worker-cli.d.ts +8 -0
- package/dist/presentation/worker-cli.d.ts.map +1 -0
- package/dist/presentation/worker-cli.js +51 -0
- package/dist/presentation/worker-cli.js.map +1 -0
- package/dist/schedulers/TaskScheduler.d.ts +99 -0
- package/dist/schedulers/TaskScheduler.d.ts.map +1 -0
- package/dist/schedulers/TaskScheduler.js +233 -0
- package/dist/schedulers/TaskScheduler.js.map +1 -0
- package/dist/schedulers/index.d.ts +5 -0
- package/dist/schedulers/index.d.ts.map +1 -0
- package/dist/schedulers/index.js +5 -0
- package/dist/schedulers/index.js.map +1 -0
- package/dist/services/image/ImageService.d.ts +68 -0
- package/dist/services/image/ImageService.d.ts.map +1 -0
- package/dist/services/image/ImageService.js +166 -0
- package/dist/services/image/ImageService.js.map +1 -0
- package/dist/services/index.d.ts +8 -0
- package/dist/services/index.d.ts.map +1 -0
- package/dist/services/index.js +12 -0
- package/dist/services/index.js.map +1 -0
- package/dist/services/llm/EnhancedLLMService.d.ts +148 -0
- package/dist/services/llm/EnhancedLLMService.d.ts.map +1 -0
- package/dist/services/llm/EnhancedLLMService.js +425 -0
- package/dist/services/llm/EnhancedLLMService.js.map +1 -0
- package/dist/services/llm/LLMService.d.ts +103 -0
- package/dist/services/llm/LLMService.d.ts.map +1 -0
- package/dist/services/llm/LLMService.js +212 -0
- package/dist/services/llm/LLMService.js.map +1 -0
- package/dist/services/quality/HardRuleChecker.d.ts +143 -0
- package/dist/services/quality/HardRuleChecker.d.ts.map +1 -0
- package/dist/services/quality/HardRuleChecker.js +353 -0
- package/dist/services/quality/HardRuleChecker.js.map +1 -0
- package/dist/services/quality/LLMEvaluator.d.ts +105 -0
- package/dist/services/quality/LLMEvaluator.d.ts.map +1 -0
- package/dist/services/quality/LLMEvaluator.js +312 -0
- package/dist/services/quality/LLMEvaluator.js.map +1 -0
- package/dist/services/quality/QualityCheckService.d.ts +112 -0
- package/dist/services/quality/QualityCheckService.d.ts.map +1 -0
- package/dist/services/quality/QualityCheckService.js +342 -0
- package/dist/services/quality/QualityCheckService.js.map +1 -0
- package/dist/services/quality/QualityService.d.ts +75 -0
- package/dist/services/quality/QualityService.d.ts.map +1 -0
- package/dist/services/quality/QualityService.js +360 -0
- package/dist/services/quality/QualityService.js.map +1 -0
- package/dist/services/quality/index.d.ts +7 -0
- package/dist/services/quality/index.d.ts.map +1 -0
- package/dist/services/quality/index.js +10 -0
- package/dist/services/quality/index.js.map +1 -0
- package/dist/services/search/SearchService.d.ts +79 -0
- package/dist/services/search/SearchService.d.ts.map +1 -0
- package/dist/services/search/SearchService.js +193 -0
- package/dist/services/search/SearchService.js.map +1 -0
- package/dist/workers/TaskWorker.d.ts +61 -0
- package/dist/workers/TaskWorker.d.ts.map +1 -0
- package/dist/workers/TaskWorker.js +256 -0
- package/dist/workers/TaskWorker.js.map +1 -0
- package/dist/workers/index.d.ts +5 -0
- package/dist/workers/index.d.ts.map +1 -0
- package/dist/workers/index.js +5 -0
- package/dist/workers/index.js.map +1 -0
- package/docs/DOCUMENTATION-ANALYSIS.md +190 -0
- package/docs/README.md +145 -0
- package/docs/SOURCE-CODE-ANALYSIS.md +1107 -0
- package/docs/architecture-complete.md +5524 -0
- package/docs/archive/implementation/implementation-analysis/README.md +244 -0
- package/docs/archive/implementation/implementation-analysis/implementation-analysis-context.md +483 -0
- package/docs/archive/implementation/implementation-analysis/implementation-analysis-plan.md +1242 -0
- package/docs/archive/implementation/implementation-analysis/implementation-analysis-tasks.md +777 -0
- package/docs/archive/phases/phase-1/phase-1-completion-summary.md +284 -0
- package/docs/archive/phases/phase-1/phase-1-implementation-guide.md +1380 -0
- package/docs/archive/phases/phase-2/phase-2a/phase-2a-completion-summary.md +443 -0
- package/docs/archive/phases/phase-2/phase-2b/phase-2b-completion-report.md +430 -0
- package/docs/archive/phases/phase-2/phase-2b/phase-2b-completion-summary.md +592 -0
- package/docs/archive/phases/phase-2/phase-2b/phase-2b-final-summary.md +371 -0
- package/docs/archive/phases/phase-2/phase-2b/phase-2b-preparation-complete.md +343 -0
- package/docs/archive/phases/phase-2/phase-2b/phase-2b-preparation.md +945 -0
- package/docs/archive/phases/phase-2/phase-2b/phase-2b-progress-update.md +366 -0
- package/docs/archive/phases/phase-3/phase-3-completion-summary.md +354 -0
- package/docs/archive/phases/phase-3/phase-3-development-plan.md +878 -0
- package/docs/archive/phases/phase-3/phase-3-quick-start.md +324 -0
- package/docs/archive/phases/phase-4/phase-4-completion-summary.md +708 -0
- package/docs/archive/phases/phase-4/phase-4-development-plan.md +740 -0
- package/docs/archive/phases/phase-4/phase-4-quick-start.md +632 -0
- package/docs/archive/phases/phase-4/phase-4-session-3-security-testing.md +484 -0
- package/docs/archive/phases/phase-4/phase-4-session-4-unit-tests.md +550 -0
- package/docs/archive/phases/phase-4/phase-4-session-5-security-tests.md +564 -0
- package/docs/archive/phases/phase-4/phase-4-session-6-cache-integration.md +456 -0
- package/docs/archive/phases/phase-4/phase-4-session-7-test-fixes.md +348 -0
- package/docs/archive/phases/phase-4/phase-4-session-8-taskqueue-fixes.md +323 -0
- package/docs/archive/phases/phase-4/phase-4-session-summary-continued.md +373 -0
- package/docs/archive/phases/phase-4/phase-4-session-summary.md +595 -0
- package/docs/archive/reports/progress-reports/PHASE_0_PROGRESS.md +242 -0
- package/docs/archive/reports/progress-reports/PHASE_0_SUMMARY.md +262 -0
- package/docs/archive/reports/progress-reports/PHASE_1_2_ISSUES.md +399 -0
- package/docs/archive/reports/progress-reports/PHASE_1_PROGRESS.md +388 -0
- package/docs/archive/reports/progress-reports/PHASE_3_PREPARATION.md +574 -0
- package/docs/archive/reports/progress-reports/current-progress-update.md +294 -0
- package/docs/archive/reports/progress-reports/final-summary.md +215 -0
- package/docs/archive/reports/progress-reports/implementation-summary.md +287 -0
- package/docs/archive/reports/progress-reports/project-progress-report.md +440 -0
- package/docs/archive/reports/progress-reports/project-progress.md +386 -0
- package/docs/archive/reports/test-reports/TEST-COVERAGE-REPORT.md +441 -0
- package/docs/archive/reports/test-reports/e2e-test-report.md +293 -0
- package/docs/archive/reports/test-reports/final-test-report.md +367 -0
- package/docs/archive/reports/test-reports/real-env-test-report.md +391 -0
- package/docs/archive/reports/test-reports/test-completion-summary.md +356 -0
- package/docs/archive/reports/test-reports/test-report.md +371 -0
- package/docs/archive/sessions/session-2-summary.md +429 -0
- package/docs/archive/sessions/session-3-summary.md +395 -0
- package/docs/archive/sessions/session-summary.md +370 -0
- package/docs/config-system-update.md +239 -0
- package/docs/database-refactoring-PLAN.md +199 -0
- package/docs/database-refactoring-SUMMARY.md +384 -0
- package/docs/quality-check-architecture.md +1030 -0
- package/docs/quick-start.md +388 -0
- package/docs/references/bullmq-quick-reference.md +525 -0
- package/docs/references/monitoring-optimization-guide.md +871 -0
- package/docs/references/performance-optimization-guide.md +933 -0
- package/docs/storage-guide.md +612 -0
- package/docs/test-implementation-PLAN.md +223 -0
- package/docs/test-implementation-SUMMARY.md +194 -0
- package/docs/user-guide.md +719 -0
- package/docs/workflow-architecture.md +549 -0
- package/package.json +126 -0
- package/src/application/workflow/SyncExecutor.ts +444 -0
- package/src/application/workflow/types.ts +57 -0
- package/src/config/index.ts +352 -0
- package/src/domain/entities/QualityCheck.ts +202 -0
- package/src/domain/entities/Result.ts +130 -0
- package/src/domain/entities/Task.ts +178 -0
- package/src/domain/entities/TaskStep.ts +188 -0
- package/src/domain/entities/TokenUsage.ts +119 -0
- package/src/domain/entities/index.ts +20 -0
- package/src/domain/repositories/QualityCheckRepository.ts +52 -0
- package/src/domain/repositories/ResultRepository.ts +47 -0
- package/src/domain/repositories/TaskRepository.ts +271 -0
- package/src/domain/workflow/CheckpointManager.ts +283 -0
- package/src/domain/workflow/ContentCreatorGraph.ts +446 -0
- package/src/domain/workflow/State.ts +321 -0
- package/src/domain/workflow/index.ts +18 -0
- package/src/domain/workflow/nodes/BaseNode.ts +325 -0
- package/src/domain/workflow/nodes/CheckImageNode.ts +325 -0
- package/src/domain/workflow/nodes/CheckTextNode.ts +709 -0
- package/src/domain/workflow/nodes/GenerateImageNode.ts +342 -0
- package/src/domain/workflow/nodes/OrganizeNode.ts +304 -0
- package/src/domain/workflow/nodes/SearchNode.ts +192 -0
- package/src/domain/workflow/nodes/WriteNode.ts +505 -0
- package/src/domain/workflow/nodes/index.ts +13 -0
- package/src/index.ts +43 -0
- package/src/infrastructure/cache/CacheService.ts +483 -0
- package/src/infrastructure/cache/index.ts +6 -0
- package/src/infrastructure/database/BaseRepository.ts +214 -0
- package/src/infrastructure/database/MemoryTaskRepository.ts +377 -0
- package/src/infrastructure/database/PostgresQualityCheckRepository.ts +115 -0
- package/src/infrastructure/database/PostgresTaskRepository.ts +424 -0
- package/src/infrastructure/database/ResultRepository.ts +113 -0
- package/src/infrastructure/database/SQLiteTaskRepository.ts +651 -0
- package/src/infrastructure/database/index.ts +83 -0
- package/src/infrastructure/logging/logger.ts +231 -0
- package/src/infrastructure/monitoring/LoggingService.ts +292 -0
- package/src/infrastructure/monitoring/MetricsService.ts +468 -0
- package/src/infrastructure/monitoring/SentryService.ts +345 -0
- package/src/infrastructure/monitoring/index.ts +12 -0
- package/src/infrastructure/queue/TaskQueue.ts +429 -0
- package/src/infrastructure/queue/index.ts +5 -0
- package/src/infrastructure/redis/connection.ts +215 -0
- package/src/infrastructure/redis/index.ts +5 -0
- package/src/infrastructure/security/ApiKeyService.ts +340 -0
- package/src/infrastructure/security/QuotaService.ts +411 -0
- package/src/infrastructure/security/RateLimiter.ts +417 -0
- package/src/infrastructure/security/index.ts +12 -0
- package/src/monitoring/index.ts +5 -0
- package/src/monitoring/server.ts +109 -0
- package/src/presentation/cli/commands/cancel.ts +64 -0
- package/src/presentation/cli/commands/create.ts +400 -0
- package/src/presentation/cli/commands/result.ts +136 -0
- package/src/presentation/cli/commands/status.ts +102 -0
- package/src/presentation/cli/index.ts +39 -0
- package/src/presentation/cli/utils/cleanup.ts +65 -0
- package/src/presentation/cli/utils/formatter.ts +74 -0
- package/src/presentation/cli.ts +8 -0
- package/src/presentation/monitor-cli.ts +52 -0
- package/src/presentation/worker-cli.ts +62 -0
- package/src/schedulers/TaskScheduler.ts +314 -0
- package/src/schedulers/index.ts +11 -0
- package/src/services/image/ImageService.ts +221 -0
- package/src/services/index.ts +15 -0
- package/src/services/llm/EnhancedLLMService.ts +596 -0
- package/src/services/llm/LLMService.ts +310 -0
- package/src/services/quality/HardRuleChecker.ts +509 -0
- package/src/services/quality/LLMEvaluator.ts +400 -0
- package/src/services/quality/QualityCheckService.ts +473 -0
- package/src/services/quality/QualityService.ts +445 -0
- package/src/services/quality/index.ts +12 -0
- package/src/services/search/SearchService.ts +266 -0
- package/src/types/global.d.ts +17 -0
- package/src/workers/TaskWorker.ts +320 -0
- package/src/workers/index.ts +5 -0
|
@@ -0,0 +1,429 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* TaskQueue - BullMQ 任务队列
|
|
3
|
+
*
|
|
4
|
+
* 负责任务的添加、调度和管理
|
|
5
|
+
* 仅在 Redis 可用时启用
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
import { Queue } from 'bullmq';
|
|
9
|
+
import type { QueueOptions, JobsOptions } from 'bullmq';
|
|
10
|
+
import { createLogger } from '../logging/logger.js';
|
|
11
|
+
import { config } from '../../config/index.js';
|
|
12
|
+
|
|
13
|
+
const logger = createLogger('TaskQueue');
|
|
14
|
+
|
|
15
|
+
/**
|
|
16
|
+
* 任务作业数据接口
|
|
17
|
+
*/
|
|
18
|
+
export interface TaskJobData {
|
|
19
|
+
taskId: string;
|
|
20
|
+
mode: 'sync' | 'async';
|
|
21
|
+
topic: string;
|
|
22
|
+
requirements: string;
|
|
23
|
+
hardConstraints?: {
|
|
24
|
+
minWords?: number;
|
|
25
|
+
maxWords?: number;
|
|
26
|
+
keywords?: string[];
|
|
27
|
+
};
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
/**
|
|
31
|
+
* TaskQueue 类
|
|
32
|
+
*
|
|
33
|
+
* 封装 BullMQ Queue,提供任务队列管理功能
|
|
34
|
+
* 仅在 Redis 可用时启用
|
|
35
|
+
*/
|
|
36
|
+
export class TaskQueue {
|
|
37
|
+
private queue: Queue<TaskJobData> | null = null;
|
|
38
|
+
private initialized = false;
|
|
39
|
+
private enabled: boolean;
|
|
40
|
+
|
|
41
|
+
constructor(name: string = 'content-creator-tasks', options?: QueueOptions) {
|
|
42
|
+
// 检查 Redis 是否可用
|
|
43
|
+
this.enabled = config.redis.enabled;
|
|
44
|
+
|
|
45
|
+
if (!this.enabled) {
|
|
46
|
+
logger.info('TaskQueue is disabled (Redis not configured)');
|
|
47
|
+
return;
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
try {
|
|
51
|
+
// 从配置中解析 Redis URL
|
|
52
|
+
if (!config.redis.url) {
|
|
53
|
+
throw new Error('REDIS_URL is not configured');
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
const redisUrl = new URL(config.redis.url);
|
|
57
|
+
const redisConnection = {
|
|
58
|
+
host: redisUrl.hostname,
|
|
59
|
+
port: parseInt(redisUrl.port) || 6379,
|
|
60
|
+
db: config.redis.db,
|
|
61
|
+
};
|
|
62
|
+
|
|
63
|
+
// 添加密码(如果存在)
|
|
64
|
+
if (config.redis.password) {
|
|
65
|
+
(redisConnection as any).password = config.redis.password;
|
|
66
|
+
} else if (redisUrl.password) {
|
|
67
|
+
(redisConnection as any).password = decodeURIComponent(redisUrl.password);
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
logger.info('Creating TaskQueue with Redis config', {
|
|
71
|
+
host: redisConnection.host,
|
|
72
|
+
port: redisConnection.port,
|
|
73
|
+
db: redisConnection.db,
|
|
74
|
+
hasPassword: !!(redisConnection as any).password,
|
|
75
|
+
});
|
|
76
|
+
|
|
77
|
+
// 创建 Queue,使用配置的 Redis 连接
|
|
78
|
+
this.queue = new Queue<TaskJobData>(name, {
|
|
79
|
+
defaultJobOptions: {
|
|
80
|
+
attempts: 3, // 默认重试 3 次
|
|
81
|
+
backoff: {
|
|
82
|
+
type: 'exponential',
|
|
83
|
+
delay: 2000, // 指数退避,初始 2 秒
|
|
84
|
+
},
|
|
85
|
+
removeOnComplete: {
|
|
86
|
+
count: 1000, // 保留最近 1000 个完成的任务
|
|
87
|
+
age: 24 * 3600, // 或保留 24 小时
|
|
88
|
+
},
|
|
89
|
+
removeOnFail: {
|
|
90
|
+
count: 5000, // 保留最近 5000 个失败的任务
|
|
91
|
+
age: 7 * 24 * 3600, // 或保留 7 天
|
|
92
|
+
},
|
|
93
|
+
},
|
|
94
|
+
connection: redisConnection,
|
|
95
|
+
...options,
|
|
96
|
+
});
|
|
97
|
+
} catch (error) {
|
|
98
|
+
logger.warn('Failed to create TaskQueue, disabling queue', { error: error instanceof Error ? error.message : String(error) });
|
|
99
|
+
this.enabled = false;
|
|
100
|
+
this.queue = null;
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
/**
|
|
105
|
+
* 检查队列是否可用
|
|
106
|
+
*/
|
|
107
|
+
isAvailable(): boolean {
|
|
108
|
+
return this.enabled && this.queue !== null;
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
/**
|
|
112
|
+
* 初始化队列
|
|
113
|
+
*/
|
|
114
|
+
async initialize(): Promise<void> {
|
|
115
|
+
if (!this.isAvailable()) {
|
|
116
|
+
logger.info('TaskQueue is not available (Redis disabled or initialization failed)');
|
|
117
|
+
return;
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
if (this.initialized) {
|
|
121
|
+
return;
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
if (!this.queue) {
|
|
125
|
+
logger.warn('TaskQueue instance is null');
|
|
126
|
+
return;
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
try {
|
|
130
|
+
// BullMQ 会在第一次使用时自动连接 Redis
|
|
131
|
+
// 这里我们只需要标记为已初始化
|
|
132
|
+
await this.queue.waitUntilReady();
|
|
133
|
+
this.initialized = true;
|
|
134
|
+
logger.info('TaskQueue initialized');
|
|
135
|
+
} catch (error) {
|
|
136
|
+
logger.error('Failed to initialize TaskQueue', error as Error);
|
|
137
|
+
throw error;
|
|
138
|
+
}
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
/**
|
|
142
|
+
* 添加任务到队列
|
|
143
|
+
*/
|
|
144
|
+
async addTask(
|
|
145
|
+
data: TaskJobData,
|
|
146
|
+
options?: JobsOptions
|
|
147
|
+
): Promise<void> {
|
|
148
|
+
if (!this.isAvailable()) {
|
|
149
|
+
throw new Error('TaskQueue is not available. Redis is not configured or connection failed. Please use sync mode instead.');
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
await this.ensureInitialized();
|
|
153
|
+
|
|
154
|
+
if (!this.queue) {
|
|
155
|
+
throw new Error('Queue is not initialized');
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
try {
|
|
159
|
+
await this.queue.add('process-content', data, {
|
|
160
|
+
priority: this.calculatePriority(data),
|
|
161
|
+
...options,
|
|
162
|
+
});
|
|
163
|
+
|
|
164
|
+
logger.info('Task added to queue', {
|
|
165
|
+
taskId: data.taskId,
|
|
166
|
+
mode: data.mode,
|
|
167
|
+
topic: data.topic,
|
|
168
|
+
});
|
|
169
|
+
} catch (error) {
|
|
170
|
+
logger.error('Failed to add task to queue', error as Error, {
|
|
171
|
+
taskId: data.taskId,
|
|
172
|
+
});
|
|
173
|
+
throw error;
|
|
174
|
+
}
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
/**
|
|
178
|
+
* 添加延迟任务
|
|
179
|
+
*/
|
|
180
|
+
async addDelayedTask(
|
|
181
|
+
data: TaskJobData,
|
|
182
|
+
delayMs: number
|
|
183
|
+
): Promise<void> {
|
|
184
|
+
await this.ensureInitialized();
|
|
185
|
+
|
|
186
|
+
try {
|
|
187
|
+
if (!this.queue) {
|
|
188
|
+
throw new Error('Queue is not initialized');
|
|
189
|
+
}
|
|
190
|
+
await this.queue.add('process-content', data, {
|
|
191
|
+
delay: delayMs,
|
|
192
|
+
priority: this.calculatePriority(data),
|
|
193
|
+
});
|
|
194
|
+
|
|
195
|
+
logger.info('Delayed task added to queue', {
|
|
196
|
+
taskId: data.taskId,
|
|
197
|
+
delay: delayMs,
|
|
198
|
+
});
|
|
199
|
+
} catch (error) {
|
|
200
|
+
logger.error('Failed to add delayed task to queue', error as Error, {
|
|
201
|
+
taskId: data.taskId,
|
|
202
|
+
});
|
|
203
|
+
throw error;
|
|
204
|
+
}
|
|
205
|
+
}
|
|
206
|
+
|
|
207
|
+
/**
|
|
208
|
+
* 批量添加任务
|
|
209
|
+
*/
|
|
210
|
+
async addBatchTasks(
|
|
211
|
+
dataList: TaskJobData[],
|
|
212
|
+
options?: JobsOptions
|
|
213
|
+
): Promise<void> {
|
|
214
|
+
await this.ensureInitialized();
|
|
215
|
+
|
|
216
|
+
try {
|
|
217
|
+
const jobs = dataList.map((data) => ({
|
|
218
|
+
name: 'process-content',
|
|
219
|
+
data,
|
|
220
|
+
opts: {
|
|
221
|
+
priority: this.calculatePriority(data),
|
|
222
|
+
...options,
|
|
223
|
+
},
|
|
224
|
+
}));
|
|
225
|
+
|
|
226
|
+
if (!this.queue) {
|
|
227
|
+
throw new Error('Queue is not initialized');
|
|
228
|
+
}
|
|
229
|
+
await this.queue.addBulk(jobs);
|
|
230
|
+
|
|
231
|
+
logger.info('Batch tasks added to queue', {
|
|
232
|
+
count: dataList.length,
|
|
233
|
+
});
|
|
234
|
+
} catch (error) {
|
|
235
|
+
logger.error('Failed to add batch tasks to queue', error as Error);
|
|
236
|
+
throw error;
|
|
237
|
+
}
|
|
238
|
+
}
|
|
239
|
+
|
|
240
|
+
/**
|
|
241
|
+
* 计算任务优先级(1-10,数字越小优先级越高)
|
|
242
|
+
*/
|
|
243
|
+
private calculatePriority(data: TaskJobData): number {
|
|
244
|
+
// 同步任务优先级最高
|
|
245
|
+
if (data.mode === 'sync') {
|
|
246
|
+
return 1;
|
|
247
|
+
}
|
|
248
|
+
|
|
249
|
+
// 根据任务类型或其他因素计算优先级
|
|
250
|
+
// 这里可以根据业务需求自定义
|
|
251
|
+
return 5; // 默认优先级
|
|
252
|
+
}
|
|
253
|
+
|
|
254
|
+
/**
|
|
255
|
+
* 暂停队列
|
|
256
|
+
*/
|
|
257
|
+
async pause(): Promise<void> {
|
|
258
|
+
if (!this.queue || !this.isAvailable()) {
|
|
259
|
+
logger.warn('Cannot pause queue (not available)');
|
|
260
|
+
return;
|
|
261
|
+
}
|
|
262
|
+
await this.queue.pause();
|
|
263
|
+
logger.info('TaskQueue paused');
|
|
264
|
+
}
|
|
265
|
+
|
|
266
|
+
/**
|
|
267
|
+
* 恢复队列
|
|
268
|
+
*/
|
|
269
|
+
async resume(): Promise<void> {
|
|
270
|
+
if (!this.queue || !this.isAvailable()) {
|
|
271
|
+
logger.warn('Cannot resume queue (not available)');
|
|
272
|
+
return;
|
|
273
|
+
}
|
|
274
|
+
await this.queue.resume();
|
|
275
|
+
logger.info('TaskQueue resumed');
|
|
276
|
+
}
|
|
277
|
+
|
|
278
|
+
/**
|
|
279
|
+
* 清空队列(等待中的任务)
|
|
280
|
+
*/
|
|
281
|
+
async drain(): Promise<void> {
|
|
282
|
+
if (!this.queue || !this.isAvailable()) {
|
|
283
|
+
logger.warn('Cannot drain queue (not available)');
|
|
284
|
+
return;
|
|
285
|
+
}
|
|
286
|
+
await this.queue.drain();
|
|
287
|
+
logger.info('TaskQueue drained');
|
|
288
|
+
}
|
|
289
|
+
|
|
290
|
+
/**
|
|
291
|
+
* 获取队列统计信息
|
|
292
|
+
*/
|
|
293
|
+
async getStats(): Promise<{
|
|
294
|
+
waiting: number;
|
|
295
|
+
active: number;
|
|
296
|
+
completed: number;
|
|
297
|
+
failed: number;
|
|
298
|
+
delayed: number;
|
|
299
|
+
repeat: number;
|
|
300
|
+
}> {
|
|
301
|
+
if (!this.queue || !this.isAvailable()) {
|
|
302
|
+
logger.warn('Cannot get stats (queue not available)');
|
|
303
|
+
return {
|
|
304
|
+
waiting: 0,
|
|
305
|
+
active: 0,
|
|
306
|
+
completed: 0,
|
|
307
|
+
failed: 0,
|
|
308
|
+
delayed: 0,
|
|
309
|
+
repeat: 0,
|
|
310
|
+
};
|
|
311
|
+
}
|
|
312
|
+
|
|
313
|
+
return {
|
|
314
|
+
waiting: await this.queue.getWaitingCount(),
|
|
315
|
+
active: await this.queue.getActiveCount(),
|
|
316
|
+
completed: await this.queue.getCompletedCount(),
|
|
317
|
+
failed: await this.queue.getFailedCount(),
|
|
318
|
+
delayed: await this.queue.getDelayedCount(),
|
|
319
|
+
// getRepeatCount 可能在某些版本的 BullMQ 中不可用
|
|
320
|
+
repeat: 0, // BullMQ 5.x 中重复任务已被重构
|
|
321
|
+
};
|
|
322
|
+
}
|
|
323
|
+
|
|
324
|
+
/**
|
|
325
|
+
* 获取队列实例(用于 Bull Board)
|
|
326
|
+
*/
|
|
327
|
+
getQueue(): Queue<TaskJobData> | null {
|
|
328
|
+
return this.queue;
|
|
329
|
+
}
|
|
330
|
+
|
|
331
|
+
/**
|
|
332
|
+
* 确保队列已初始化
|
|
333
|
+
*/
|
|
334
|
+
private async ensureInitialized(): Promise<void> {
|
|
335
|
+
if (!this.initialized) {
|
|
336
|
+
await this.initialize();
|
|
337
|
+
}
|
|
338
|
+
}
|
|
339
|
+
|
|
340
|
+
/**
|
|
341
|
+
* 关闭队列
|
|
342
|
+
*/
|
|
343
|
+
async close(): Promise<void> {
|
|
344
|
+
if (!this.queue) {
|
|
345
|
+
logger.warn('Cannot close queue (not initialized)');
|
|
346
|
+
return;
|
|
347
|
+
}
|
|
348
|
+
await this.queue.close();
|
|
349
|
+
this.initialized = false;
|
|
350
|
+
logger.info('TaskQueue closed');
|
|
351
|
+
}
|
|
352
|
+
|
|
353
|
+
/**
|
|
354
|
+
* 获取任务状态
|
|
355
|
+
*/
|
|
356
|
+
async getJobState(jobId: string): Promise<string | null> {
|
|
357
|
+
if (!this.queue || !this.isAvailable()) {
|
|
358
|
+
logger.warn('Cannot get job state (queue not available)', { jobId });
|
|
359
|
+
return null;
|
|
360
|
+
}
|
|
361
|
+
|
|
362
|
+
try {
|
|
363
|
+
const job = await this.queue.getJob(jobId);
|
|
364
|
+
if (!job) {
|
|
365
|
+
return null;
|
|
366
|
+
}
|
|
367
|
+
const state = await job.getState();
|
|
368
|
+
return state;
|
|
369
|
+
} catch (error) {
|
|
370
|
+
logger.error('Failed to get job state', error as Error, { jobId });
|
|
371
|
+
return null;
|
|
372
|
+
}
|
|
373
|
+
}
|
|
374
|
+
|
|
375
|
+
/**
|
|
376
|
+
* 删除任务
|
|
377
|
+
*/
|
|
378
|
+
async removeJob(jobId: string): Promise<boolean> {
|
|
379
|
+
if (!this.queue || !this.isAvailable()) {
|
|
380
|
+
logger.warn('Cannot remove job (queue not available)', { jobId });
|
|
381
|
+
return false;
|
|
382
|
+
}
|
|
383
|
+
|
|
384
|
+
try {
|
|
385
|
+
const job = await this.queue.getJob(jobId);
|
|
386
|
+
if (!job) {
|
|
387
|
+
return false;
|
|
388
|
+
}
|
|
389
|
+
await job.remove();
|
|
390
|
+
logger.info('Job removed', { jobId });
|
|
391
|
+
return true;
|
|
392
|
+
} catch (error) {
|
|
393
|
+
logger.error('Failed to remove job', error as Error, { jobId });
|
|
394
|
+
return false;
|
|
395
|
+
}
|
|
396
|
+
}
|
|
397
|
+
|
|
398
|
+
/**
|
|
399
|
+
* 重试失败的任务
|
|
400
|
+
*/
|
|
401
|
+
async retryJob(jobId: string): Promise<boolean> {
|
|
402
|
+
if (!this.queue || !this.isAvailable()) {
|
|
403
|
+
logger.warn('Cannot retry job (queue not available)', { jobId });
|
|
404
|
+
return false;
|
|
405
|
+
}
|
|
406
|
+
|
|
407
|
+
try {
|
|
408
|
+
const job = await this.queue.getJob(jobId);
|
|
409
|
+
if (!job) {
|
|
410
|
+
return false;
|
|
411
|
+
}
|
|
412
|
+
await job.retry();
|
|
413
|
+
logger.info('Job retried', { jobId });
|
|
414
|
+
return true;
|
|
415
|
+
} catch (error) {
|
|
416
|
+
logger.error('Failed to retry job', error as Error, { jobId });
|
|
417
|
+
return false;
|
|
418
|
+
}
|
|
419
|
+
}
|
|
420
|
+
}
|
|
421
|
+
|
|
422
|
+
/**
|
|
423
|
+
* 创建默认任务队列实例
|
|
424
|
+
*/
|
|
425
|
+
export async function createTaskQueue(): Promise<TaskQueue> {
|
|
426
|
+
const queue = new TaskQueue();
|
|
427
|
+
await queue.initialize();
|
|
428
|
+
return queue;
|
|
429
|
+
}
|
|
@@ -0,0 +1,215 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Redis 连接池
|
|
3
|
+
*
|
|
4
|
+
* 提供 Redis 连接管理和错误处理
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
import Redis from 'ioredis';
|
|
8
|
+
import { config } from '../../config/index.js';
|
|
9
|
+
import { createLogger } from '../logging/logger.js';
|
|
10
|
+
|
|
11
|
+
const logger = createLogger('Redis');
|
|
12
|
+
|
|
13
|
+
/**
|
|
14
|
+
* Redis 客户端类
|
|
15
|
+
*/
|
|
16
|
+
export class RedisClient {
|
|
17
|
+
private client: any | null = null;
|
|
18
|
+
private isConnecting = false;
|
|
19
|
+
private reconnectAttempts = 0;
|
|
20
|
+
private maxReconnectAttempts = 10;
|
|
21
|
+
private enabled: boolean;
|
|
22
|
+
|
|
23
|
+
constructor() {
|
|
24
|
+
this.enabled = config.redis.enabled;
|
|
25
|
+
if (!this.enabled) {
|
|
26
|
+
logger.info('Redis is disabled in configuration');
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
/**
|
|
31
|
+
* 检查 Redis 是否启用
|
|
32
|
+
*/
|
|
33
|
+
isEnabled(): boolean {
|
|
34
|
+
return this.enabled;
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
/**
|
|
38
|
+
* 获取 Redis 客户端实例(单例)
|
|
39
|
+
*/
|
|
40
|
+
async getClient(): Promise<any> {
|
|
41
|
+
if (!this.enabled) {
|
|
42
|
+
throw new Error('Redis is not configured');
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
if (this.client) {
|
|
46
|
+
return this.client;
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
if (this.isConnecting) {
|
|
50
|
+
// 等待连接完成
|
|
51
|
+
await this.waitForConnection();
|
|
52
|
+
return this.client!;
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
return this.connect();
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
/**
|
|
59
|
+
* 连接到 Redis
|
|
60
|
+
*/
|
|
61
|
+
private async connect(): Promise<any> {
|
|
62
|
+
this.isConnecting = true;
|
|
63
|
+
|
|
64
|
+
try {
|
|
65
|
+
// 检查 Redis URL 是否配置
|
|
66
|
+
if (!config.redis.url) {
|
|
67
|
+
throw new Error('REDIS_URL is not configured');
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
// 解析 Redis URL
|
|
71
|
+
const redisUrl = new URL(config.redis.url);
|
|
72
|
+
|
|
73
|
+
logger.info('Connecting to Redis', {
|
|
74
|
+
host: redisUrl.hostname,
|
|
75
|
+
port: redisUrl.port,
|
|
76
|
+
password: redisUrl.password ? '****' : 'none',
|
|
77
|
+
});
|
|
78
|
+
|
|
79
|
+
// 创建 Redis 客户端配置
|
|
80
|
+
const redisOptions: any = {
|
|
81
|
+
host: redisUrl.hostname,
|
|
82
|
+
port: parseInt(redisUrl.port) || 6379,
|
|
83
|
+
db: config.redis.db,
|
|
84
|
+
maxRetriesPerRequest: config.redis.maxRetriesPerRequest,
|
|
85
|
+
retryStrategy: (times: number) => {
|
|
86
|
+
const delay = Math.min(times * 50, 2000);
|
|
87
|
+
logger.debug(`Redis retry attempt ${times}, delay: ${delay}ms`);
|
|
88
|
+
return delay;
|
|
89
|
+
},
|
|
90
|
+
connectTimeout: config.redis.connectTimeout,
|
|
91
|
+
commandTimeout: config.redis.commandTimeout,
|
|
92
|
+
};
|
|
93
|
+
|
|
94
|
+
// 优先使用配置中的密码,否则使用 URL 中的密码
|
|
95
|
+
if (config.redis.password) {
|
|
96
|
+
redisOptions.password = config.redis.password;
|
|
97
|
+
} else if (redisUrl.password) {
|
|
98
|
+
redisOptions.password = decodeURIComponent(redisUrl.password);
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
// 创建 Redis 客户端
|
|
102
|
+
this.client = new (Redis as any)(redisOptions);
|
|
103
|
+
|
|
104
|
+
// 监听连接事件
|
|
105
|
+
this.client.on('connect', () => {
|
|
106
|
+
logger.info('Redis connected');
|
|
107
|
+
this.reconnectAttempts = 0;
|
|
108
|
+
this.isConnecting = false;
|
|
109
|
+
});
|
|
110
|
+
|
|
111
|
+
this.client.on('ready', () => {
|
|
112
|
+
logger.info('Redis ready');
|
|
113
|
+
});
|
|
114
|
+
|
|
115
|
+
this.client.on('error', (error: Error) => {
|
|
116
|
+
logger.error('Redis error', error);
|
|
117
|
+
});
|
|
118
|
+
|
|
119
|
+
this.client.on('close', () => {
|
|
120
|
+
logger.warn('Redis connection closed');
|
|
121
|
+
});
|
|
122
|
+
|
|
123
|
+
this.client.on('reconnecting', () => {
|
|
124
|
+
this.reconnectAttempts++;
|
|
125
|
+
logger.info(`Redis reconnecting (attempt ${this.reconnectAttempts})`);
|
|
126
|
+
|
|
127
|
+
if (this.reconnectAttempts > this.maxReconnectAttempts) {
|
|
128
|
+
logger.error('Max reconnection attempts reached');
|
|
129
|
+
this.disconnect();
|
|
130
|
+
}
|
|
131
|
+
});
|
|
132
|
+
|
|
133
|
+
// 等待连接就绪
|
|
134
|
+
await this.client.ready;
|
|
135
|
+
|
|
136
|
+
logger.info('Redis connection established');
|
|
137
|
+
return this.client;
|
|
138
|
+
} catch (error) {
|
|
139
|
+
this.isConnecting = false;
|
|
140
|
+
logger.error('Failed to connect to Redis', error as Error);
|
|
141
|
+
throw error;
|
|
142
|
+
}
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
/**
|
|
146
|
+
* 等待连接完成
|
|
147
|
+
*/
|
|
148
|
+
private async waitForConnection(): Promise<void> {
|
|
149
|
+
let attempts = 0;
|
|
150
|
+
const maxAttempts = 100;
|
|
151
|
+
|
|
152
|
+
while (this.isConnecting && attempts < maxAttempts) {
|
|
153
|
+
await new Promise((resolve) => setTimeout(resolve, 100));
|
|
154
|
+
attempts++;
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
if (!this.client) {
|
|
158
|
+
throw new Error('Redis connection failed');
|
|
159
|
+
}
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
/**
|
|
163
|
+
* 断开 Redis 连接
|
|
164
|
+
*/
|
|
165
|
+
async disconnect(): Promise<void> {
|
|
166
|
+
if (this.client) {
|
|
167
|
+
logger.info('Disconnecting Redis');
|
|
168
|
+
await this.client.quit();
|
|
169
|
+
this.client = null;
|
|
170
|
+
this.isConnecting = false;
|
|
171
|
+
}
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
/**
|
|
175
|
+
* 检查连接状态
|
|
176
|
+
*/
|
|
177
|
+
isConnected(): boolean {
|
|
178
|
+
return this.client !== null && this.client.status === 'ready';
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
/**
|
|
182
|
+
* Ping Redis
|
|
183
|
+
*/
|
|
184
|
+
async ping(): Promise<string> {
|
|
185
|
+
const client = await this.getClient();
|
|
186
|
+
return await client.ping();
|
|
187
|
+
}
|
|
188
|
+
|
|
189
|
+
/**
|
|
190
|
+
* 获取 Redis 信息
|
|
191
|
+
*/
|
|
192
|
+
async info(section?: string): Promise<string> {
|
|
193
|
+
const client = await this.getClient();
|
|
194
|
+
return await client.info(section);
|
|
195
|
+
}
|
|
196
|
+
}
|
|
197
|
+
|
|
198
|
+
/**
|
|
199
|
+
* Redis 客户端单例
|
|
200
|
+
*/
|
|
201
|
+
export const redisClient = new RedisClient();
|
|
202
|
+
|
|
203
|
+
/**
|
|
204
|
+
* 获取 Redis 客户端便捷方法
|
|
205
|
+
*/
|
|
206
|
+
export async function getRedisClient(): Promise<any> {
|
|
207
|
+
return await redisClient.getClient();
|
|
208
|
+
}
|
|
209
|
+
|
|
210
|
+
/**
|
|
211
|
+
* 检查 Redis 是否可用
|
|
212
|
+
*/
|
|
213
|
+
export function isRedisEnabled(): boolean {
|
|
214
|
+
return redisClient.isEnabled();
|
|
215
|
+
}
|