materialized view and a bit better ui
Build and Publish / Metadata (push) Successful in 2s
Build and Publish / BuildAndDeployAmd64 (push) Successful in 1m3s

This commit is contained in:
mats committed 2026-09-19 12:43:17 +02:00
1 parent 26b677154b
commit 49f9bb3458
30 files changed
+2184 -106

No files matched your search

+21
View File
@@ -117,6 +117,19 @@ type Tracker struct {
mu sync.Mutex
issues map[string]*Issue
feedback map[string]string
sink OccurrenceSink
}
// OccurrenceSink receives every recorded occurrence (already normalized) so
// it can be persisted beyond the bounded in-memory sample window. It is
// called outside the tracker lock and must not block.
type OccurrenceSink func(issueID, kind, service string, sample Sample)
// SetOccurrenceSink registers the sink; nil disables it.
func (t *Tracker) SetOccurrenceSink(fn OccurrenceSink) {
t.mu.Lock()
t.sink = fn
t.mu.Unlock()
}
// ListOptions filters and paginates the issue list. Issues remain ordered by
@@ -153,6 +166,13 @@ func NewTracker() *Tracker {
// fingerprint.
func (t *Tracker) Record(kind, service, title string, sample Sample) {
normalizeSample(&sample, title)
id, sink := t.record(kind, service, title, sample)
if sink != nil {
sink(id, kind, service, sample)
}
}
func (t *Tracker) record(kind, service, title string, sample Sample) (string, OccurrenceSink) {
id := Fingerprint(kind, service, NormalizeTitle(title))
bucket := HourBucket(sample.Timestamp)
@@ -196,6 +216,7 @@ func (t *Tracker) Record(kind, service, title string, sample Sample) {
if len(issue.Samples) > maxSamples {
issue.Samples = issue.Samples[len(issue.Samples)-maxSamples:]
}
return id, t.sink
}
// Similar returns bounded, deterministic near-match suggestions for an issue.