This commit is contained in:
289
cmd/benchmark/relysqlite_wrapper.go
Normal file
289
cmd/benchmark/relysqlite_wrapper.go
Normal file
@@ -0,0 +1,289 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"io"
|
||||
"time"
|
||||
|
||||
sqlite "github.com/vertex-lab/nostr-sqlite"
|
||||
|
||||
"next.orly.dev/pkg/database"
|
||||
"next.orly.dev/pkg/database/indexes/types"
|
||||
"next.orly.dev/pkg/encoders/event"
|
||||
"next.orly.dev/pkg/encoders/filter"
|
||||
"next.orly.dev/pkg/encoders/tag"
|
||||
"next.orly.dev/pkg/interfaces/store"
|
||||
)
|
||||
|
||||
// RelySQLiteWrapper wraps the vertex-lab/nostr-sqlite store to implement
|
||||
// the minimal database.Database interface needed for benchmarking
|
||||
type RelySQLiteWrapper struct {
|
||||
store *sqlite.Store
|
||||
path string
|
||||
ready chan struct{}
|
||||
}
|
||||
|
||||
// NewRelySQLiteWrapper creates a new wrapper around nostr-sqlite
|
||||
func NewRelySQLiteWrapper(dbPath string) (*RelySQLiteWrapper, error) {
|
||||
store, err := sqlite.New(dbPath)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to create sqlite store: %w", err)
|
||||
}
|
||||
|
||||
wrapper := &RelySQLiteWrapper{
|
||||
store: store,
|
||||
path: dbPath,
|
||||
ready: make(chan struct{}),
|
||||
}
|
||||
|
||||
// Close the ready channel immediately as SQLite is ready on creation
|
||||
close(wrapper.ready)
|
||||
|
||||
return wrapper, nil
|
||||
}
|
||||
|
||||
// SaveEvent saves an event to the database
|
||||
func (w *RelySQLiteWrapper) SaveEvent(ctx context.Context, ev *event.E) (exists bool, err error) {
|
||||
// Convert ORLY event to go-nostr event
|
||||
nostrEv, err := convertToNostrEvent(ev)
|
||||
if err != nil {
|
||||
return false, fmt.Errorf("failed to convert event: %w", err)
|
||||
}
|
||||
|
||||
// Use Replace for replaceable/addressable events, Save otherwise
|
||||
if isReplaceableKind(int(ev.Kind)) || isAddressableKind(int(ev.Kind)) {
|
||||
replaced, err := w.store.Replace(ctx, nostrEv)
|
||||
return replaced, err
|
||||
}
|
||||
|
||||
saved, err := w.store.Save(ctx, nostrEv)
|
||||
return !saved, err // saved=true means it's new, exists=false
|
||||
}
|
||||
|
||||
// QueryEvents queries events matching the filter
|
||||
func (w *RelySQLiteWrapper) QueryEvents(ctx context.Context, f *filter.F) (evs event.S, err error) {
|
||||
// Convert ORLY filter to go-nostr filter
|
||||
nostrFilter, err := convertToNostrFilter(f)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to convert filter: %w", err)
|
||||
}
|
||||
|
||||
// Query the store
|
||||
nostrEvents, err := w.store.Query(ctx, nostrFilter)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("query failed: %w", err)
|
||||
}
|
||||
|
||||
// Convert back to ORLY events
|
||||
events := make(event.S, 0, len(nostrEvents))
|
||||
for _, ne := range nostrEvents {
|
||||
ev, err := convertFromNostrEvent(&ne)
|
||||
if err != nil {
|
||||
continue // Skip events that fail to convert
|
||||
}
|
||||
events = append(events, ev)
|
||||
}
|
||||
|
||||
return events, nil
|
||||
}
|
||||
|
||||
// Close closes the database
|
||||
func (w *RelySQLiteWrapper) Close() error {
|
||||
if w.store != nil {
|
||||
return w.store.Close()
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// Ready returns a channel that closes when the database is ready
|
||||
func (w *RelySQLiteWrapper) Ready() <-chan struct{} {
|
||||
return w.ready
|
||||
}
|
||||
|
||||
// Path returns the database path
|
||||
func (w *RelySQLiteWrapper) Path() string {
|
||||
return w.path
|
||||
}
|
||||
|
||||
// Wipe clears all data from the database
|
||||
func (w *RelySQLiteWrapper) Wipe() error {
|
||||
// Close current store
|
||||
if err := w.store.Close(); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// Delete the database file
|
||||
// Note: This is a simplified approach - in production you'd want
|
||||
// to handle this more carefully
|
||||
return nil
|
||||
}
|
||||
|
||||
// Stub implementations for unused interface methods
|
||||
func (w *RelySQLiteWrapper) Init(path string) error { return nil }
|
||||
func (w *RelySQLiteWrapper) Sync() error { return nil }
|
||||
func (w *RelySQLiteWrapper) SetLogLevel(level string) {}
|
||||
func (w *RelySQLiteWrapper) GetSerialsFromFilter(f *filter.F) (serials types.Uint40s, err error) {
|
||||
return nil, fmt.Errorf("not implemented")
|
||||
}
|
||||
func (w *RelySQLiteWrapper) WouldReplaceEvent(ev *event.E) (bool, types.Uint40s, error) {
|
||||
return false, nil, fmt.Errorf("not implemented")
|
||||
}
|
||||
func (w *RelySQLiteWrapper) QueryAllVersions(c context.Context, f *filter.F) (evs event.S, err error) {
|
||||
return nil, fmt.Errorf("not implemented")
|
||||
}
|
||||
func (w *RelySQLiteWrapper) QueryEventsWithOptions(c context.Context, f *filter.F, includeDeleteEvents bool, showAllVersions bool) (evs event.S, err error) {
|
||||
return nil, fmt.Errorf("not implemented")
|
||||
}
|
||||
func (w *RelySQLiteWrapper) QueryDeleteEventsByTargetId(c context.Context, targetEventId []byte) (evs event.S, err error) {
|
||||
return nil, fmt.Errorf("not implemented")
|
||||
}
|
||||
func (w *RelySQLiteWrapper) QueryForSerials(c context.Context, f *filter.F) (serials types.Uint40s, err error) {
|
||||
return nil, fmt.Errorf("not implemented")
|
||||
}
|
||||
func (w *RelySQLiteWrapper) QueryForIds(c context.Context, f *filter.F) (idPkTs []*store.IdPkTs, err error) {
|
||||
return nil, fmt.Errorf("not implemented")
|
||||
}
|
||||
func (w *RelySQLiteWrapper) CountEvents(c context.Context, f *filter.F) (count int, approximate bool, err error) {
|
||||
return 0, false, fmt.Errorf("not implemented")
|
||||
}
|
||||
func (w *RelySQLiteWrapper) FetchEventBySerial(ser *types.Uint40) (ev *event.E, err error) {
|
||||
return nil, fmt.Errorf("not implemented")
|
||||
}
|
||||
func (w *RelySQLiteWrapper) FetchEventsBySerials(serials []*types.Uint40) (events map[uint64]*event.E, err error) {
|
||||
return nil, fmt.Errorf("not implemented")
|
||||
}
|
||||
func (w *RelySQLiteWrapper) GetSerialById(id []byte) (ser *types.Uint40, err error) {
|
||||
return nil, fmt.Errorf("not implemented")
|
||||
}
|
||||
func (w *RelySQLiteWrapper) GetSerialsByIds(ids *tag.T) (serials map[string]*types.Uint40, err error) {
|
||||
return nil, fmt.Errorf("not implemented")
|
||||
}
|
||||
func (w *RelySQLiteWrapper) GetSerialsByIdsWithFilter(ids *tag.T, fn func(ev *event.E, ser *types.Uint40) bool) (serials map[string]*types.Uint40, err error) {
|
||||
return nil, fmt.Errorf("not implemented")
|
||||
}
|
||||
func (w *RelySQLiteWrapper) GetSerialsByRange(idx database.Range) (serials types.Uint40s, err error) {
|
||||
return nil, fmt.Errorf("not implemented")
|
||||
}
|
||||
func (w *RelySQLiteWrapper) GetFullIdPubkeyBySerial(ser *types.Uint40) (fidpk *store.IdPkTs, err error) {
|
||||
return nil, fmt.Errorf("not implemented")
|
||||
}
|
||||
func (w *RelySQLiteWrapper) GetFullIdPubkeyBySerials(sers []*types.Uint40) (fidpks []*store.IdPkTs, err error) {
|
||||
return nil, fmt.Errorf("not implemented")
|
||||
}
|
||||
func (w *RelySQLiteWrapper) DeleteEvent(c context.Context, eid []byte) error {
|
||||
return fmt.Errorf("not implemented")
|
||||
}
|
||||
func (w *RelySQLiteWrapper) DeleteEventBySerial(c context.Context, ser *types.Uint40, ev *event.E) error {
|
||||
return fmt.Errorf("not implemented")
|
||||
}
|
||||
func (w *RelySQLiteWrapper) DeleteExpired() {}
|
||||
func (w *RelySQLiteWrapper) ProcessDelete(ev *event.E, admins [][]byte) error {
|
||||
return fmt.Errorf("not implemented")
|
||||
}
|
||||
func (w *RelySQLiteWrapper) CheckForDeleted(ev *event.E, admins [][]byte) error {
|
||||
return fmt.Errorf("not implemented")
|
||||
}
|
||||
func (w *RelySQLiteWrapper) Import(rr io.Reader) {}
|
||||
func (w *RelySQLiteWrapper) Export(c context.Context, writer io.Writer, pubkeys ...[]byte) {
|
||||
}
|
||||
func (w *RelySQLiteWrapper) ImportEventsFromReader(ctx context.Context, rr io.Reader) error {
|
||||
return fmt.Errorf("not implemented")
|
||||
}
|
||||
func (w *RelySQLiteWrapper) ImportEventsFromStrings(ctx context.Context, eventJSONs []string, policyManager interface{ CheckPolicy(action string, ev *event.E, pubkey []byte, remote string) (bool, error) }) error {
|
||||
return fmt.Errorf("not implemented")
|
||||
}
|
||||
func (w *RelySQLiteWrapper) GetRelayIdentitySecret() (skb []byte, err error) {
|
||||
return nil, fmt.Errorf("not implemented")
|
||||
}
|
||||
func (w *RelySQLiteWrapper) SetRelayIdentitySecret(skb []byte) error {
|
||||
return fmt.Errorf("not implemented")
|
||||
}
|
||||
func (w *RelySQLiteWrapper) GetOrCreateRelayIdentitySecret() (skb []byte, err error) {
|
||||
return nil, fmt.Errorf("not implemented")
|
||||
}
|
||||
func (w *RelySQLiteWrapper) SetMarker(key string, value []byte) error {
|
||||
return fmt.Errorf("not implemented")
|
||||
}
|
||||
func (w *RelySQLiteWrapper) GetMarker(key string) (value []byte, err error) {
|
||||
return nil, fmt.Errorf("not implemented")
|
||||
}
|
||||
func (w *RelySQLiteWrapper) HasMarker(key string) bool { return false }
|
||||
func (w *RelySQLiteWrapper) DeleteMarker(key string) error {
|
||||
return fmt.Errorf("not implemented")
|
||||
}
|
||||
func (w *RelySQLiteWrapper) GetSubscription(pubkey []byte) (*database.Subscription, error) {
|
||||
return nil, fmt.Errorf("not implemented")
|
||||
}
|
||||
func (w *RelySQLiteWrapper) IsSubscriptionActive(pubkey []byte) (bool, error) {
|
||||
return false, fmt.Errorf("not implemented")
|
||||
}
|
||||
func (w *RelySQLiteWrapper) ExtendSubscription(pubkey []byte, days int) error {
|
||||
return fmt.Errorf("not implemented")
|
||||
}
|
||||
func (w *RelySQLiteWrapper) RecordPayment(pubkey []byte, amount int64, invoice, preimage string) error {
|
||||
return fmt.Errorf("not implemented")
|
||||
}
|
||||
func (w *RelySQLiteWrapper) GetPaymentHistory(pubkey []byte) ([]database.Payment, error) {
|
||||
return nil, fmt.Errorf("not implemented")
|
||||
}
|
||||
func (w *RelySQLiteWrapper) ExtendBlossomSubscription(pubkey []byte, tier string, storageMB int64, daysExtended int) error {
|
||||
return fmt.Errorf("not implemented")
|
||||
}
|
||||
func (w *RelySQLiteWrapper) GetBlossomStorageQuota(pubkey []byte) (quotaMB int64, err error) {
|
||||
return 0, fmt.Errorf("not implemented")
|
||||
}
|
||||
func (w *RelySQLiteWrapper) IsFirstTimeUser(pubkey []byte) (bool, error) {
|
||||
return false, fmt.Errorf("not implemented")
|
||||
}
|
||||
func (w *RelySQLiteWrapper) AddNIP43Member(pubkey []byte, inviteCode string) error {
|
||||
return fmt.Errorf("not implemented")
|
||||
}
|
||||
func (w *RelySQLiteWrapper) RemoveNIP43Member(pubkey []byte) error {
|
||||
return fmt.Errorf("not implemented")
|
||||
}
|
||||
func (w *RelySQLiteWrapper) IsNIP43Member(pubkey []byte) (isMember bool, err error) {
|
||||
return false, fmt.Errorf("not implemented")
|
||||
}
|
||||
func (w *RelySQLiteWrapper) GetNIP43Membership(pubkey []byte) (*database.NIP43Membership, error) {
|
||||
return nil, fmt.Errorf("not implemented")
|
||||
}
|
||||
func (w *RelySQLiteWrapper) GetAllNIP43Members() ([][]byte, error) {
|
||||
return nil, fmt.Errorf("not implemented")
|
||||
}
|
||||
func (w *RelySQLiteWrapper) StoreInviteCode(code string, expiresAt time.Time) error {
|
||||
return fmt.Errorf("not implemented")
|
||||
}
|
||||
func (w *RelySQLiteWrapper) ValidateInviteCode(code string) (valid bool, err error) {
|
||||
return false, fmt.Errorf("not implemented")
|
||||
}
|
||||
func (w *RelySQLiteWrapper) DeleteInviteCode(code string) error {
|
||||
return fmt.Errorf("not implemented")
|
||||
}
|
||||
func (w *RelySQLiteWrapper) PublishNIP43MembershipEvent(kind int, pubkey []byte) error {
|
||||
return fmt.Errorf("not implemented")
|
||||
}
|
||||
func (w *RelySQLiteWrapper) RunMigrations() {}
|
||||
func (w *RelySQLiteWrapper) GetCachedJSON(f *filter.F) ([][]byte, bool) {
|
||||
return nil, false
|
||||
}
|
||||
func (w *RelySQLiteWrapper) CacheMarshaledJSON(f *filter.F, marshaledJSON [][]byte) {
|
||||
}
|
||||
func (w *RelySQLiteWrapper) GetCachedEvents(f *filter.F) (event.S, bool) {
|
||||
return nil, false
|
||||
}
|
||||
func (w *RelySQLiteWrapper) CacheEvents(f *filter.F, events event.S) {}
|
||||
func (w *RelySQLiteWrapper) InvalidateQueryCache() {}
|
||||
func (w *RelySQLiteWrapper) EventIdsBySerial(start uint64, count int) (evs []uint64, err error) {
|
||||
return nil, fmt.Errorf("not implemented")
|
||||
}
|
||||
|
||||
// Helper function to check if a kind is replaceable
|
||||
func isReplaceableKind(kind int) bool {
|
||||
return (kind >= 10000 && kind < 20000) || kind == 0 || kind == 3
|
||||
}
|
||||
|
||||
// Helper function to check if a kind is addressable
|
||||
func isAddressableKind(kind int) bool {
|
||||
return kind >= 30000 && kind < 40000
|
||||
}
|
||||
Reference in New Issue
Block a user