fix: code-review findings on overnight-jul5
- digest queue no longer dropped on failed dispatch (retry next tick) - collapsed reminders marked fired/rescheduled only after digest delivers - /tools step-up gate skipped when WebAuthn is not configured (was 403 forever) - passkey credential store rolls back memory on persist failure - auth_test fake updated for TickTrace (branch build break) Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01ASstMtsZWLSRcD1Tq8T68Q
This commit is contained in:
+10
-20
@@ -12,7 +12,6 @@ import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"log"
|
||||
"time"
|
||||
|
||||
"github.com/kami/maven/internal/store"
|
||||
@@ -143,10 +142,7 @@ func (g *Gatherer) GatherState(ctx context.Context, now time.Time) (State, []sto
|
||||
if err != nil {
|
||||
return State{}, nil, err
|
||||
}
|
||||
due, err = collapseReminders(ctx, g.store, due)
|
||||
if err != nil {
|
||||
return State{}, nil, err
|
||||
}
|
||||
due = collapseReminders(due)
|
||||
|
||||
s := State{
|
||||
Now: now,
|
||||
@@ -204,12 +200,14 @@ func readFact(ctx context.Context, s *store.Store, key string) (store.Fact, bool
|
||||
|
||||
// collapseReminders — when multiple reminders are due at once (e.g. after
|
||||
// the daemon was offline), collapse them into a single digest reminder to
|
||||
// avoid a burst of individual notifications. All original reminders are
|
||||
// marked as fired; the synthetic digest (ID=0) is what gets dispatched.
|
||||
// avoid a burst of individual notifications. The synthetic digest (ID=0)
|
||||
// carries the originals in Collapsed; the dispatcher completes them (mark
|
||||
// fired / reschedule) only after the digest actually delivers, preserving
|
||||
// the "failed send leaves the reminder pending" invariant.
|
||||
// When 0 or 1 reminders are due, returns them unchanged.
|
||||
func collapseReminders(ctx context.Context, s *store.Store, due []store.Reminder) ([]store.Reminder, error) {
|
||||
func collapseReminders(due []store.Reminder) []store.Reminder {
|
||||
if len(due) <= 1 {
|
||||
return due, nil
|
||||
return due
|
||||
}
|
||||
// Build a summary payload.
|
||||
var items []string
|
||||
@@ -235,21 +233,13 @@ func collapseReminders(ctx context.Context, s *store.Store, due []store.Reminder
|
||||
"items": items,
|
||||
})
|
||||
|
||||
// Mark originals as fired so they won't re-fire on next tick.
|
||||
for _, r := range due {
|
||||
if err := s.MarkReminder(ctx, r.ID, "fired"); err != nil {
|
||||
// Log and continue — one failure shouldn't block the digest.
|
||||
// The next tick will re-gather and re-attempt.
|
||||
log.Printf("gather: mark reminder %d fired: %v", r.ID, err)
|
||||
}
|
||||
}
|
||||
|
||||
// Return a single synthetic digest reminder. ID=0 signals "digest" to
|
||||
// the dispatcher (which skips MarkReminder for ID=0).
|
||||
// the dispatcher, which completes the Collapsed originals on success.
|
||||
return []store.Reminder{{
|
||||
ID: 0,
|
||||
FireTs: earliest,
|
||||
Payload: string(digestPayload),
|
||||
Status: "pending",
|
||||
}}, nil
|
||||
Collapsed: due,
|
||||
}}
|
||||
}
|
||||
Reference in New Issue
Block a user