store: return one calendar row per event

CalendarEvents range-scanned the key prefix and returned every historical
row, voided ones included. The facts table is append-only and the event
key is day plus summary, so moving a standup from 14:00 to 16:00 left two
rows under one key. The day plan prints a time per line, so it recited
both and told the owner he had two standups.

The query now drops voided rows, keeps the latest row within a source,
and prefers the best-evidenced source across them, so a notification
relay guessing at a meeting cannot displace the calendar read of it.
Found in review of #58.
This commit is contained in:
kami
2026-08-01 14:01:57 +04:00
parent 4f012e350c
commit 38b09ded95
2 changed files with 109 additions and 2 deletions
+49 -2
View File
@@ -90,6 +90,13 @@ func (s *Store) RecentFacts(ctx context.Context, n int) ([]Fact, error) {
// the same answer. The source stays on each Fact, along with its confidence, so
// the caller can hedge a reading it did not get from a calendar server —
// filtering by source here would have thrown that judgement away.
//
// One row per event, not one per write. The facts table is append-only, so a
// standup moved from 14:00 to 16:00 leaves two rows under the same key, and the
// day plan used to recite both as if the owner had two meetings. Voided rows
// are excluded, the latest row wins within a source, and the best-evidenced
// source wins across them — a calendar read beats the notification relay that
// guessed at the same meeting.
func (s *Store) CalendarEvents(ctx context.Context, from, to time.Time) ([]Fact, error) {
prefixFrom := calendar.KeyPrefixForDay(from)
prefixTo := calendar.KeyPrefixForDay(to)
@@ -104,7 +111,8 @@ func (s *Store) CalendarEvents(ctx context.Context, from, to time.Time) ([]Fact,
FROM facts
WHERE source IN (`+placeholders(len(sources))+`)
AND key >= ? AND key < ?
ORDER BY key`, args...)
AND id NOT IN (SELECT voids_id FROM facts WHERE voids_id IS NOT NULL)
ORDER BY key, ts, id`, args...)
if err != nil {
return nil, fmt.Errorf("calendar events: %w", err)
}
@@ -117,7 +125,46 @@ func (s *Store) CalendarEvents(ctx context.Context, from, to time.Time) ([]Fact,
}
out = append(out, f)
}
return out, rows.Err()
if err := rows.Err(); err != nil {
return nil, err
}
return latestPerCalendarKey(out), nil
}
// latestPerCalendarKey reduces the append-only rows for one day to one row per
// event key. Input must be ordered by key then oldest-first, so the last row
// seen for a key and source is that source's current value.
func latestPerCalendarKey(in []Fact) []Fact {
type slot struct {
bySource map[string]Fact
order []string
}
var keys []string
byKey := map[string]*slot{}
for _, f := range in {
s, ok := byKey[f.Key]
if !ok {
s = &slot{bySource: map[string]Fact{}}
byKey[f.Key] = s
keys = append(keys, f.Key)
}
if _, seen := s.bySource[f.Source]; !seen {
s.order = append(s.order, f.Source)
}
s.bySource[f.Source] = f
}
out := make([]Fact, 0, len(keys))
for _, k := range keys {
s := byKey[k]
best := s.bySource[s.order[0]]
for _, src := range s.order[1:] {
if s.bySource[src].Confidence > best.Confidence {
best = s.bySource[src]
}
}
out = append(out, best)
}
return out
}
// LatestFactBySource — provenance-scoped. A rule on `service_down` trusts only