llm-content-creator 0.1.0 → 0.1.1
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/dist/application/workflow/SyncExecutor.d.ts.map +1 -1
- package/dist/application/workflow/SyncExecutor.js +1 -0
- package/dist/application/workflow/SyncExecutor.js.map +1 -1
- package/dist/config/index.d.ts +2 -2
- package/dist/config/index.js +3 -3
- package/dist/config/index.js.map +1 -1
- package/dist/domain/repositories/TaskRepository.d.ts +1 -0
- package/dist/domain/repositories/TaskRepository.d.ts.map +1 -1
- package/dist/infrastructure/database/MemoryTaskRepository.d.ts +17 -1
- package/dist/infrastructure/database/MemoryTaskRepository.d.ts.map +1 -1
- package/dist/infrastructure/database/MemoryTaskRepository.js +76 -1
- package/dist/infrastructure/database/MemoryTaskRepository.js.map +1 -1
- package/dist/infrastructure/database/SQLiteQualityCheckRepository.d.ts +27 -0
- package/dist/infrastructure/database/SQLiteQualityCheckRepository.d.ts.map +1 -0
- package/dist/infrastructure/database/SQLiteQualityCheckRepository.js +80 -0
- package/dist/infrastructure/database/SQLiteQualityCheckRepository.js.map +1 -0
- package/dist/infrastructure/database/SQLiteResultRepository.d.ts +31 -0
- package/dist/infrastructure/database/SQLiteResultRepository.d.ts.map +1 -0
- package/dist/infrastructure/database/SQLiteResultRepository.js +77 -0
- package/dist/infrastructure/database/SQLiteResultRepository.js.map +1 -0
- package/dist/infrastructure/database/SQLiteTaskRepository.d.ts +12 -0
- package/dist/infrastructure/database/SQLiteTaskRepository.d.ts.map +1 -1
- package/dist/infrastructure/database/SQLiteTaskRepository.js +69 -2
- package/dist/infrastructure/database/SQLiteTaskRepository.js.map +1 -1
- package/dist/infrastructure/database/index.d.ts +23 -2
- package/dist/infrastructure/database/index.d.ts.map +1 -1
- package/dist/infrastructure/database/index.js +33 -2
- package/dist/infrastructure/database/index.js.map +1 -1
- package/dist/infrastructure/redis/connection.d.ts.map +1 -1
- package/dist/infrastructure/redis/connection.js +14 -3
- package/dist/infrastructure/redis/connection.js.map +1 -1
- package/dist/presentation/cli/commands/cancel.d.ts.map +1 -1
- package/dist/presentation/cli/commands/cancel.js +1 -0
- package/dist/presentation/cli/commands/cancel.js.map +1 -1
- package/dist/presentation/cli/commands/create.d.ts.map +1 -1
- package/dist/presentation/cli/commands/create.js +29 -14
- package/dist/presentation/cli/commands/create.js.map +1 -1
- package/dist/presentation/cli/commands/list.d.ts +8 -0
- package/dist/presentation/cli/commands/list.d.ts.map +1 -0
- package/dist/presentation/cli/commands/list.js +154 -0
- package/dist/presentation/cli/commands/list.js.map +1 -0
- package/dist/presentation/cli/commands/result.d.ts.map +1 -1
- package/dist/presentation/cli/commands/result.js +33 -3
- package/dist/presentation/cli/commands/result.js.map +1 -1
- package/dist/presentation/cli/commands/retry.d.ts +8 -0
- package/dist/presentation/cli/commands/retry.d.ts.map +1 -0
- package/dist/presentation/cli/commands/retry.js +203 -0
- package/dist/presentation/cli/commands/retry.js.map +1 -0
- package/dist/presentation/cli/commands/status.d.ts.map +1 -1
- package/dist/presentation/cli/commands/status.js +3 -2
- package/dist/presentation/cli/commands/status.js.map +1 -1
- package/dist/presentation/cli/index.js +4 -0
- package/dist/presentation/cli/index.js.map +1 -1
- package/dist/presentation/cli/utils/cleanup.d.ts +1 -3
- package/dist/presentation/cli/utils/cleanup.d.ts.map +1 -1
- package/dist/presentation/cli/utils/cleanup.js.map +1 -1
- package/dist/presentation/monitor-cli.js +2 -4
- package/dist/presentation/monitor-cli.js.map +1 -1
- package/dist/presentation/worker-cli.js +8 -5
- package/dist/presentation/worker-cli.js.map +1 -1
- package/dist/schedulers/TaskScheduler.d.ts.map +1 -1
- package/dist/schedulers/TaskScheduler.js +13 -5
- package/dist/schedulers/TaskScheduler.js.map +1 -1
- package/dist/workers/TaskWorker.d.ts.map +1 -1
- package/dist/workers/TaskWorker.js +39 -21
- package/dist/workers/TaskWorker.js.map +1 -1
- package/docs/cli-reference.md +623 -0
- package/docs/quick-start.md +47 -0
- package/docs/user-guide.md +191 -24
- package/package.json +3 -1
- package/src/application/workflow/SyncExecutor.ts +1 -0
- package/src/config/index.ts +3 -3
- package/src/domain/repositories/TaskRepository.ts +1 -0
- package/src/infrastructure/database/MemoryTaskRepository.ts +89 -1
- package/src/infrastructure/database/SQLiteQualityCheckRepository.ts +102 -0
- package/src/infrastructure/database/SQLiteResultRepository.ts +95 -0
- package/src/infrastructure/database/SQLiteTaskRepository.ts +80 -2
- package/src/infrastructure/database/index.ts +39 -2
- package/src/infrastructure/redis/connection.ts +16 -3
- package/src/presentation/cli/commands/cancel.ts +1 -0
- package/src/presentation/cli/commands/create.ts +30 -14
- package/src/presentation/cli/commands/list.ts +172 -0
- package/src/presentation/cli/commands/result.ts +33 -3
- package/src/presentation/cli/commands/retry.ts +241 -0
- package/src/presentation/cli/commands/status.ts +3 -2
- package/src/presentation/cli/index.ts +4 -0
- package/src/presentation/cli/utils/cleanup.ts +1 -1
- package/src/presentation/monitor-cli.ts +2 -4
- package/src/presentation/worker-cli.ts +8 -5
- package/src/schedulers/TaskScheduler.ts +13 -5
- package/src/workers/TaskWorker.ts +47 -22
package/docs/user-guide.md
CHANGED
|
@@ -65,11 +65,11 @@ cp .env.example .env
|
|
|
65
65
|
pnpm run db:migrate
|
|
66
66
|
|
|
67
67
|
# 5. 创建第一个任务
|
|
68
|
-
pnpm run cli
|
|
68
|
+
pnpm run cli create \
|
|
69
69
|
--topic "人工智能的未来" \
|
|
70
70
|
--requirements "写一篇关于 AI 未来发展的文章" \
|
|
71
71
|
--audience "技术爱好者" \
|
|
72
|
-
--sync
|
|
72
|
+
--mode sync
|
|
73
73
|
```
|
|
74
74
|
|
|
75
75
|
### Docker 快速启动
|
|
@@ -294,7 +294,7 @@ pnpm run start
|
|
|
294
294
|
#### 创建内容创作任务
|
|
295
295
|
|
|
296
296
|
```bash
|
|
297
|
-
pnpm run cli
|
|
297
|
+
pnpm run cli create \
|
|
298
298
|
--topic "文章主题" \
|
|
299
299
|
--requirements "创作要求" \
|
|
300
300
|
--audience "目标受众" \
|
|
@@ -302,7 +302,7 @@ pnpm run cli:create \
|
|
|
302
302
|
--keywords "关键词1,关键词2" \
|
|
303
303
|
--min-words 500 \
|
|
304
304
|
--max-words 2000 \
|
|
305
|
-
--sync
|
|
305
|
+
--mode sync
|
|
306
306
|
```
|
|
307
307
|
|
|
308
308
|
#### 参数说明
|
|
@@ -324,7 +324,7 @@ pnpm run cli:create \
|
|
|
324
324
|
##### 示例 1:技术博客文章
|
|
325
325
|
|
|
326
326
|
```bash
|
|
327
|
-
pnpm run cli
|
|
327
|
+
pnpm run cli create \
|
|
328
328
|
--topic "TypeScript 5.0 新特性解析" \
|
|
329
329
|
--requirements "详细介绍 TypeScript 5.0 的新特性、改进和迁移指南" \
|
|
330
330
|
--audience "前端开发者" \
|
|
@@ -332,13 +332,13 @@ pnpm run cli:create \
|
|
|
332
332
|
--keywords "TypeScript,JavaScript,前端开发" \
|
|
333
333
|
--min-words 1000 \
|
|
334
334
|
--max-words 2000 \
|
|
335
|
-
--sync
|
|
335
|
+
--mode sync
|
|
336
336
|
```
|
|
337
337
|
|
|
338
338
|
##### 示例 2:生活类文章
|
|
339
339
|
|
|
340
340
|
```bash
|
|
341
|
-
pnpm run cli
|
|
341
|
+
pnpm run cli create \
|
|
342
342
|
--topic "健康生活方式建议" \
|
|
343
343
|
--requirements "提供实用的健康生活建议,包括饮食、运动和睡眠" \
|
|
344
344
|
--audience "普通读者" \
|
|
@@ -346,7 +346,7 @@ pnpm run cli:create \
|
|
|
346
346
|
--keywords "健康,生活,养生" \
|
|
347
347
|
--min-words 800 \
|
|
348
348
|
--max-words 1200 \
|
|
349
|
-
--sync
|
|
349
|
+
--mode sync
|
|
350
350
|
```
|
|
351
351
|
|
|
352
352
|
### 方式二:程序化调用
|
|
@@ -394,20 +394,20 @@ console.log('配图 URL:', result.finalState.imageUrl);
|
|
|
394
394
|
### create - 创建任务
|
|
395
395
|
|
|
396
396
|
```bash
|
|
397
|
-
pnpm run cli
|
|
397
|
+
pnpm run cli create [options]
|
|
398
398
|
```
|
|
399
399
|
|
|
400
400
|
**示例**:
|
|
401
401
|
|
|
402
402
|
```bash
|
|
403
403
|
# 同步执行(推荐用于测试)
|
|
404
|
-
pnpm run cli
|
|
404
|
+
pnpm run cli create \
|
|
405
405
|
--topic "主题" \
|
|
406
406
|
--requirements "要求" \
|
|
407
|
-
--sync
|
|
407
|
+
--mode sync
|
|
408
408
|
|
|
409
409
|
# 异步执行(推荐用于生产)
|
|
410
|
-
pnpm run cli
|
|
410
|
+
pnpm run cli create \
|
|
411
411
|
--topic "主题" \
|
|
412
412
|
--requirements "要求" \
|
|
413
413
|
--mode async
|
|
@@ -415,27 +415,122 @@ pnpm run cli:create \
|
|
|
415
415
|
|
|
416
416
|
### 其他 CLI 命令
|
|
417
417
|
|
|
418
|
+
#### 查看历史任务列表
|
|
419
|
+
|
|
420
|
+
```bash
|
|
421
|
+
# 查看最近 20 个任务(默认)
|
|
422
|
+
pnpm run cli list
|
|
423
|
+
|
|
424
|
+
# 查看最近 10 个任务
|
|
425
|
+
pnpm run cli list --limit 10
|
|
426
|
+
|
|
427
|
+
# 只查看已完成的任务
|
|
428
|
+
pnpm run cli list --status completed
|
|
429
|
+
|
|
430
|
+
# 只查看失败的任务
|
|
431
|
+
pnpm run cli list --status failed
|
|
432
|
+
|
|
433
|
+
# 只查看异步任务
|
|
434
|
+
pnpm run cli list --mode async
|
|
435
|
+
|
|
436
|
+
# 查看第 2 页(分页)
|
|
437
|
+
pnpm run cli list --offset 20
|
|
438
|
+
|
|
439
|
+
# 以 JSON 格式输出(方便脚本处理)
|
|
440
|
+
pnpm run cli list --json
|
|
441
|
+
```
|
|
442
|
+
|
|
443
|
+
**显示内容**:
|
|
444
|
+
- 任务主题
|
|
445
|
+
- 任务 ID
|
|
446
|
+
- 当前状态(等待中/运行中/已完成/失败)
|
|
447
|
+
- 执行模式(同步/异步)
|
|
448
|
+
- 创建时间(智能相对时间)
|
|
449
|
+
- 执行耗时
|
|
450
|
+
- 错误信息(如果失败)
|
|
451
|
+
|
|
452
|
+
#### 重新执行任务
|
|
453
|
+
|
|
454
|
+
```bash
|
|
455
|
+
# 重新执行单个任务
|
|
456
|
+
pnpm run cli retry --task-id <任务ID>
|
|
457
|
+
|
|
458
|
+
# 批量重新执行所有等待任务
|
|
459
|
+
pnpm run cli retry --all
|
|
460
|
+
|
|
461
|
+
# 批量重新执行失败任务
|
|
462
|
+
pnpm run cli retry --all --status failed
|
|
463
|
+
|
|
464
|
+
# 模拟运行(预览但不实际执行)
|
|
465
|
+
pnpm run cli retry --all --dry-run
|
|
466
|
+
|
|
467
|
+
# 限制处理数量
|
|
468
|
+
pnpm run cli retry --all --limit 5
|
|
469
|
+
```
|
|
470
|
+
|
|
471
|
+
**使用场景**:
|
|
472
|
+
- Worker 临时停止导致任务堆积
|
|
473
|
+
- 任务创建时队列不可用
|
|
474
|
+
- 失败的任务需要重试
|
|
475
|
+
- 想要重新执行历史任务
|
|
476
|
+
|
|
418
477
|
#### 查看任务状态
|
|
419
478
|
|
|
420
479
|
```bash
|
|
421
|
-
pnpm run cli
|
|
480
|
+
pnpm run cli status --task-id <task-id>
|
|
481
|
+
```
|
|
482
|
+
|
|
483
|
+
#### 获取任务结果
|
|
484
|
+
|
|
485
|
+
```bash
|
|
486
|
+
pnpm run cli result --task-id <task-id>
|
|
422
487
|
```
|
|
423
488
|
|
|
424
489
|
#### 取消任务
|
|
425
490
|
|
|
426
491
|
```bash
|
|
427
|
-
pnpm run cli
|
|
492
|
+
pnpm run cli cancel --task-id <task-id>
|
|
428
493
|
```
|
|
429
494
|
|
|
430
|
-
#### 监控面板
|
|
495
|
+
#### 监控面板 (Monitor)
|
|
496
|
+
|
|
497
|
+
**启动监控面板**:
|
|
431
498
|
|
|
432
499
|
```bash
|
|
433
|
-
# 启动 BullMQ
|
|
500
|
+
# 启动 BullMQ 监控面板(默认端口 3000)
|
|
434
501
|
pnpm run monitor
|
|
435
502
|
|
|
436
|
-
#
|
|
503
|
+
# 指定端口启动
|
|
504
|
+
npx tsx src/presentation/monitor-cli.ts start -p 3001
|
|
437
505
|
```
|
|
438
506
|
|
|
507
|
+
**访问 Web UI**:
|
|
508
|
+
|
|
509
|
+
启动后访问: `http://localhost:3000/admin/queues`
|
|
510
|
+
|
|
511
|
+
**功能特性**:
|
|
512
|
+
- ✅ **实时队列监控** - 查看待处理、执行中、已完成、失败的任务
|
|
513
|
+
- ✅ **任务详情查看** - 查看任务数据、堆栈跟踪、执行日志
|
|
514
|
+
- ✅ **任务管理** - 手动重试失败任务、删除任务、暂停/恢复队列
|
|
515
|
+
- ✅ **队列统计** - 实时查看队列状态和任务数量
|
|
516
|
+
- ✅ **错误追踪** - 查看失败任务的原因和错误信息
|
|
517
|
+
|
|
518
|
+
**API 端点**:
|
|
519
|
+
|
|
520
|
+
```bash
|
|
521
|
+
# 健康检查
|
|
522
|
+
curl http://localhost:3000/health
|
|
523
|
+
|
|
524
|
+
# 获取队列统计
|
|
525
|
+
curl http://localhost:3000/api/stats
|
|
526
|
+
```
|
|
527
|
+
|
|
528
|
+
**使用场景**:
|
|
529
|
+
- 监控异步任务执行状态
|
|
530
|
+
- 查看失败任务并进行手动重试
|
|
531
|
+
- 清理堆积的任务队列
|
|
532
|
+
- 调试任务执行问题
|
|
533
|
+
|
|
439
534
|
---
|
|
440
535
|
|
|
441
536
|
## 🔌 API 接口
|
|
@@ -459,10 +554,10 @@ pnpm run monitor
|
|
|
459
554
|
```bash
|
|
460
555
|
# 创建批量脚本
|
|
461
556
|
for topic in "AI发展" "区块链应用" "云计算趋势"; do
|
|
462
|
-
pnpm run cli
|
|
557
|
+
pnpm run cli create \
|
|
463
558
|
--topic "$topic" \
|
|
464
559
|
--requirements "详细介绍 $topic" \
|
|
465
|
-
--sync
|
|
560
|
+
--mode sync
|
|
466
561
|
done
|
|
467
562
|
```
|
|
468
563
|
|
|
@@ -481,17 +576,30 @@ LLM_TEMPERATURE=0.3 # 降低创造性(更确定性)
|
|
|
481
576
|
创建任务时设置:
|
|
482
577
|
|
|
483
578
|
```bash
|
|
484
|
-
pnpm run cli
|
|
579
|
+
pnpm run cli create \
|
|
485
580
|
--topic "主题" \
|
|
486
|
-
--requirements "要求"
|
|
487
|
-
--no-search #
|
|
581
|
+
--requirements "要求"
|
|
582
|
+
# --no-search # 暂不支持此参数
|
|
488
583
|
```
|
|
489
584
|
|
|
490
585
|
或在代码中设置 `useCache: true` 强制使用缓存。
|
|
491
586
|
|
|
492
587
|
### Q4: 如何查看任务历史?
|
|
493
588
|
|
|
494
|
-
|
|
589
|
+
使用 CLI 命令:
|
|
590
|
+
|
|
591
|
+
```bash
|
|
592
|
+
# 查看最近的任务
|
|
593
|
+
pnpm run cli list
|
|
594
|
+
|
|
595
|
+
# 查看失败的任务
|
|
596
|
+
pnpm run cli list --status failed
|
|
597
|
+
|
|
598
|
+
# 以 JSON 格式输出
|
|
599
|
+
pnpm run cli list --json
|
|
600
|
+
```
|
|
601
|
+
|
|
602
|
+
或直接查询数据库:
|
|
495
603
|
|
|
496
604
|
```bash
|
|
497
605
|
# 使用 psql
|
|
@@ -660,11 +768,52 @@ pnpm run verify-env
|
|
|
660
768
|
|
|
661
769
|
# 数据库状态
|
|
662
770
|
pnpm run db:status
|
|
771
|
+
```
|
|
772
|
+
|
|
773
|
+
### Monitor 监控面板
|
|
663
774
|
|
|
664
|
-
|
|
775
|
+
**启动监控面板**:
|
|
776
|
+
|
|
777
|
+
```bash
|
|
778
|
+
# 启动 Monitor(推荐)
|
|
665
779
|
pnpm run monitor
|
|
780
|
+
|
|
781
|
+
# 指定端口
|
|
782
|
+
npx tsx src/presentation/monitor-cli.ts start -p 3001
|
|
666
783
|
```
|
|
667
784
|
|
|
785
|
+
**访问地址**:
|
|
786
|
+
- Web UI: http://localhost:3000/admin/queues
|
|
787
|
+
- 健康检查: http://localhost:3000/health
|
|
788
|
+
- 队列统计: http://localhost:3000/api/stats
|
|
789
|
+
|
|
790
|
+
**监控面板功能**:
|
|
791
|
+
|
|
792
|
+
1. **队列概览**
|
|
793
|
+
- Waiting(等待中)- 待处理的任务
|
|
794
|
+
- Active(执行中)- 正在执行的任务
|
|
795
|
+
- Completed(已完成)- 成功完成的任务
|
|
796
|
+
- Failed(失败)- 执行失败的任务
|
|
797
|
+
- Delayed(延迟)- 延迟执行的任务
|
|
798
|
+
|
|
799
|
+
2. **任务操作**
|
|
800
|
+
- 查看任务详情(点击任务 ID)
|
|
801
|
+
- 重试失败任务(Retry 按钮)
|
|
802
|
+
- 删除任务(Delete 按钮)
|
|
803
|
+
- 查看任务日志和堆栈跟踪
|
|
804
|
+
|
|
805
|
+
3. **队列管理**
|
|
806
|
+
- 暂停队列(Pause 按钮)
|
|
807
|
+
- 恢复队列(Resume 按钮)
|
|
808
|
+
- 清空队列(Clean all 按钮)
|
|
809
|
+
- 批量操作失败任务
|
|
810
|
+
|
|
811
|
+
4. **性能监控**
|
|
812
|
+
- 任务处理速度
|
|
813
|
+
- 队列堆积情况
|
|
814
|
+
- 失败率统计
|
|
815
|
+
- Worker 性能指标
|
|
816
|
+
|
|
668
817
|
### 日志查看
|
|
669
818
|
|
|
670
819
|
```bash
|
|
@@ -673,6 +822,9 @@ tail -f ./logs/app.log
|
|
|
673
822
|
|
|
674
823
|
# 搜索错误日志
|
|
675
824
|
grep "error" ./logs/app.log
|
|
825
|
+
|
|
826
|
+
# 查看 Monitor 日志
|
|
827
|
+
tail -f ./logs/app.log | grep BullBoard
|
|
676
828
|
```
|
|
677
829
|
|
|
678
830
|
### 性能指标
|
|
@@ -683,6 +835,21 @@ grep "error" ./logs/app.log
|
|
|
683
835
|
- 缓存命中率
|
|
684
836
|
- 错误率
|
|
685
837
|
|
|
838
|
+
### 常用监控组合
|
|
839
|
+
|
|
840
|
+
```bash
|
|
841
|
+
# 终端 1: 启动监控面板
|
|
842
|
+
pnpm run monitor
|
|
843
|
+
|
|
844
|
+
# 终端 2: 启动 Worker
|
|
845
|
+
pnpm run worker
|
|
846
|
+
|
|
847
|
+
# 终端 3: 创建异步任务
|
|
848
|
+
pnpm run cli create --topic "测试" --requirements "测试描述" --mode async
|
|
849
|
+
|
|
850
|
+
# 浏览器: 访问 http://localhost:3000/admin/queues 观察任务执行
|
|
851
|
+
```
|
|
852
|
+
|
|
686
853
|
---
|
|
687
854
|
|
|
688
855
|
## 📞 技术支持
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "llm-content-creator",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.1",
|
|
4
4
|
"description": "AI 驱动的内容创作工具库",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
6
|
"type": "module",
|
|
@@ -52,6 +52,8 @@
|
|
|
52
52
|
"db:status": "tsx scripts/run-migration.ts status",
|
|
53
53
|
"cli": "tsx src/presentation/cli/index.ts",
|
|
54
54
|
"cli:create": "tsx src/presentation/cli/index.ts create",
|
|
55
|
+
"cli:list": "tsx src/presentation/cli/index.ts list",
|
|
56
|
+
"cli:retry": "tsx src/presentation/cli/index.ts retry",
|
|
55
57
|
"cli:status": "tsx src/presentation/cli/index.ts status",
|
|
56
58
|
"cli:result": "tsx src/presentation/cli/index.ts result",
|
|
57
59
|
"cli:cancel": "tsx src/presentation/cli/index.ts cancel",
|
package/src/config/index.ts
CHANGED
|
@@ -62,7 +62,7 @@ const envSchema = z.object({
|
|
|
62
62
|
S3_BUCKET: z.string().optional(),
|
|
63
63
|
|
|
64
64
|
// Worker 配置
|
|
65
|
-
WORKER_ID: z.string().
|
|
65
|
+
WORKER_ID: z.string().optional(),
|
|
66
66
|
WORKER_CONCURRENCY: z.coerce.number().int().positive().default(2),
|
|
67
67
|
|
|
68
68
|
// 日志配置
|
|
@@ -160,7 +160,7 @@ class Config {
|
|
|
160
160
|
console.log('Configuration Loaded Successfully');
|
|
161
161
|
console.log('========================================');
|
|
162
162
|
console.log(`Environment: ${this.env.NODE_ENV}`);
|
|
163
|
-
console.log(`Worker ID: ${this.env.WORKER_ID}`);
|
|
163
|
+
console.log(`Worker ID: ${this.env.WORKER_ID || 'Not set (auto-generating UUID)'}`);
|
|
164
164
|
console.log(`Concurrency: ${this.env.WORKER_CONCURRENCY}`);
|
|
165
165
|
console.log(`Database Type: ${this.databaseType}`);
|
|
166
166
|
|
|
@@ -256,7 +256,7 @@ class Config {
|
|
|
256
256
|
// 连接超时
|
|
257
257
|
connectTimeout: 10000,
|
|
258
258
|
// 命令超时
|
|
259
|
-
commandTimeout:
|
|
259
|
+
commandTimeout: 30000,
|
|
260
260
|
};
|
|
261
261
|
}
|
|
262
262
|
|
|
@@ -127,7 +127,42 @@ export class MemoryTaskRepository {
|
|
|
127
127
|
}
|
|
128
128
|
|
|
129
129
|
/**
|
|
130
|
-
* 抢占任务(Worker
|
|
130
|
+
* 抢占任务(Worker 抢占机制)- 按任务ID抢占
|
|
131
|
+
*/
|
|
132
|
+
async claimTask(taskId: string, workerId: string, version: number): Promise<boolean> {
|
|
133
|
+
const task = this.tasks.get(taskId);
|
|
134
|
+
if (!task) {
|
|
135
|
+
return false;
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
// 检查版本号(乐观锁)
|
|
139
|
+
if (task.version !== version || task.status !== TaskStatus.PENDING) {
|
|
140
|
+
logger.warn('Task claim failed (version mismatch or not pending)', {
|
|
141
|
+
taskId,
|
|
142
|
+
expectedVersion: version,
|
|
143
|
+
actualVersion: task.version,
|
|
144
|
+
status: task.status
|
|
145
|
+
});
|
|
146
|
+
return false;
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
const now = new Date();
|
|
150
|
+
const updatedTask: Task = {
|
|
151
|
+
...task,
|
|
152
|
+
status: TaskStatus.RUNNING,
|
|
153
|
+
workerId,
|
|
154
|
+
startedAt: now,
|
|
155
|
+
version: version + 1,
|
|
156
|
+
updatedAt: now,
|
|
157
|
+
};
|
|
158
|
+
|
|
159
|
+
this.tasks.set(taskId, updatedTask);
|
|
160
|
+
logger.info('Task claimed (memory)', { taskId, workerId });
|
|
161
|
+
return true;
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
/**
|
|
165
|
+
* 抢占任务(Worker 抢占机制)- 批量抢占
|
|
131
166
|
*/
|
|
132
167
|
async claimForProcessing(workerId: string, limit: number = 1): Promise<Task[]> {
|
|
133
168
|
const now = new Date();
|
|
@@ -361,6 +396,59 @@ export class MemoryTaskRepository {
|
|
|
361
396
|
return true;
|
|
362
397
|
}
|
|
363
398
|
|
|
399
|
+
/**
|
|
400
|
+
* 查询任务列表(支持过滤和分页)
|
|
401
|
+
*/
|
|
402
|
+
async findMany(filter?: any, pagination?: any): Promise<Task[]> {
|
|
403
|
+
const { limit = 50, offset = 0 } = pagination || {};
|
|
404
|
+
|
|
405
|
+
let tasks = Array.from(this.tasks.values());
|
|
406
|
+
|
|
407
|
+
// 应用过滤
|
|
408
|
+
if (filter?.status) {
|
|
409
|
+
tasks = tasks.filter((t) => t.status === filter.status);
|
|
410
|
+
}
|
|
411
|
+
if (filter?.userId) {
|
|
412
|
+
tasks = tasks.filter((t) => t.id === filter.userId); // Memory 没有 userId 字段
|
|
413
|
+
}
|
|
414
|
+
if (filter?.mode) {
|
|
415
|
+
tasks = tasks.filter((t) => t.mode === filter.mode);
|
|
416
|
+
}
|
|
417
|
+
|
|
418
|
+
// 按创建时间倒序排序
|
|
419
|
+
tasks.sort((a, b) => new Date(b.createdAt).getTime() - new Date(a.createdAt).getTime());
|
|
420
|
+
|
|
421
|
+
// 分页
|
|
422
|
+
return tasks.slice(offset, offset + limit);
|
|
423
|
+
}
|
|
424
|
+
|
|
425
|
+
/**
|
|
426
|
+
* 统计任务数量
|
|
427
|
+
*/
|
|
428
|
+
async count(filter?: any): Promise<number> {
|
|
429
|
+
let tasks = Array.from(this.tasks.values());
|
|
430
|
+
|
|
431
|
+
// 应用过滤
|
|
432
|
+
if (filter?.status) {
|
|
433
|
+
tasks = tasks.filter((t) => t.status === filter.status);
|
|
434
|
+
}
|
|
435
|
+
if (filter?.userId) {
|
|
436
|
+
tasks = tasks.filter((t) => t.id === filter.userId);
|
|
437
|
+
}
|
|
438
|
+
if (filter?.mode) {
|
|
439
|
+
tasks = tasks.filter((t) => t.mode === filter.mode);
|
|
440
|
+
}
|
|
441
|
+
|
|
442
|
+
return tasks.length;
|
|
443
|
+
}
|
|
444
|
+
|
|
445
|
+
/**
|
|
446
|
+
* 根据 userId 查询任务列表
|
|
447
|
+
*/
|
|
448
|
+
async findByUserId(userId: string, pagination?: any): Promise<Task[]> {
|
|
449
|
+
return this.findMany({ userId }, pagination);
|
|
450
|
+
}
|
|
451
|
+
|
|
364
452
|
/**
|
|
365
453
|
* 获取统计信息
|
|
366
454
|
*/
|
|
@@ -0,0 +1,102 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* SQLite Quality Check Repository
|
|
3
|
+
*
|
|
4
|
+
* 使用 better-sqlite3 实现的轻量级质量检查数据访问层
|
|
5
|
+
* 适合开发和测试环境
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
import Database from 'better-sqlite3';
|
|
9
|
+
import { v4 as uuidv4 } from 'uuid';
|
|
10
|
+
import { createLogger } from '../../infrastructure/logging/logger.js';
|
|
11
|
+
import type { IQualityCheckRepository, CreateQualityCheckParams, QualityCheckRecord } from '../../domain/repositories/QualityCheckRepository.js';
|
|
12
|
+
|
|
13
|
+
const logger = createLogger('SQLite:QualityCheckRepository');
|
|
14
|
+
|
|
15
|
+
/**
|
|
16
|
+
* SQLite Quality Check Repository 实现
|
|
17
|
+
*/
|
|
18
|
+
export class SQLiteQualityCheckRepository implements IQualityCheckRepository {
|
|
19
|
+
private db: Database.Database;
|
|
20
|
+
|
|
21
|
+
constructor(dbPath?: string) {
|
|
22
|
+
const actualDbPath = dbPath || './data/content-creator.db';
|
|
23
|
+
this.db = new Database(actualDbPath);
|
|
24
|
+
logger.info('SQLite quality check repository initialized', { dbPath: actualDbPath });
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
/**
|
|
28
|
+
* 创建质量检查记录
|
|
29
|
+
*/
|
|
30
|
+
async create(params: CreateQualityCheckParams): Promise<void> {
|
|
31
|
+
const now = new Date().toISOString();
|
|
32
|
+
const stmt = this.db.prepare(`
|
|
33
|
+
INSERT INTO quality_checks (
|
|
34
|
+
id, task_id, check_type, score, passed, hard_constraints_passed,
|
|
35
|
+
details, fix_suggestions, rubric_version, model_name, prompt_hash, created_at
|
|
36
|
+
) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
|
|
37
|
+
`);
|
|
38
|
+
|
|
39
|
+
const details = params.details ? JSON.stringify(params.details) : null;
|
|
40
|
+
const fixSuggestions = (params.fixSuggestions && params.fixSuggestions.length > 0)
|
|
41
|
+
? JSON.stringify(params.fixSuggestions)
|
|
42
|
+
: null;
|
|
43
|
+
|
|
44
|
+
try {
|
|
45
|
+
stmt.run(
|
|
46
|
+
uuidv4(), // 使用 UUID v4 确保唯一性
|
|
47
|
+
params.taskId,
|
|
48
|
+
params.checkType,
|
|
49
|
+
params.score,
|
|
50
|
+
params.passed,
|
|
51
|
+
params.hardConstraintsPassed,
|
|
52
|
+
details,
|
|
53
|
+
fixSuggestions,
|
|
54
|
+
params.rubricVersion || null,
|
|
55
|
+
params.modelName || null,
|
|
56
|
+
params.promptHash || null,
|
|
57
|
+
now
|
|
58
|
+
);
|
|
59
|
+
|
|
60
|
+
logger.info('Quality check created', {
|
|
61
|
+
taskId: params.taskId,
|
|
62
|
+
checkType: params.checkType,
|
|
63
|
+
score: params.score,
|
|
64
|
+
passed: params.passed,
|
|
65
|
+
});
|
|
66
|
+
} catch (error) {
|
|
67
|
+
logger.error('Failed to create quality check', { error: error as any, params });
|
|
68
|
+
throw error;
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
/**
|
|
73
|
+
* 根据任务 ID 查询质量检查
|
|
74
|
+
*/
|
|
75
|
+
async findByTaskId(taskId: string): Promise<QualityCheckRecord[]> {
|
|
76
|
+
const stmt = this.db.prepare('SELECT * FROM quality_checks WHERE task_id = ? ORDER BY created_at DESC');
|
|
77
|
+
const rows = stmt.all(taskId) as any[];
|
|
78
|
+
|
|
79
|
+
return rows.map((row) => ({
|
|
80
|
+
id: row.id,
|
|
81
|
+
taskId: row.task_id,
|
|
82
|
+
checkType: row.check_type,
|
|
83
|
+
score: row.score,
|
|
84
|
+
passed: row.passed,
|
|
85
|
+
hardConstraintsPassed: row.hard_constraints_passed,
|
|
86
|
+
details: row.details ? JSON.parse(row.details) : null,
|
|
87
|
+
fixSuggestions: row.fix_suggestions ? JSON.parse(row.fix_suggestions) : null,
|
|
88
|
+
rubricVersion: row.rubric_version,
|
|
89
|
+
modelName: row.model_name,
|
|
90
|
+
promptHash: row.prompt_hash,
|
|
91
|
+
createdAt: new Date(row.created_at),
|
|
92
|
+
})) as QualityCheckRecord[];
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
/**
|
|
96
|
+
* 关闭数据库连接
|
|
97
|
+
*/
|
|
98
|
+
close(): void {
|
|
99
|
+
this.db.close();
|
|
100
|
+
logger.info('SQLite quality check repository connection closed');
|
|
101
|
+
}
|
|
102
|
+
}
|
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* SQLite Result Repository
|
|
3
|
+
*
|
|
4
|
+
* 使用 better-sqlite3 实现的轻量级结果数据访问层
|
|
5
|
+
* 适合开发和测试环境
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
import Database from 'better-sqlite3';
|
|
9
|
+
import { v4 as uuidv4 } from 'uuid';
|
|
10
|
+
import { createLogger } from '../../infrastructure/logging/logger.js';
|
|
11
|
+
import type { IResultRepository, CreateResultParams, ResultRecord } from '../../domain/repositories/ResultRepository.js';
|
|
12
|
+
|
|
13
|
+
const logger = createLogger('SQLite:ResultRepository');
|
|
14
|
+
|
|
15
|
+
/**
|
|
16
|
+
* SQLite Result Repository 实现
|
|
17
|
+
*/
|
|
18
|
+
export class SQLiteResultRepository implements IResultRepository {
|
|
19
|
+
private db: Database.Database;
|
|
20
|
+
|
|
21
|
+
constructor(dbPath?: string) {
|
|
22
|
+
const actualDbPath = dbPath || './data/content-creator.db';
|
|
23
|
+
this.db = new Database(actualDbPath);
|
|
24
|
+
logger.info('SQLite result repository initialized', { dbPath: actualDbPath });
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
/**
|
|
28
|
+
* 创建结果记录
|
|
29
|
+
*/
|
|
30
|
+
async create(params: CreateResultParams): Promise<void> {
|
|
31
|
+
const now = new Date().toISOString();
|
|
32
|
+
const stmt = this.db.prepare(`
|
|
33
|
+
INSERT INTO results (
|
|
34
|
+
id, task_id, result_type, content, file_path, metadata, created_at
|
|
35
|
+
) VALUES (?, ?, ?, ?, ?, ?, ?)
|
|
36
|
+
`);
|
|
37
|
+
|
|
38
|
+
const metadata = params.metadata ? JSON.stringify(params.metadata) : null;
|
|
39
|
+
|
|
40
|
+
try {
|
|
41
|
+
stmt.run(
|
|
42
|
+
uuidv4(), // 使用 UUID v4 确保唯一性
|
|
43
|
+
params.taskId,
|
|
44
|
+
params.resultType,
|
|
45
|
+
params.content || null,
|
|
46
|
+
params.filePath || null,
|
|
47
|
+
metadata,
|
|
48
|
+
now
|
|
49
|
+
);
|
|
50
|
+
|
|
51
|
+
logger.info('Result created', {
|
|
52
|
+
taskId: params.taskId,
|
|
53
|
+
resultType: params.resultType,
|
|
54
|
+
});
|
|
55
|
+
} catch (error) {
|
|
56
|
+
logger.error('Failed to create result', { error: error as any, params });
|
|
57
|
+
throw error;
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
/**
|
|
62
|
+
* 根据任务 ID 查询结果
|
|
63
|
+
*/
|
|
64
|
+
async findByTaskId(taskId: string): Promise<ResultRecord[]> {
|
|
65
|
+
const stmt = this.db.prepare('SELECT * FROM results WHERE task_id = ? ORDER BY result_type');
|
|
66
|
+
const rows = stmt.all(taskId) as any[];
|
|
67
|
+
|
|
68
|
+
return rows.map((row) => ({
|
|
69
|
+
id: row.id,
|
|
70
|
+
taskId: row.task_id,
|
|
71
|
+
resultType: row.result_type,
|
|
72
|
+
content: row.content,
|
|
73
|
+
filePath: row.file_path,
|
|
74
|
+
metadata: row.metadata ? JSON.parse(row.metadata) : null,
|
|
75
|
+
createdAt: new Date(row.created_at),
|
|
76
|
+
})) as ResultRecord[];
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
/**
|
|
80
|
+
* 删除任务的所有结果
|
|
81
|
+
*/
|
|
82
|
+
async deleteByTaskId(taskId: string): Promise<void> {
|
|
83
|
+
const stmt = this.db.prepare('DELETE FROM results WHERE task_id = ?');
|
|
84
|
+
stmt.run(taskId);
|
|
85
|
+
logger.info('Results deleted', { taskId });
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
/**
|
|
89
|
+
* 关闭数据库连接
|
|
90
|
+
*/
|
|
91
|
+
close(): void {
|
|
92
|
+
this.db.close();
|
|
93
|
+
logger.info('SQLite result repository connection closed');
|
|
94
|
+
}
|
|
95
|
+
}
|