Search Apps Documentation Source Content File Folder Download Copy Actions Download

feed.gno

2.44 Kb · 86 lines
 1package nightsky
 2
 3import (
 4	"gno.land/p/nt/avl/v0"
 5	"gno.land/p/nt/ufmt/v0"
 6)
 7
 8// CaptureFeed is a bounded, newest-first collection of CaptureResult values
 9// backed by an avl.Tree. It is used for both a single telescope's history and
10// the network-wide recent feed.
11//
12// Entries are keyed by a zero-padded, monotonically increasing sequence so the
13// tree iterates in insertion order. Newest-first reads use ReverseIterate, and
14// trimming removes the lowest key (the oldest entry). This avoids the O(n)
15// slice-prepend the previous implementation paid on every insert, and only
16// loads the search path on access instead of the whole collection.
17type CaptureFeed struct {
18	tree *avl.Tree
19	seq  int
20	max  int
21}
22
23// NewCaptureFeed creates a feed that keeps at most max entries.
24func NewCaptureFeed(max int) *CaptureFeed {
25	if max <= 0 {
26		panic("capture feed size must be positive")
27	}
28	return &CaptureFeed{
29		tree: avl.NewTree(),
30		seq:  0,
31		max:  max,
32	}
33}
34
35// feedKey renders a sequence into a fixed-width key so that string ordering
36// matches numeric ordering.
37func feedKey(seq int) string {
38	return ufmt.Sprintf("%020d", seq)
39}
40
41// Add inserts a capture as the newest entry and trims the oldest if the feed is
42// over capacity.
43func (f *CaptureFeed) Add(c CaptureResult) {
44	f.seq++
45	f.tree.Set(feedKey(f.seq), c)
46
47	for f.tree.Size() > f.max {
48		oldest, _ := f.tree.GetByIndex(0)
49		f.tree.Remove(oldest)
50	}
51}
52
53// Len returns the number of stored captures.
54func (f *CaptureFeed) Len() int {
55	return f.tree.Size()
56}
57
58// Latest returns the most recent capture, if any.
59func (f *CaptureFeed) Latest() (CaptureResult, bool) {
60	if f.tree.Size() == 0 {
61		return CaptureResult{}, false
62	}
63	_, value := f.tree.GetByIndex(f.tree.Size() - 1)
64	return value.(CaptureResult), true
65}
66
67// RemoveAt removes the index-th newest capture (0 = most recent). It reports
68// whether a capture was removed. Used for moderation of individual entries.
69func (f *CaptureFeed) RemoveAt(index int) bool {
70	size := f.tree.Size()
71	if index < 0 || index >= size {
72		return false
73	}
74	// Newest-first index i maps to ascending-key index (size-1-i).
75	key, _ := f.tree.GetByIndex(size - 1 - index)
76	_, removed := f.tree.Remove(key)
77	return removed
78}
79
80// IterateNewest calls cb for each capture from newest to oldest. Return true
81// from cb to stop early.
82func (f *CaptureFeed) IterateNewest(cb func(c CaptureResult) bool) {
83	f.tree.ReverseIterate("", "", func(_ string, value any) bool {
84		return cb(value.(CaptureResult))
85	})
86}