v2.0.0: claims model - signed MMUR2 votes in a truth DB, merged view in a rebuildable cache DB; POST /api/claims, claims and merge routes, unsigned writes answer 410
Build and Push Docker Image / build (push) Successful in 5m1s

This commit is contained in:
Worph
2026-10-25 17:36:00 +00:00
parent b0adefb97b
commit 84af298792
78 changed files with 7203 additions and 5617 deletions
+22 -9
View File
@@ -112,7 +112,15 @@ func (s *Server) streamSSE(w http.ResponseWriter, r *http.Request, stream string
}
cursor = head
} else {
cursor = resolveStartCursor(ctx, store, stream, lastID, w, flusher)
if rebuilt := s.storage.RebuiltAt(); stream == storage.MetaEventsStream && lastID != "" && rebuilt != "" &&
compareStreamIDs(lastID, rebuilt) < 0 {
// The cache was rebuilt after this cursor: the rebuild published no
// per-key events, so the consumer must take a snapshot.
writeGap(w, flusher, lastID, rebuilt, "rebuild")
cursor = "0"
} else {
cursor = resolveStartCursor(ctx, store, stream, lastID, w, flusher)
}
}
lastWrite := time.Now()
@@ -256,14 +264,7 @@ func resolveStartCursor(ctx context.Context, store *kv.Store, stream, lastID str
}
// Cursor was trimmed. Emit a gap event so consumers that care can react.
gap := map[string]string{
"requested": lastID,
"resumeFrom": oldest,
"reason": "retention",
}
payload, _ := json.Marshal(gap)
fmt.Fprintf(w, "event: gap\ndata: %s\n\n", string(payload))
flusher.Flush()
writeGap(w, flusher, lastID, oldest, "retention")
// Return "0" so the next read picks up entries starting from the
// stream's true minimum — including `oldest` itself.
@@ -327,3 +328,15 @@ func parseStreamID(id string) (int64, int64) {
}
return ms, seq
}
// writeGap emits the synthetic `gap` event: the consumer's cursor cannot be
// resumed losslessly and it should take a snapshot (Last-Event-ID: 0).
func writeGap(w http.ResponseWriter, flusher http.Flusher, requested, resumeFrom, reason string) {
payload, _ := json.Marshal(map[string]string{
"requested": requested,
"resumeFrom": resumeFrom,
"reason": reason,
})
fmt.Fprintf(w, "event: gap\ndata: %s\n\n", string(payload))
flusher.Flush()
}