Skip to content

[4/7] feat(core-intake): quota, admission and dual-channel routing - #1809

Merged
Nexisato merged 6 commits into
feat/core/io-modelfrom
feat/core/io-4-intake
Oct 29, 2026
Merged

Nexisato merged 6 commits into
feat/core/io-modelfrom
feat/core/io-4-intake

Conversation

@Nexisato

@Nexisato Nexisato commented Oct 29, 2026 •

Copy link
Copy Markdown
Collaborator

概要

新增会话级的接收与分流层:一条 record 进来先预留容量,再分配 storeSeq 并同时进入本地落盘与上传两条通道。本地 run-*.swanlab 是唯一事实源;容量不足只反压,不丢记录;上传暂停期间尚未确认刷盘的记录在本地写失败时会按序回收补传。

变更内容

包 文件 职责
internal/budget budget.go 会话级条数 + 字节双限账本;TryAcquire / Acquire / Release / Adjust 与水位统计
internal/buffer buffer.go 两阶段 Reserve / Commit;storeSeq 分配;本地/上传双通道路由;容量预留与反压
internal/buffer recovery.go 暂停投递、未确认记录跟踪、pauseStoreSeq 与本地失效后的按序回收补传

关键行为:

  • 两阶段接收:Reserve 只读预检并预留本地通道、上传预算与上传槽位,失败零副作用;Commit 分配 storeSeq、写本地并分流。Demand 分别声明立即/延迟记录的条数与字节估算,暂停批次只按延迟记录自身占用配额。
  • 容量不足只反压:本地或上传通道满时在 QueueWait 内有界等待,仍失败返回 ErrOverloaded;单批超过通道容量返回 ErrBatchTooLarge。只有 AsyncWriter 真实写入失败才置 storeDegraded,运行期不会修改 skip_store 等启动配置。
  • 暂停与恢复:上传预算满且本地副本完整时暂停投递,全局暂停状态与 pauseStoreSeq 在记录真正提交时才发布;被放弃、空提交或校验失败的票据只归还容量,不会遗留暂停。恢复后旧票据若晚到,会开启新的回填区间。
  • END 保存持有配额:SAVE_POLICY_END 记录从 Reserve 起按自身条数与字节占用上传预算,直到 Close 上传终结;暂停期间预算不足直接反压,不会以未计费状态在内存中无界堆积,也不会被同批立即记录的字节拖累。
  • 本地失效兜底:暂停期间已 Commit 但尚未确认刷盘的记录会保留到 Flushed() 推进;写盘失败后进入统一回收队列,后续批次排在队尾按 FIFO 补传,不会越过更早的记录。宁可短暂超出预算也不丢记录;降级后不再使用暂停快路径,继续受上传预算约束。
  • 分流规则:数据类记录双通道;Start(-1) / Finish(-2) 仅本地;崩溃 error_log 仅上传;SAVE_POLICY_END 先落本地、Close 时再上传。
  • 收尾:Close 先补投回收队列与暂存的 END 保存,再关闭上传通道;被取消时两个队列都会恢复,重试不会丢失记录。

验证

  • go build ./...、go test -race ./... 通过;golangci-lint run 0 issues。
  • 覆盖率:budget 100%,buffer 88.9%。
  • 回归覆盖:放弃暂停票据、暂停后 Resume 与旧票据竞争、暂停后本地降级、降级补传的 FIFO 顺序、连续暂停 END 保存的预算约束、大立即记录叠加小 END 保存的混合批次、上传通道满时的反压,以及真实 AsyncWriter 写失败后的记录回收。
  • S4 冒烟(本地临时目录,无网络):暂停投递、storeDegraded 后反压、慢盘反压三种场景通过;落盘文件经 Python DataStoreReader 回读,num 序列连续无洞。
  • S1 / S3 回归通过。

范围说明

  • 本 PR 只交付 budget + intake;攒批、分轨、HTTP 上传在后续 PR。
  • internal/config 仅补充 SkipStore 的启动期/运行期边界注释。

Base: feat/core/io-model.

- add internal/budget: session-level record/byte quota with acquire, release and estimate adjustment
- add internal/buffer: two-phase intake, storeSeq assignment, pause and degraded backpressure, routing to store/upload
- cover quota conservation, backpressure, routing and Close paths
@Nexisato
Nexisato marked this pull request as ready for review October 29, 2026 05:29
- 暂停记录保留到 Flushed 确认,写盘失败由 DrainRecovery 补传
- Resume 后的旧票据开启新的回填区间
- 暂停后降级仍受上传预算约束
- 上传通道槽位纳入预留,Commit 不再持锁等待
- 归并容量等待与回收发送逻辑,恢复逻辑拆到 recovery.go
- 降级批次并入回收队列按序补传,不再越过更早的暂停记录
- Demand 拆分 Deferred:END 保存从 Reserve 起占用配额,预算不足直接反压
- 全局暂停状态推迟到 Commit 发布,放弃票据不再遗留 paused
- Close 补投回收记录被取消时一并归还 pending
- Demand 增加 DeferredBytes,Bytes 仅覆盖立即上传记录
- 暂停批次只按延迟记录自身的条数与字节申请配额
- 补充大立即记录叠加小 END 保存的回归测试
@Nexisato
Nexisato merged commit 7e0e1a3 into feat/core/io-model Oct 29, 2026
6 checks passed
@Nexisato
Nexisato deleted the feat/core/io-4-intake branch October 29, 2026 09:11
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant