Skip to content

GH-5268: fix(briefs): receipts digest — record SentAt = query End to close the sub-second (End, SentAt) skip window - #5271

Merged
alekspetrov merged 1 commit into
mainfrom
pilot/GH-5268
Aug 30, 2026
Merged

GH-5268: fix(briefs): receipts digest — record SentAt = query End to close the sub-second (End, SentAt) skip window#5271
alekspetrov merged 1 commit into
mainfrom
pilot/GH-5268

Conversation

@alekspetrov

Copy link
Copy Markdown
Collaborator

Summary

Automated PR created by Pilot for task GH-5268.

Closes #5268

Changes

GitHub Issue GH-5268: fix(briefs): receipts digest — record SentAt = query End to close the sub-second (End, SentAt) skip window

Problem

Follow-up from PR#5258 re-review (note-level, non-blocking): in ReceiptsScheduler.runDigest (internal/briefs/receipts.go), the executions query uses End: now captured at the top of the function, but after delivery the brief_history record is stamped with a fresh time.Now():

record := &memory.BriefRecord{
    SentAt:    time.Now(),   // later than the query's End by delivery latency
    ...
}

The next digest windows [lastRecord.SentAt, now). A run whose completed_at lands in the gap (End, SentAt) — i.e. completes during the ~100–500ms of Telegram delivery — is after this digest's window and before the next one's start, so it is never receipted. Breaks the exactly-once guarantee established by GH-5261, just at sub-second scale.

Fix

One line: stamp the record with the same now used as the query End (SentAt: now), so consecutive windows tile exactly: [prev.End, now).

Acceptance

  1. runDigest records SentAt equal to the query's End bound (same time.Time value).
  2. Test: an execution with completed_at exactly between the first digest's query End and its (formerly later) send-completion time appears in the second digest — extend TestReceiptsSchedulerRunNow_InFlightRunAppearsInNextDigest or add a sibling.
  3. make lint && make test green; no other behavior change.

Refs

…livery time.Now() (GH-5268)

Closes the sub-second (End, SentAt) skip window: an execution completing
during Telegram delivery latency fell after one digest's End and before
the next digest's start, so it was never receipted. Consecutive windows
now tile exactly as [prev.End, now).
@codecov-commenter

Copy link
Copy Markdown

⚠️ Please install the 'codecov app svg image' to ensure uploads and comments are reliably processed by Codecov.

Codecov Report

✅ All modified and coverable lines are covered by tests.

📢 Thoughts on this report? Let us know!

@alekspetrov
alekspetrov merged commit 77c3d54 into main Aug 30, 2026
9 checks passed
@alekspetrov
alekspetrov deleted the pilot/GH-5268 branch August 30, 2026 16:59
@alekspetrov

Copy link
Copy Markdown
Collaborator Author

Post-merge review — APPROVE

Exactly the requested fix, nothing more: SentAt stamped with the same now used as the executions query's End bound, so consecutive digest windows tile as [prev.End, now) with no sub-second gap.

Test quality is the highlight: TestReceiptsSchedulerRunNow_SentAtMatchesQueryEnd reproduces the actual race — the mock sender's onSend hook inserts a completing execution synchronously mid-SendBriefMessage, i.e. strictly after the query ran and strictly before SentAt is stamped. That's the exact (End, SentAt) dead window from GH-5268, and the test proves the row surfaces in digest 2. Boundary semantics verified: query is completed_at >= start AND < End, so an exactly-at-End row lands in the next digest only — no gap, no duplicate.

All 3 acceptance criteria met; 8/8 checks green; the only non-receipts change is the additive optional onSend hook on the shared mock. No follow-ups.

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.

fix(briefs): receipts digest — record SentAt = query End to close the sub-second (End, SentAt) skip window

2 participants