interface.go raw
1 package database
2
3 import (
4 "context"
5 "io"
6 "time"
7
8 "next.orly.dev/pkg/database/indexes/types"
9 "next.orly.dev/pkg/nostr/encoders/event"
10 "next.orly.dev/pkg/nostr/encoders/filter"
11 "next.orly.dev/pkg/nostr/encoders/tag"
12 "next.orly.dev/pkg/interfaces/store"
13 )
14
15 // Database defines the interface that all database implementations must satisfy.
16 // This allows switching between different storage backends (badger, neo4j, etc.)
17 type Database interface {
18 // Core lifecycle methods
19 Path() string
20 Init(path string) error
21 Sync() error
22 Close() error
23 Wipe() error
24 SetLogLevel(level string)
25 Ready() <-chan struct{} // Returns a channel that closes when database is ready to serve requests
26
27 // Event storage and retrieval
28 SaveEvent(c context.Context, ev *event.E) (exists bool, err error)
29 GetSerialsFromFilter(f *filter.F) (serials types.Uint40s, err error)
30 WouldReplaceEvent(ev *event.E) (bool, types.Uint40s, error)
31
32 QueryEvents(c context.Context, f *filter.F) (evs event.S, err error)
33 QueryAllVersions(c context.Context, f *filter.F) (evs event.S, err error)
34 QueryEventsWithOptions(c context.Context, f *filter.F, includeDeleteEvents bool, showAllVersions bool) (evs event.S, err error)
35 QueryDeleteEventsByTargetId(c context.Context, targetEventId []byte) (evs event.S, err error)
36 QueryForSerials(c context.Context, f *filter.F) (serials types.Uint40s, err error)
37 QueryForIds(c context.Context, f *filter.F) (idPkTs []*store.IdPkTs, err error)
38
39 CountEvents(c context.Context, f *filter.F) (count int, approximate bool, err error)
40
41 FetchEventBySerial(ser *types.Uint40) (ev *event.E, err error)
42 FetchEventsBySerials(serials []*types.Uint40) (events map[uint64]*event.E, err error)
43
44 GetSerialById(id []byte) (ser *types.Uint40, err error)
45 GetSerialsByIds(ids *tag.T) (serials map[string]*types.Uint40, err error)
46 GetSerialsByIdsWithFilter(ids *tag.T, fn func(ev *event.E, ser *types.Uint40) bool) (serials map[string]*types.Uint40, err error)
47 GetSerialsByRange(idx Range) (serials types.Uint40s, err error)
48
49 GetFullIdPubkeyBySerial(ser *types.Uint40) (fidpk *store.IdPkTs, err error)
50 GetFullIdPubkeyBySerials(sers []*types.Uint40) (fidpks []*store.IdPkTs, err error)
51
52 // Event deletion
53 DeleteEvent(c context.Context, eid []byte) error
54 DeleteEventBySerial(c context.Context, ser *types.Uint40, ev *event.E) error
55 DeleteExpired()
56 ProcessDelete(ev *event.E, admins [][]byte) error
57 CheckForDeleted(ev *event.E, admins [][]byte) error
58
59 // Import/Export
60 Import(rr io.Reader)
61 Export(c context.Context, w io.Writer, pubkeys ...[]byte)
62 ImportEventsFromReader(ctx context.Context, rr io.Reader) error
63 ImportEventsFromStrings(ctx context.Context, eventJSONs []string, policyManager interface{ CheckPolicy(action string, ev *event.E, pubkey []byte, remote string) (bool, error) }) error
64
65 // Relay identity
66 GetRelayIdentitySecret() (skb []byte, err error)
67 SetRelayIdentitySecret(skb []byte) error
68 GetOrCreateRelayIdentitySecret() (skb []byte, err error)
69
70 // Markers (metadata key-value storage)
71 SetMarker(key string, value []byte) error
72 GetMarker(key string) (value []byte, err error)
73 HasMarker(key string) bool
74 DeleteMarker(key string) error
75
76 // Subscriptions (payment-based access control)
77 GetSubscription(pubkey []byte) (*Subscription, error)
78 IsSubscriptionActive(pubkey []byte) (bool, error)
79 ExtendSubscription(pubkey []byte, days int) error
80 RecordPayment(pubkey []byte, amount int64, invoice, preimage string) error
81 GetPaymentHistory(pubkey []byte) ([]Payment, error)
82 ExtendBlossomSubscription(pubkey []byte, tier string, storageMB int64, daysExtended int) error
83 GetBlossomStorageQuota(pubkey []byte) (quotaMB int64, err error)
84 IsFirstTimeUser(pubkey []byte) (bool, error)
85
86 // Paid ACL (Lightning payment-gated access)
87 SavePaidSubscription(sub *PaidSubscription) error
88 GetPaidSubscription(pubkeyHex string) (*PaidSubscription, error)
89 DeletePaidSubscription(pubkeyHex string) error
90 ListPaidSubscriptions() ([]*PaidSubscription, error)
91 ClaimAlias(alias, pubkeyHex string) error
92 GetAliasByPubkey(pubkeyHex string) (string, error)
93 GetPubkeyByAlias(alias string) (string, error)
94 IsAliasTaken(alias string) (bool, error)
95
96 // NIP-43 Invite-based ACL
97 AddNIP43Member(pubkey []byte, inviteCode string) error
98 RemoveNIP43Member(pubkey []byte) error
99 IsNIP43Member(pubkey []byte) (isMember bool, err error)
100 GetNIP43Membership(pubkey []byte) (*NIP43Membership, error)
101 GetAllNIP43Members() ([][]byte, error)
102 StoreInviteCode(code string, expiresAt time.Time) error
103 ValidateInviteCode(code string) (valid bool, err error)
104 DeleteInviteCode(code string) error
105 PublishNIP43MembershipEvent(kind int, pubkey []byte) error
106
107 // Migrations (version tracking for schema updates)
108 RunMigrations()
109
110 // Query cache methods
111 GetCachedJSON(f *filter.F) ([][]byte, bool)
112 CacheMarshaledJSON(f *filter.F, marshaledJSON [][]byte)
113 GetCachedEvents(f *filter.F) (event.S, bool)
114 CacheEvents(f *filter.F, events event.S)
115 InvalidateQueryCache()
116
117 // Access tracking for storage management (garbage collection based on access patterns)
118 // RecordEventAccess records an access to an event by a connection.
119 // The connectionID is used to deduplicate accesses from the same connection.
120 RecordEventAccess(serial uint64, connectionID string) error
121 // GetEventAccessInfo returns the last access time and access count for an event.
122 GetEventAccessInfo(serial uint64) (lastAccess int64, accessCount uint32, err error)
123 // GetLeastAccessedEvents returns event serials sorted by coldness (oldest/lowest access).
124 // limit: max events to return, minAgeSec: minimum age in seconds since last access.
125 GetLeastAccessedEvents(limit int, minAgeSec int64) (serials []uint64, err error)
126
127 // Utility methods
128 EventIdsBySerial(start uint64, count int) (evs []uint64, err error)
129
130 // Blob storage (Blossom)
131 SaveBlob(sha256Hash []byte, data []byte, pubkey []byte, mimeType string, extension string) error
132 SaveBlobMetadata(sha256Hash []byte, size int64, pubkey []byte, mimeType string, extension string) error
133 GetBlob(sha256Hash []byte) (data []byte, metadata *BlobMetadata, err error)
134 HasBlob(sha256Hash []byte) (exists bool, err error)
135 DeleteBlob(sha256Hash []byte, pubkey []byte) error
136 ListBlobs(pubkey []byte, since, until int64) ([]*BlobDescriptor, error)
137 ListAllBlobs() ([]*BlobDescriptor, error)
138 GetBlobMetadata(sha256Hash []byte) (*BlobMetadata, error)
139 GetTotalBlobStorageUsed(pubkey []byte) (totalMB int64, err error)
140 SaveBlobReport(sha256Hash []byte, reportData []byte) error
141 ListAllBlobUserStats() ([]*UserBlobStats, error)
142 ReconcileBlobMetadata() (reconciled int, err error)
143
144 // Thumbnail caching
145 GetThumbnail(key string) (data []byte, err error)
146 SaveThumbnail(key string, data []byte) error
147
148 // NRC (Nostr Relay Connect) client management
149 CreateNRCConnection(label string, createdBy []byte) (*NRCConnection, error)
150 GetNRCConnection(id string) (*NRCConnection, error)
151 GetNRCConnectionByDerivedPubkey(derivedPubkey []byte) (*NRCConnection, error)
152 SaveNRCConnection(conn *NRCConnection) error
153 DeleteNRCConnection(id string) error
154 GetAllNRCConnections() ([]*NRCConnection, error)
155 GetNRCAuthorizedSecrets() (map[string]string, error)
156 UpdateNRCConnectionLastUsed(id string) error
157 GetNRCConnectionURI(conn *NRCConnection, relayPubkey []byte, rendezvousURL string) (string, error)
158 }
159