You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
fix(exchange): in-flight reservations disappear from daily headroom at UTC rollover #657
Active RI exchange reservations can stop counting at midnight UTC before their execution settles. This is separate from the same-day AUTO concurrency fix in LeanerCloud/cloud-commitments-go#41.
Current behaviour
At platform baseline 3131779, internal/config/store_postgres.go:3059-3065 sums completed and processing rows only when COALESCE(completed_at,updated_at) lies inside the requested UTC day. The go#41 atomic reservation change reuses this daily-window policy, so an unsettled prior-day processing row remains excluded after rollover.
Steps to verify the gap
Use a frozen clock, fixture execution and real local PostgreSQL; do not make purchases. Hold a day-A AUTO reservation of1000 in execution across midnight. A day-B daily read sees zero from that hold and permits another1000 reservation. If both fresh quotes settle for950 on dayB, the day-B accepted total becomes1900 under cap1000. This is a code-derived scenario, not an observed production purchase.
Expected behaviour
Active reservations remain counted conservatively until reconciled, including across UTC midnight. Completed prior-day spend resets according to a clearly defined acceptance-day policy.
Proposed fix and acceptance
Define acceptance-day accounting and keep active processing holds included across rollover under the same global reservation lock. Add frozen-clock real-database coverage spanning midnight, exact UTC boundaries, completed prior-day reset and active-hold retention. Relevant path: internal/config/store_postgres.go, GetRIExchangeDailySpend and atomic ReserveRIExchange.
References and severity
Refs LeanerCloud/cloud-commitments-go#41. High severity when triggered; limited timing-dependent impact. No failing regression or production incident is claimed by this tracking issue.
Fix: the daily spend query now counts every processing row regardless of day (an unsettled hold), and completed rows on their completed_at UTC day.
Verified (real PostgreSQL 16, local image, no purchases or cloud calls):
a frozen day-B read counts a day-A unsettled $1000 hold and not the completed day-A $500
exact UTC boundary: completed at 23:59:59.999999 counts for day A only, at 00:00:00 for day B only
a 30h-old processing hold still reduces headroom for a new AUTO reservation
mutation check: reverting to the day-windowed query fails the rollover tests (independent reviewer reproduced); all 25 required CI checks green at the merged head
Test note: the table has a BEFORE UPDATE trigger that rewrites updated_at, so back-dating in tests bypasses it with session_replication_role=replica on the dedicated test DB.
Known consequence: a row stuck in processing (crash mid-exchange) holds headroom on every later day until settled; tracked in #692. Recommend closing.
Activity
fix(exchange): make the approval lock test deterministic and hide res…
test(exchange): fix lint findings in the approved reservation integra…
test(exchange): avoid account-id literals the git-secrets allowlist r…
fix(exchange): reserve approved RI exchange ceiling atomically and ke…
cristim commentedon Oct 9, 2026
Deployed: merged in #690 as cf0b1a0 (squash, head 6bafb61).
Fix: the daily spend query now counts every
processingrow regardless of day (an unsettled hold), andcompletedrows on theircompleted_atUTC day.Verified (real PostgreSQL 16, local image, no purchases or cloud calls):
Test note: the table has a BEFORE UPDATE trigger that rewrites updated_at, so back-dating in tests bypasses it with session_replication_role=replica on the dedicated test DB.
Known consequence: a row stuck in processing (crash mid-exchange) holds headroom on every later day until settled; tracked in #692. Recommend closing.