feat(ledger): quiet idle outbox polling

This commit is contained in:
Hermes Agent
2026-09-20 21:57:30 +09:00
parent 62e4f57c2b
commit a2be76b199
14 changed files with 437 additions and 15 deletions
+43
View File
@@ -0,0 +1,43 @@
---
id: "req-0012"
status: approved
discovery: "dcy-0012"
criteria:
create:
- "ac-0040"
update: []
retire: []
satisfy:
- "ac-0029"
---
# Ledger outbox idle poll 로그 억제와 관측 보존
## Objective
정상 idle 상태의 ledger outbox poll이 초 단위 INFO 로그를 만들지 않게 하면서, process-lifetime claim·outcome 통계를 operator가 instance별로 조회할 수 있게 한다. 실제 work와 failure는 correlation 가능한 sanitized observability를 유지하고 기존 lease·ownership·retry 동작은 변경하지 않는다.
## Scope
- pending row가 없는 `LedgerWriter.run_once()`는 `claim:empty`를 누적하지만 INFO claim log를 남기지 않는다.
- non-empty batch claim INFO는 configured `instance_key`, non-zero `count`, `limit`, 해당 batch의 non-empty correlation ID를 repository claim 순서와 같은 `correlation_ids` JSON string array로 제공한다.
- `trex.slots.req`의 `spy=true` 응답에 top-level `ledger_outbox_metrics` process-lifetime snapshot을 additive로 제공한다. `spy=false` 응답에는 해당 key를 포함하지 않는다.
- metrics reader가 없거나 조회에 실패해도 slots 조회는 성공하며 stable unavailable snapshot을 반환한다.
- `_ledger_loop()`의 예상 밖 writer exception은 stable reason, configured `instance_key`, exception class name만 ERROR로 남기고 다음 poll을 계속한다.
- `AC-0029`의 ownership, active lease exclusion, stale outcome fencing, foreign/unowned isolation, retry 및 terminal outcome 계약을 회귀 검증한다.
- `docs/runtime-flows.md`와 `docs/interface-contract.md`를 idle suppression, operator-only metrics, process-lifetime scope, fixed cadence와 sanitized writer exception contract에 맞게 동기화한다.
## Constraints
- metrics snapshot은 해당 daemon process의 configured instance writer만 집계하는 process-lifetime 값이며 process restart 시 0부터 시작한다.
- counter는 누락 없는 0 이상의 정수이고 호출자가 내부 mutable state를 변경할 수 없는 새 snapshot이어야 한다.
- log, metric, status에는 credential, account identifier, token, password, DSN, provider payload, raw exception message 또는 traceback을 포함하지 않는다.
- fixed `ledger_interval_sec`, retry `next_retry_at`, claim lease, ownership/filtering, persistence schema와 ledger API contract는 변경하지 않는다.
- PostgreSQL multi-instance verification은 disposable fixture가 있을 때 실행하며 fixture 부재로 skip되면 환경 미검증으로 명시한다.
## Non-Goals
- adaptive idle backoff 또는 event-driven wakeup을 추가하지 않는다.
- 범용 metrics exporter나 신규 transport/status RPC를 만들지 않는다.
- portfolio/business-state, broker order/fill, correlation-ID format, dead-letter policy를 변경하지 않는다.
- production deployment, live database migration, backfill 또는 remediation을 수행하지 않는다.