5.6 KiB
5.6 KiB
Dispatcher v0.4 项目内验收证据
**记录时间:**2026-09-27 UTC。仅限单 Dispatcher、单 Agent、单 Cell、单租户的隔离 Mock;没有真实 SaaS、OSS、ECS、供应商、生产部署或真实拨号。
合同和环境
- Go
go1.27.1 linux/amd64;分支feat/dispatcher-state-v04。未修改contracts/upstream/v1/,未自动暂存或提交。 python3 scripts/validate-local-contracts.py:v0.4 发现、控制、外呼三类 Schema,10 个正例、4 个反例、20 个带 SHA-256 的文件全部通过;内嵌 Schema 与项目内源文件逐字节一致。历史 v0.1/v0.3 校验仍通过。v0.4 是项目内提案,不是 SaaS 已签收的外部合同。scripts/mq-integration-local.sh:使用本地缓存的rabbitmq:4.1-management-alpine(镜像 IDsha256:fcc273cebb0880ec25845c9bfd97687122ac9cc391538f053cb5873f4181f35f)。Mock SaaS 预建每 D 控制队列、每任务任务队列及结果队列;Dispatcher 的 RabbitMQconfigure权限为^$,不能自建任务队列。仅在隔离本机 Docker 中测试,运行后临时容器已由脚本清理。
故障与恢复矩阵
| 场景 | 本地证据与结果 |
|---|---|
| 重启全量/多页完整性 | TestRuntimeCommitsCompleteSnapshotBeforeControlAndTaskAdmission:完整页先提交,控制积压处理前准入保持关闭;TestRuntimeInterruptedSnapshotRestartsFromFirstPage:第二页故障不提交部分清单,从第一页重读。 |
| 重启不继承旧游标、在线归属变化 | TestRuntimeRestartDiscardsLiveCursorAndReloadsCompleteSnapshot、TestRuntimeCatchesChangesArrivingAfterSnapshotWatermark、TestRuntimeCatchesChangeCommittedDuringSnapshotPagination:每次重启全量,运行内存水位接续,撤销不丢;Mock HTTP 实际请求 mode=snapshot 后 after=42。 |
| 状态冲突与控制积压 | TestV04LiveChangesOnlyManageMembershipNotExistingStatus、TestRuntimeHTTPRunningAfterPauseNeedsMQResume、task_runtime_v04_control_test.go:HTTP 增量不代替 MQ resume,状态冲突关准入;控制先于任务消费。 |
| 历史 pause/resume/stop | TestOldQueuedPauseResumeStopPreservesOrderAndEveryReceipt:一个月前发出的三条命令逐条按序应用并各有回执;TestOldQueuedStopStillHangsUpAndDrains:旧 stop 不因年龄拒绝。RabbitMQ Mock 在真实预建控制队列验证旧 stop、原消息身份重排队、stop 排空未接纳任务队列并发布回执。 |
| 挂断与确认 | task_queue_v3_stop_active_test.go、task_control_v3_test.go:pause/stop 发挂断、Agent 终态未知或失败不伪报完成;resume 不挂断;stop 回执在排空后。 |
| 历史外呼、新鲜门禁、未来命令 | TestAcceptLocalV01CommandPersistsReceiptAndAcceptsOldBacklog:旧外呼不因年龄拒绝;TestOldQueuedCallRejectsCurrentlyUnlistedCallee:积压一个月仍检查当前号码白名单;TestOldQueuedCallOriginationRejectsPauseAndStop、TestOldQueuedCallOriginationRechecksBoundWindowAndClaimsOnlyOnce:旧请求在拨号前仍检查最新任务控制和绑定的时间/授权截止,不二次发起;TestFutureIssuedCallExecuteNeverReservesOrDials:未来 issued_at 不提前接纳。local_origination_quota_test.go 和 dial_policy_test.go 另覆盖额度、任务/线路时间窗及较小通话时限。 |
| 结果发送、确认丢失与复投 | TestLocalDispatcherMockSaaSEndToEndWithOutboxRecovery:先存事实再 ACK,结果队列不存在时 outbox 保留,恢复后原消息发出;确认只说明 RabbitMQ 接收,不等于 SaaS 已处理。 |
| 安全的 SQLite 局部清理 | TestTerminalTaskCacheEvictionPreservesRecoveryAndDedupRecords:只显式删除终止任务的任务配置副本,命令重复投递继续使用原身份和回执;inbox、outbox、归属与租户绑定均保留。TestTerminalTaskCacheEvictionFailClosedWhileWorkOrDeliveryIsUnknown:未知/在途执行、额度占用、上传中和待发送结果均阻断;TestTerminalTaskCacheEvictionDatabaseFailureRetainsSnapshot:SQLite 写失败回滚。无现有数据自动扫描/删除。 |
| 历史任务增长 | TestSingleTaskControlLookupUsesIndexedIdentityWithGrowingHistory:600 条归属历史,按 Dispatcher+task ID 直接查询,SQLite 查询计划使用索引而非全表扫描。 |
工具检查与覆盖率
bash scripts/acceptance-local.sh 已通过合同校验、格式检查、go vet ./...、go test -race ./...、go build ./... 和 RabbitMQ 隔离集成测试;额外执行 go test -cover 统计相关业务模块。覆盖率以实际执行测试集为准:
| 模块 | 覆盖率 | 测试集 |
|---|---|---|
internal/dispatcher |
70.3% | 隔离 RabbitMQ 集成测试 |
internal/store |
67.6% | 单元测试 |
internal/configread |
75.9% | 单元测试 |
internal/contract |
77.4% | 单元测试 |
contracts |
100.0% | 内嵌文件读写及错误路径单元测试 |
internal/mq |
67.5% | 隔离 RabbitMQ 集成测试;纯单元测试单独执行不足 65%,不能混称 |
不可代签的外部阻断
- SaaS/management 尚未提供或签收真实的 v0.4 分页快照、水位、增量保留和控制交接合同;本地 Schema 与 Mock 不证明接口真实兼容。
- SaaS 应用收讫、可查询恢复依据和最长命令重投期限尚未确认。本轮不删除执行身份、幂等、未知占用、上传、终结事实或 outbox;RabbitMQ publisher confirm 不能替代应用收讫。任务配置副本的局部清理仅能显式调用且全部条件通过,不能宣称数据库已整体清理。
- 真实供应商/OSS/ECS/生产部署与拨号、容量及切换均不在本次本地验收范围;需要独立授权和实测。