initial public relay build repo
ci / build (push) Successful in 2m3s
ci / image (push) Successful in 1m4s

This commit is contained in:
2026-07-24 13:11:06 -04:00
commit 294616642f
24 changed files with 2957 additions and 0 deletions
+116
View File
@@ -0,0 +1,116 @@
package retention
import (
"testing"
"time"
"fiatjaf.com/nostr"
"fiatjaf.com/nostr/eventstore/slicestore"
)
func mkStore(t *testing.T) *slicestore.SliceStore {
t.Helper()
s := &slicestore.SliceStore{}
if err := s.Init(); err != nil {
t.Fatalf("init: %v", err)
}
return s
}
func save(t *testing.T, s *slicestore.SliceStore, sk nostr.SecretKey, kind nostr.Kind, createdAt nostr.Timestamp) nostr.ID {
t.Helper()
e := nostr.Event{Kind: kind, CreatedAt: createdAt, Tags: nostr.Tags{{"h", "g"}}}
if kind == nostr.KindSimpleGroupChatMessage {
e.Content = "msg"
}
if err := e.Sign(sk); err != nil {
t.Fatalf("sign: %v", err)
}
if err := s.SaveEvent(e); err != nil {
t.Fatalf("save: %v", err)
}
return e.ID
}
func count(s *slicestore.SliceStore, kinds ...nostr.Kind) int {
n := 0
for range s.QueryEvents(nostr.Filter{Kinds: kinds}, 1_000_000) {
n++
}
return n
}
func TestRetentionPrunesOldChatByAge(t *testing.T) {
s := mkStore(t)
sk := nostr.Generate()
now := time.Unix(1_700_000_000, 0)
old := nostr.Timestamp(now.Add(-48 * time.Hour).Unix())
fresh := nostr.Timestamp(now.Add(-1 * time.Hour).Unix())
save(t, s, sk, nostr.KindSimpleGroupChatMessage, old)
save(t, s, sk, nostr.KindSimpleGroupChatMessage, fresh)
deleted := Sweep(s, Config{MaxAge: 24 * time.Hour}, now)
if deleted != 1 {
t.Fatalf("expected 1 pruned, got %d", deleted)
}
if c := count(s, nostr.KindSimpleGroupChatMessage); c != 1 {
t.Fatalf("expected 1 chat remaining, got %d", c)
}
}
func TestRetentionPrunesSurplusByCount(t *testing.T) {
s := mkStore(t)
sk := nostr.Generate()
now := time.Unix(1_700_000_000, 0)
for i := 0; i < 5; i++ {
save(t, s, sk, nostr.KindSimpleGroupChatMessage, nostr.Timestamp(1_700_000_000+int64(i)))
}
deleted := Sweep(s, Config{MaxMessages: 2}, now)
if deleted != 3 {
t.Fatalf("expected 3 pruned, got %d", deleted)
}
if c := count(s, nostr.KindSimpleGroupChatMessage); c != 2 {
t.Fatalf("expected 2 chats remaining, got %d", c)
}
}
func TestRetentionNeverPrunesManagementEvents(t *testing.T) {
s := mkStore(t)
sk := nostr.Generate()
now := time.Unix(1_700_000_000, 0)
ancient := nostr.Timestamp(now.Add(-1000 * time.Hour).Unix())
// Very old management + metadata events must be preserved.
save(t, s, sk, nostr.KindSimpleGroupCreateGroup, ancient)
save(t, s, sk, nostr.KindSimpleGroupPutUser, ancient)
save(t, s, sk, nostr.KindSimpleGroupJoinRequest, ancient)
save(t, s, sk, nostr.KindSimpleGroupMetadata, ancient)
save(t, s, sk, nostr.KindSimpleGroupAdmins, ancient)
save(t, s, sk, nostr.KindSimpleGroupMembers, ancient)
// An old chat that SHOULD be pruned.
save(t, s, sk, nostr.KindSimpleGroupChatMessage, ancient)
deleted := Sweep(s, Config{MaxAge: time.Hour, MaxMessages: 1}, now)
if deleted != 1 {
t.Fatalf("expected only the 1 chat pruned, got %d", deleted)
}
// All 6 management/metadata events survive.
mgmt := count(s,
nostr.KindSimpleGroupCreateGroup, nostr.KindSimpleGroupPutUser,
nostr.KindSimpleGroupJoinRequest, nostr.KindSimpleGroupMetadata,
nostr.KindSimpleGroupAdmins, nostr.KindSimpleGroupMembers)
if mgmt != 6 {
t.Fatalf("management events must never be pruned; have %d/6", mgmt)
}
}
func TestRetentionDisabledIsNoop(t *testing.T) {
s := mkStore(t)
sk := nostr.Generate()
now := time.Unix(1_700_000_000, 0)
save(t, s, sk, nostr.KindSimpleGroupChatMessage, nostr.Timestamp(1))
if d := Sweep(s, Config{}, now); d != 0 {
t.Fatalf("no limits should prune nothing, got %d", d)
}
}