You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
223 lines
5.9 KiB
223 lines
5.9 KiB
// Package store is an interface and ancillary helpers and types for defining a |
|
// series of API elements for abstracting the event storage from the |
|
// implementation. |
|
// |
|
// It is composed so that the top-level interface can be |
|
// partially implemented if need be. |
|
package store |
|
|
|
import ( |
|
"context" |
|
"io" |
|
|
|
"next.orly.dev/app/config" |
|
"next.orly.dev/pkg/database/indexes/types" |
|
"git.mleku.dev/mleku/nostr/encoders/event" |
|
"git.mleku.dev/mleku/nostr/encoders/filter" |
|
"git.mleku.dev/mleku/nostr/encoders/tag" |
|
ntypes "git.mleku.dev/mleku/nostr/types" |
|
) |
|
|
|
// I am a type for a persistence layer for nostr events handled by a relay. |
|
type I interface { |
|
Pather |
|
io.Closer |
|
Pather |
|
Wiper |
|
Querier |
|
Querent |
|
Deleter |
|
Saver |
|
Importer |
|
Exporter |
|
Syncer |
|
LogLeveler |
|
EventIdSerialer |
|
Initer |
|
SerialByIder |
|
} |
|
|
|
type Initer interface { |
|
Init(path string) (err error) |
|
} |
|
|
|
type Pather interface { |
|
// Path returns the directory of the database. |
|
Path() (s string) |
|
} |
|
|
|
type Wiper interface { |
|
// Wipe deletes everything in the database. |
|
Wipe() (err error) |
|
} |
|
|
|
type Querent interface { |
|
// QueryEvents is invoked upon a client's REQ as described in NIP-01. It |
|
// returns the matching events in reverse chronological order in a slice. |
|
QueryEvents(c context.Context, f *filter.F) (evs event.S, err error) |
|
} |
|
|
|
type Accountant interface { |
|
EventCount() (count uint64, err error) |
|
} |
|
|
|
// IdPkTs holds event reference data with slice fields for backward compatibility. |
|
// For new code preferring stack-allocated, copy-on-assignment semantics, |
|
// use the IDFixed() and PubFixed() methods or convert to EventRef. |
|
type IdPkTs struct { |
|
Id []byte |
|
Pub []byte |
|
Ts int64 |
|
Ser uint64 |
|
} |
|
|
|
// IDFixed returns the event ID as a fixed-size array (stack-allocated, copied on assignment). |
|
func (i *IdPkTs) IDFixed() ntypes.EventID { |
|
return ntypes.EventIDFromBytes(i.Id) |
|
} |
|
|
|
// PubFixed returns the pubkey as a fixed-size array (stack-allocated, copied on assignment). |
|
func (i *IdPkTs) PubFixed() ntypes.Pubkey { |
|
return ntypes.PubkeyFromBytes(i.Pub) |
|
} |
|
|
|
// IDHex returns the event ID as a lowercase hex string. |
|
func (i *IdPkTs) IDHex() string { |
|
return ntypes.EventIDFromBytes(i.Id).Hex() |
|
} |
|
|
|
// PubHex returns the pubkey as a lowercase hex string. |
|
func (i *IdPkTs) PubHex() string { |
|
return ntypes.PubkeyFromBytes(i.Pub).Hex() |
|
} |
|
|
|
// ToEventRef converts IdPkTs to an EventRef (fully stack-allocated). |
|
func (i *IdPkTs) ToEventRef() EventRef { |
|
return NewEventRef(i.Id, i.Pub, i.Ts, i.Ser) |
|
} |
|
|
|
// EventRef is a stack-friendly event reference using fixed-size arrays. |
|
// Total size: 80 bytes (32+32+8+8), fits in a cache line, copies stay on stack. |
|
// Use this type when you need safe, immutable event references. |
|
type EventRef struct { |
|
id ntypes.EventID // 32 bytes |
|
pub ntypes.Pubkey // 32 bytes |
|
ts int64 // 8 bytes |
|
ser uint64 // 8 bytes |
|
} |
|
|
|
// NewEventRef creates an EventRef from byte slices. |
|
// The slices are copied into fixed-size arrays. |
|
func NewEventRef(id, pub []byte, ts int64, ser uint64) EventRef { |
|
return EventRef{ |
|
id: ntypes.EventIDFromBytes(id), |
|
pub: ntypes.PubkeyFromBytes(pub), |
|
ts: ts, |
|
ser: ser, |
|
} |
|
} |
|
|
|
// ID returns the event ID (copy, stays on stack). |
|
func (r EventRef) ID() ntypes.EventID { return r.id } |
|
|
|
// Pub returns the pubkey (copy, stays on stack). |
|
func (r EventRef) Pub() ntypes.Pubkey { return r.pub } |
|
|
|
// Ts returns the timestamp. |
|
func (r EventRef) Ts() int64 { return r.ts } |
|
|
|
// Ser returns the serial number. |
|
func (r EventRef) Ser() uint64 { return r.ser } |
|
|
|
// IDHex returns the event ID as lowercase hex. |
|
func (r EventRef) IDHex() string { return r.id.Hex() } |
|
|
|
// PubHex returns the pubkey as lowercase hex. |
|
func (r EventRef) PubHex() string { return r.pub.Hex() } |
|
|
|
// IDSlice returns a slice view of the ID (shares memory, use carefully). |
|
func (r *EventRef) IDSlice() []byte { return r.id.Bytes() } |
|
|
|
// PubSlice returns a slice view of the pubkey (shares memory, use carefully). |
|
func (r *EventRef) PubSlice() []byte { return r.pub.Bytes() } |
|
|
|
// ToIdPkTs converts EventRef to IdPkTs for backward compatibility. |
|
// Note: This allocates new slices. |
|
func (r EventRef) ToIdPkTs() *IdPkTs { |
|
return &IdPkTs{ |
|
Id: r.id.Copy(), |
|
Pub: r.pub.Copy(), |
|
Ts: r.ts, |
|
Ser: r.ser, |
|
} |
|
} |
|
|
|
type Querier interface { |
|
QueryForIds(c context.Context, f *filter.F) (evs []*IdPkTs, err error) |
|
} |
|
|
|
type GetIdsWriter interface { |
|
FetchIds(c context.Context, evIds *tag.T, out io.Writer) (err error) |
|
} |
|
|
|
type Deleter interface { |
|
// DeleteEvent is used to handle deletion events, as per NIP-09. |
|
DeleteEvent(c context.Context, ev []byte) (err error) |
|
} |
|
|
|
type Saver interface { |
|
// SaveEvent is called once relay.AcceptEvent reports true. The owners |
|
// parameter is for designating admins whose delete by e tag events apply |
|
// the same as author's own. |
|
SaveEvent(c context.Context, ev *event.E) (replaced bool, err error) |
|
} |
|
|
|
type Importer interface { |
|
// Import reads in a stream of line-structured JSON the events to save into |
|
// the store. |
|
Import(r io.Reader) |
|
} |
|
|
|
type Exporter interface { |
|
// Export writes a stream of line structured JSON of all events in the |
|
// store. |
|
// |
|
// If pubkeys are present, only those with these pubkeys in the `pubkey` |
|
// field and in `p` tags will be included. |
|
Export(c context.Context, w io.Writer, pubkeys ...[]byte) |
|
} |
|
|
|
type Rescanner interface { |
|
// Rescan triggers the regeneration of indexes of the database to enable old |
|
// records to be found with new indexes. |
|
Rescan() (err error) |
|
} |
|
|
|
type Syncer interface { |
|
// Sync signals the event store to flush its buffers. |
|
Sync() (err error) |
|
} |
|
|
|
type Configuration struct { |
|
BlockList []string `json:"block_list" doc:"list of IP addresses that will be ignored"` |
|
} |
|
|
|
type Configurationer interface { |
|
GetConfiguration() (c config.C, err error) |
|
SetConfiguration(c config.C) (err error) |
|
} |
|
|
|
type LogLeveler interface { |
|
SetLogLevel(level string) |
|
} |
|
|
|
type EventIdSerialer interface { |
|
EventIdsBySerial(start uint64, count int) ( |
|
evs [][]byte, |
|
err error, |
|
) |
|
} |
|
|
|
type SerialByIder interface { |
|
GetSerialById(id []byte) (ser *types.Uint40, err error) |
|
}
|
|
|