54 changed files with 5519 additions and 4442 deletions
@ -0,0 +1,6 @@ |
|||||||
|
data/ |
||||||
|
reports/ |
||||||
|
*.log |
||||||
|
*.db |
||||||
|
external/ |
||||||
|
configs/ |
||||||
@ -0,0 +1,99 @@ |
|||||||
|
//go:build ignore
|
||||||
|
// +build ignore
|
||||||
|
|
||||||
|
package main |
||||||
|
|
||||||
|
import ( |
||||||
|
"context" |
||||||
|
"log" |
||||||
|
"os" |
||||||
|
"os/signal" |
||||||
|
"syscall" |
||||||
|
"time" |
||||||
|
|
||||||
|
"github.com/nbd-wtf/go-nostr" |
||||||
|
sqlite "github.com/vertex-lab/nostr-sqlite" |
||||||
|
"github.com/pippellia-btc/rely" |
||||||
|
) |
||||||
|
|
||||||
|
func main() { |
||||||
|
ctx, cancel := signal.NotifyContext(context.Background(), syscall.SIGINT, syscall.SIGTERM) |
||||||
|
defer cancel() |
||||||
|
|
||||||
|
// Get configuration from environment with defaults
|
||||||
|
dbPath := os.Getenv("DATABASE_PATH") |
||||||
|
if dbPath == "" { |
||||||
|
dbPath = "./relay.db" |
||||||
|
} |
||||||
|
|
||||||
|
listenAddr := os.Getenv("RELAY_LISTEN") |
||||||
|
if listenAddr == "" { |
||||||
|
listenAddr = "0.0.0.0:3334" |
||||||
|
} |
||||||
|
|
||||||
|
// Initialize database
|
||||||
|
db, err := sqlite.New(dbPath) |
||||||
|
if err != nil { |
||||||
|
log.Fatalf("failed to initialize database: %v", err) |
||||||
|
} |
||||||
|
defer db.Close() |
||||||
|
|
||||||
|
// Create relay with handlers
|
||||||
|
relay := rely.NewRelay( |
||||||
|
rely.WithQueueCapacity(10_000), |
||||||
|
rely.WithMaxProcessors(10), |
||||||
|
) |
||||||
|
|
||||||
|
// Register event handlers using the correct API
|
||||||
|
relay.On.Event = Save(db) |
||||||
|
relay.On.Req = Query(db) |
||||||
|
relay.On.Count = Count(db) |
||||||
|
|
||||||
|
// Start relay
|
||||||
|
log.Printf("Starting rely-sqlite on %s with database %s", listenAddr, dbPath) |
||||||
|
err = relay.StartAndServe(ctx, listenAddr) |
||||||
|
if err != nil { |
||||||
|
log.Fatalf("relay failed: %v", err) |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
// Save handles incoming events
|
||||||
|
func Save(db *sqlite.Store) func(_ rely.Client, e *nostr.Event) error { |
||||||
|
return func(_ rely.Client, e *nostr.Event) error { |
||||||
|
ctx, cancel := context.WithTimeout(context.Background(), 2*time.Second) |
||||||
|
defer cancel() |
||||||
|
|
||||||
|
switch { |
||||||
|
case nostr.IsRegularKind(e.Kind): |
||||||
|
_, err := db.Save(ctx, e) |
||||||
|
return err |
||||||
|
case nostr.IsReplaceableKind(e.Kind) || nostr.IsAddressableKind(e.Kind): |
||||||
|
_, err := db.Replace(ctx, e) |
||||||
|
return err |
||||||
|
default: |
||||||
|
return nil |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
// Query retrieves events matching filters
|
||||||
|
func Query(db *sqlite.Store) func(ctx context.Context, _ rely.Client, filters nostr.Filters) ([]nostr.Event, error) { |
||||||
|
return func(ctx context.Context, _ rely.Client, filters nostr.Filters) ([]nostr.Event, error) { |
||||||
|
ctx, cancel := context.WithTimeout(ctx, 2*time.Second) |
||||||
|
defer cancel() |
||||||
|
return db.Query(ctx, filters...) |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
// Count counts events matching filters
|
||||||
|
func Count(db *sqlite.Store) func(_ rely.Client, filters nostr.Filters) (count int64, approx bool, err error) { |
||||||
|
return func(_ rely.Client, filters nostr.Filters) (count int64, approx bool, err error) { |
||||||
|
ctx, cancel := context.WithTimeout(context.Background(), time.Second) |
||||||
|
defer cancel() |
||||||
|
count, err = db.Count(ctx, filters...) |
||||||
|
if err != nil { |
||||||
|
return -1, false, err |
||||||
|
} |
||||||
|
return count, false, nil |
||||||
|
} |
||||||
|
} |
||||||
@ -0,0 +1,151 @@ |
|||||||
|
package main |
||||||
|
|
||||||
|
import ( |
||||||
|
"fmt" |
||||||
|
"log" |
||||||
|
"os" |
||||||
|
"path/filepath" |
||||||
|
"time" |
||||||
|
|
||||||
|
"next.orly.dev/pkg/database" |
||||||
|
) |
||||||
|
|
||||||
|
// RelySQLiteBenchmark wraps a Benchmark with rely-sqlite-specific setup
|
||||||
|
type RelySQLiteBenchmark struct { |
||||||
|
config *BenchmarkConfig |
||||||
|
database database.Database |
||||||
|
bench *BenchmarkAdapter |
||||||
|
dbPath string |
||||||
|
} |
||||||
|
|
||||||
|
// NewRelySQLiteBenchmark creates a new rely-sqlite benchmark instance
|
||||||
|
func NewRelySQLiteBenchmark(config *BenchmarkConfig) (*RelySQLiteBenchmark, error) { |
||||||
|
// Create database path
|
||||||
|
dbPath := filepath.Join(config.DataDir, "relysqlite.db") |
||||||
|
|
||||||
|
// Ensure parent directory exists
|
||||||
|
if err := os.MkdirAll(config.DataDir, 0755); err != nil { |
||||||
|
return nil, fmt.Errorf("failed to create data directory: %w", err) |
||||||
|
} |
||||||
|
|
||||||
|
// Remove existing database file if it exists
|
||||||
|
if _, err := os.Stat(dbPath); err == nil { |
||||||
|
if err := os.Remove(dbPath); err != nil { |
||||||
|
return nil, fmt.Errorf("failed to remove existing database: %w", err) |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
// Create wrapper
|
||||||
|
wrapper, err := NewRelySQLiteWrapper(dbPath) |
||||||
|
if err != nil { |
||||||
|
return nil, fmt.Errorf("failed to create rely-sqlite wrapper: %w", err) |
||||||
|
} |
||||||
|
|
||||||
|
// Wait for database to be ready
|
||||||
|
fmt.Println("Waiting for rely-sqlite database to be ready...") |
||||||
|
select { |
||||||
|
case <-wrapper.Ready(): |
||||||
|
fmt.Println("Rely-sqlite database is ready") |
||||||
|
case <-time.After(10 * time.Second): |
||||||
|
wrapper.Close() |
||||||
|
return nil, fmt.Errorf("rely-sqlite database failed to become ready") |
||||||
|
} |
||||||
|
|
||||||
|
// Create adapter to use Database interface with Benchmark
|
||||||
|
adapter := NewBenchmarkAdapter(config, wrapper) |
||||||
|
|
||||||
|
relysqliteBench := &RelySQLiteBenchmark{ |
||||||
|
config: config, |
||||||
|
database: wrapper, |
||||||
|
bench: adapter, |
||||||
|
dbPath: dbPath, |
||||||
|
} |
||||||
|
|
||||||
|
return relysqliteBench, nil |
||||||
|
} |
||||||
|
|
||||||
|
// Close closes the rely-sqlite benchmark
|
||||||
|
func (rsb *RelySQLiteBenchmark) Close() { |
||||||
|
fmt.Println("Closing rely-sqlite benchmark...") |
||||||
|
|
||||||
|
if rsb.database != nil { |
||||||
|
rsb.database.Close() |
||||||
|
} |
||||||
|
|
||||||
|
// Clean up database file
|
||||||
|
if rsb.dbPath != "" { |
||||||
|
os.Remove(rsb.dbPath) |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
// RunSuite runs the benchmark suite on rely-sqlite
|
||||||
|
func (rsb *RelySQLiteBenchmark) RunSuite() { |
||||||
|
fmt.Println("\n╔════════════════════════════════════════════════════════╗") |
||||||
|
fmt.Println("║ RELY-SQLITE BACKEND BENCHMARK SUITE ║") |
||||||
|
fmt.Println("╚════════════════════════════════════════════════════════╝") |
||||||
|
|
||||||
|
// Run benchmark tests
|
||||||
|
fmt.Printf("\n=== Starting Rely-SQLite benchmark ===\n") |
||||||
|
|
||||||
|
fmt.Printf("RunPeakThroughputTest (Rely-SQLite)..\n") |
||||||
|
rsb.bench.RunPeakThroughputTest() |
||||||
|
fmt.Println("Wiping database between tests...") |
||||||
|
rsb.wipeDatabase() |
||||||
|
time.Sleep(5 * time.Second) |
||||||
|
|
||||||
|
fmt.Printf("RunBurstPatternTest (Rely-SQLite)..\n") |
||||||
|
rsb.bench.RunBurstPatternTest() |
||||||
|
fmt.Println("Wiping database between tests...") |
||||||
|
rsb.wipeDatabase() |
||||||
|
time.Sleep(5 * time.Second) |
||||||
|
|
||||||
|
fmt.Printf("RunMixedReadWriteTest (Rely-SQLite)..\n") |
||||||
|
rsb.bench.RunMixedReadWriteTest() |
||||||
|
fmt.Println("Wiping database between tests...") |
||||||
|
rsb.wipeDatabase() |
||||||
|
time.Sleep(5 * time.Second) |
||||||
|
|
||||||
|
fmt.Printf("RunQueryTest (Rely-SQLite)..\n") |
||||||
|
rsb.bench.RunQueryTest() |
||||||
|
fmt.Println("Wiping database between tests...") |
||||||
|
rsb.wipeDatabase() |
||||||
|
time.Sleep(5 * time.Second) |
||||||
|
|
||||||
|
fmt.Printf("RunConcurrentQueryStoreTest (Rely-SQLite)..\n") |
||||||
|
rsb.bench.RunConcurrentQueryStoreTest() |
||||||
|
|
||||||
|
fmt.Printf("\n=== Rely-SQLite benchmark completed ===\n\n") |
||||||
|
} |
||||||
|
|
||||||
|
// wipeDatabase recreates the database for a clean slate
|
||||||
|
func (rsb *RelySQLiteBenchmark) wipeDatabase() { |
||||||
|
// Close existing database
|
||||||
|
if rsb.database != nil { |
||||||
|
rsb.database.Close() |
||||||
|
} |
||||||
|
|
||||||
|
// Remove database file
|
||||||
|
if rsb.dbPath != "" { |
||||||
|
os.Remove(rsb.dbPath) |
||||||
|
} |
||||||
|
|
||||||
|
// Recreate database
|
||||||
|
wrapper, err := NewRelySQLiteWrapper(rsb.dbPath) |
||||||
|
if err != nil { |
||||||
|
log.Printf("Failed to recreate database: %v", err) |
||||||
|
return |
||||||
|
} |
||||||
|
|
||||||
|
rsb.database = wrapper |
||||||
|
rsb.bench.db = wrapper |
||||||
|
} |
||||||
|
|
||||||
|
// GenerateReport generates the benchmark report
|
||||||
|
func (rsb *RelySQLiteBenchmark) GenerateReport() { |
||||||
|
rsb.bench.GenerateReport() |
||||||
|
} |
||||||
|
|
||||||
|
// GenerateAsciidocReport generates asciidoc format report
|
||||||
|
func (rsb *RelySQLiteBenchmark) GenerateAsciidocReport() { |
||||||
|
rsb.bench.GenerateAsciidocReport() |
||||||
|
} |
||||||
@ -0,0 +1,164 @@ |
|||||||
|
package main |
||||||
|
|
||||||
|
import ( |
||||||
|
"encoding/hex" |
||||||
|
"fmt" |
||||||
|
|
||||||
|
"github.com/nbd-wtf/go-nostr" |
||||||
|
|
||||||
|
orlyEvent "next.orly.dev/pkg/encoders/event" |
||||||
|
orlyFilter "next.orly.dev/pkg/encoders/filter" |
||||||
|
orlyTag "next.orly.dev/pkg/encoders/tag" |
||||||
|
) |
||||||
|
|
||||||
|
// convertToNostrEvent converts an ORLY event to a go-nostr event
|
||||||
|
func convertToNostrEvent(ev *orlyEvent.E) (*nostr.Event, error) { |
||||||
|
if ev == nil { |
||||||
|
return nil, fmt.Errorf("nil event") |
||||||
|
} |
||||||
|
|
||||||
|
nostrEv := &nostr.Event{ |
||||||
|
ID: hex.EncodeToString(ev.ID), |
||||||
|
PubKey: hex.EncodeToString(ev.Pubkey), |
||||||
|
CreatedAt: nostr.Timestamp(ev.CreatedAt), |
||||||
|
Kind: int(ev.Kind), |
||||||
|
Content: string(ev.Content), |
||||||
|
Sig: hex.EncodeToString(ev.Sig), |
||||||
|
} |
||||||
|
|
||||||
|
// Convert tags
|
||||||
|
if ev.Tags != nil && len(*ev.Tags) > 0 { |
||||||
|
nostrEv.Tags = make(nostr.Tags, 0, len(*ev.Tags)) |
||||||
|
for _, orlyTag := range *ev.Tags { |
||||||
|
if orlyTag != nil && len(orlyTag.T) > 0 { |
||||||
|
tag := make(nostr.Tag, len(orlyTag.T)) |
||||||
|
for i, val := range orlyTag.T { |
||||||
|
tag[i] = string(val) |
||||||
|
} |
||||||
|
nostrEv.Tags = append(nostrEv.Tags, tag) |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
return nostrEv, nil |
||||||
|
} |
||||||
|
|
||||||
|
// convertFromNostrEvent converts a go-nostr event to an ORLY event
|
||||||
|
func convertFromNostrEvent(ne *nostr.Event) (*orlyEvent.E, error) { |
||||||
|
if ne == nil { |
||||||
|
return nil, fmt.Errorf("nil event") |
||||||
|
} |
||||||
|
|
||||||
|
ev := orlyEvent.New() |
||||||
|
|
||||||
|
// Convert ID
|
||||||
|
idBytes, err := hex.DecodeString(ne.ID) |
||||||
|
if err != nil { |
||||||
|
return nil, fmt.Errorf("failed to decode ID: %w", err) |
||||||
|
} |
||||||
|
ev.ID = idBytes |
||||||
|
|
||||||
|
// Convert Pubkey
|
||||||
|
pubkeyBytes, err := hex.DecodeString(ne.PubKey) |
||||||
|
if err != nil { |
||||||
|
return nil, fmt.Errorf("failed to decode pubkey: %w", err) |
||||||
|
} |
||||||
|
ev.Pubkey = pubkeyBytes |
||||||
|
|
||||||
|
// Convert Sig
|
||||||
|
sigBytes, err := hex.DecodeString(ne.Sig) |
||||||
|
if err != nil { |
||||||
|
return nil, fmt.Errorf("failed to decode signature: %w", err) |
||||||
|
} |
||||||
|
ev.Sig = sigBytes |
||||||
|
|
||||||
|
// Simple fields
|
||||||
|
ev.CreatedAt = int64(ne.CreatedAt) |
||||||
|
ev.Kind = uint16(ne.Kind) |
||||||
|
ev.Content = []byte(ne.Content) |
||||||
|
|
||||||
|
// Convert tags
|
||||||
|
if len(ne.Tags) > 0 { |
||||||
|
ev.Tags = orlyTag.NewS() |
||||||
|
for _, nostrTag := range ne.Tags { |
||||||
|
if len(nostrTag) > 0 { |
||||||
|
tag := orlyTag.NewWithCap(len(nostrTag)) |
||||||
|
for _, val := range nostrTag { |
||||||
|
tag.T = append(tag.T, []byte(val)) |
||||||
|
} |
||||||
|
*ev.Tags = append(*ev.Tags, tag) |
||||||
|
} |
||||||
|
} |
||||||
|
} else { |
||||||
|
ev.Tags = orlyTag.NewS() |
||||||
|
} |
||||||
|
|
||||||
|
return ev, nil |
||||||
|
} |
||||||
|
|
||||||
|
// convertToNostrFilter converts an ORLY filter to a go-nostr filter
|
||||||
|
func convertToNostrFilter(f *orlyFilter.F) (nostr.Filter, error) { |
||||||
|
if f == nil { |
||||||
|
return nostr.Filter{}, fmt.Errorf("nil filter") |
||||||
|
} |
||||||
|
|
||||||
|
filter := nostr.Filter{} |
||||||
|
|
||||||
|
// Convert IDs
|
||||||
|
if f.Ids != nil && len(f.Ids.T) > 0 { |
||||||
|
filter.IDs = make([]string, 0, len(f.Ids.T)) |
||||||
|
for _, id := range f.Ids.T { |
||||||
|
filter.IDs = append(filter.IDs, hex.EncodeToString(id)) |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
// Convert Authors
|
||||||
|
if f.Authors != nil && len(f.Authors.T) > 0 { |
||||||
|
filter.Authors = make([]string, 0, len(f.Authors.T)) |
||||||
|
for _, author := range f.Authors.T { |
||||||
|
filter.Authors = append(filter.Authors, hex.EncodeToString(author)) |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
// Convert Kinds
|
||||||
|
if f.Kinds != nil && len(f.Kinds.K) > 0 { |
||||||
|
filter.Kinds = make([]int, 0, len(f.Kinds.K)) |
||||||
|
for _, kind := range f.Kinds.K { |
||||||
|
filter.Kinds = append(filter.Kinds, int(kind.K)) |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
// Convert Tags
|
||||||
|
if f.Tags != nil && len(*f.Tags) > 0 { |
||||||
|
filter.Tags = make(nostr.TagMap) |
||||||
|
for _, tag := range *f.Tags { |
||||||
|
if tag != nil && len(tag.T) >= 2 { |
||||||
|
tagName := string(tag.T[0]) |
||||||
|
tagValues := make([]string, 0, len(tag.T)-1) |
||||||
|
for i := 1; i < len(tag.T); i++ { |
||||||
|
tagValues = append(tagValues, string(tag.T[i])) |
||||||
|
} |
||||||
|
filter.Tags[tagName] = tagValues |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
// Convert timestamps
|
||||||
|
if f.Since != nil { |
||||||
|
ts := nostr.Timestamp(f.Since.V) |
||||||
|
filter.Since = &ts |
||||||
|
} |
||||||
|
|
||||||
|
if f.Until != nil { |
||||||
|
ts := nostr.Timestamp(f.Until.V) |
||||||
|
filter.Until = &ts |
||||||
|
} |
||||||
|
|
||||||
|
// Convert limit
|
||||||
|
if f.Limit != nil { |
||||||
|
limit := int(*f.Limit) |
||||||
|
filter.Limit = limit |
||||||
|
} |
||||||
|
|
||||||
|
return filter, nil |
||||||
|
} |
||||||
@ -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 |
||||||
|
} |
||||||
@ -1,176 +0,0 @@ |
|||||||
================================================================ |
|
||||||
NOSTR RELAY BENCHMARK AGGREGATE REPORT |
|
||||||
================================================================ |
|
||||||
Generated: 2025-11-19T06:13:40+00:00 |
|
||||||
Benchmark Configuration: |
|
||||||
Events per test: 50000 |
|
||||||
Concurrent workers: 24 |
|
||||||
Test duration: 60s |
|
||||||
|
|
||||||
Relays tested: 8 |
|
||||||
|
|
||||||
================================================================ |
|
||||||
SUMMARY BY RELAY |
|
||||||
================================================================ |
|
||||||
|
|
||||||
Relay: next-orly-badger |
|
||||||
---------------------------------------- |
|
||||||
Status: COMPLETED |
|
||||||
Events/sec: 2911.52 |
|
||||||
Events/sec: 0.00 |
|
||||||
Events/sec: 2911.52 |
|
||||||
Success Rate: 23.2% |
|
||||||
Success Rate: 0.0% |
|
||||||
Success Rate: 50.0% |
|
||||||
Avg Latency: 3.938925ms |
|
||||||
Bottom 10% Avg Latency: 1.115318ms |
|
||||||
Avg Latency: 0s |
|
||||||
P95 Latency: 4.624387ms |
|
||||||
P95 Latency: 0s |
|
||||||
P95 Latency: 112.915µs |
|
||||||
|
|
||||||
Relay: next-orly-dgraph |
|
||||||
---------------------------------------- |
|
||||||
Status: COMPLETED |
|
||||||
Events/sec: 2661.66 |
|
||||||
Events/sec: 0.00 |
|
||||||
Events/sec: 2661.66 |
|
||||||
Success Rate: 23.2% |
|
||||||
Success Rate: 0.0% |
|
||||||
Success Rate: 50.0% |
|
||||||
Avg Latency: 4.795769ms |
|
||||||
Bottom 10% Avg Latency: 1.212562ms |
|
||||||
Avg Latency: 0s |
|
||||||
P95 Latency: 6.029522ms |
|
||||||
P95 Latency: 0s |
|
||||||
P95 Latency: 115.35µs |
|
||||||
|
|
||||||
Relay: next-orly-neo4j |
|
||||||
---------------------------------------- |
|
||||||
Status: COMPLETED |
|
||||||
Events/sec: 2827.54 |
|
||||||
Events/sec: 0.00 |
|
||||||
Events/sec: 2827.54 |
|
||||||
Success Rate: 23.2% |
|
||||||
Success Rate: 0.0% |
|
||||||
Success Rate: 50.0% |
|
||||||
Avg Latency: 4.203722ms |
|
||||||
Bottom 10% Avg Latency: 1.124184ms |
|
||||||
Avg Latency: 0s |
|
||||||
P95 Latency: 4.568189ms |
|
||||||
P95 Latency: 0s |
|
||||||
P95 Latency: 112.755µs |
|
||||||
|
|
||||||
Relay: khatru-sqlite |
|
||||||
---------------------------------------- |
|
||||||
Status: COMPLETED |
|
||||||
Events/sec: 2840.91 |
|
||||||
Events/sec: 0.00 |
|
||||||
Events/sec: 2840.91 |
|
||||||
Success Rate: 23.2% |
|
||||||
Success Rate: 0.0% |
|
||||||
Success Rate: 50.0% |
|
||||||
Avg Latency: 4.23095ms |
|
||||||
Bottom 10% Avg Latency: 1.142932ms |
|
||||||
Avg Latency: 0s |
|
||||||
P95 Latency: 4.703046ms |
|
||||||
P95 Latency: 0s |
|
||||||
P95 Latency: 113.897µs |
|
||||||
|
|
||||||
Relay: khatru-badger |
|
||||||
---------------------------------------- |
|
||||||
Status: COMPLETED |
|
||||||
Events/sec: 2885.30 |
|
||||||
Events/sec: 0.00 |
|
||||||
Events/sec: 2885.30 |
|
||||||
Success Rate: 23.2% |
|
||||||
Success Rate: 0.0% |
|
||||||
Success Rate: 50.0% |
|
||||||
Avg Latency: 3.985846ms |
|
||||||
Bottom 10% Avg Latency: 1.120349ms |
|
||||||
Avg Latency: 0s |
|
||||||
P95 Latency: 4.23797ms |
|
||||||
P95 Latency: 0s |
|
||||||
P95 Latency: 114.277µs |
|
||||||
|
|
||||||
Relay: relayer-basic |
|
||||||
---------------------------------------- |
|
||||||
Status: COMPLETED |
|
||||||
Events/sec: 2707.76 |
|
||||||
Events/sec: 0.00 |
|
||||||
Events/sec: 2707.76 |
|
||||||
Success Rate: 23.2% |
|
||||||
Success Rate: 0.0% |
|
||||||
Success Rate: 50.0% |
|
||||||
Avg Latency: 4.657987ms |
|
||||||
Bottom 10% Avg Latency: 1.266467ms |
|
||||||
Avg Latency: 0s |
|
||||||
P95 Latency: 5.603449ms |
|
||||||
P95 Latency: 0s |
|
||||||
P95 Latency: 112.123µs |
|
||||||
|
|
||||||
Relay: strfry |
|
||||||
---------------------------------------- |
|
||||||
Status: COMPLETED |
|
||||||
Events/sec: 2841.22 |
|
||||||
Events/sec: 0.00 |
|
||||||
Events/sec: 2841.22 |
|
||||||
Success Rate: 23.2% |
|
||||||
Success Rate: 0.0% |
|
||||||
Success Rate: 50.0% |
|
||||||
Avg Latency: 4.088506ms |
|
||||||
Bottom 10% Avg Latency: 1.135387ms |
|
||||||
Avg Latency: 0s |
|
||||||
P95 Latency: 4.517428ms |
|
||||||
P95 Latency: 0s |
|
||||||
P95 Latency: 113.396µs |
|
||||||
|
|
||||||
Relay: nostr-rs-relay |
|
||||||
---------------------------------------- |
|
||||||
Status: COMPLETED |
|
||||||
Events/sec: 2883.32 |
|
||||||
Events/sec: 0.00 |
|
||||||
Events/sec: 2883.32 |
|
||||||
Success Rate: 23.2% |
|
||||||
Success Rate: 0.0% |
|
||||||
Success Rate: 50.0% |
|
||||||
Avg Latency: 4.044321ms |
|
||||||
Bottom 10% Avg Latency: 1.103637ms |
|
||||||
Avg Latency: 0s |
|
||||||
P95 Latency: 4.602719ms |
|
||||||
P95 Latency: 0s |
|
||||||
P95 Latency: 114.679µs |
|
||||||
|
|
||||||
|
|
||||||
================================================================ |
|
||||||
DETAILED RESULTS |
|
||||||
================================================================ |
|
||||||
|
|
||||||
Individual relay reports are available in: |
|
||||||
- /reports/run_20251119_054648/khatru-badger_results.txt |
|
||||||
- /reports/run_20251119_054648/khatru-sqlite_results.txt |
|
||||||
- /reports/run_20251119_054648/next-orly-badger_results.txt |
|
||||||
- /reports/run_20251119_054648/next-orly-dgraph_results.txt |
|
||||||
- /reports/run_20251119_054648/next-orly-neo4j_results.txt |
|
||||||
- /reports/run_20251119_054648/nostr-rs-relay_results.txt |
|
||||||
- /reports/run_20251119_054648/relayer-basic_results.txt |
|
||||||
- /reports/run_20251119_054648/strfry_results.txt |
|
||||||
|
|
||||||
================================================================ |
|
||||||
BENCHMARK COMPARISON TABLE |
|
||||||
================================================================ |
|
||||||
|
|
||||||
Relay Status Peak Tput/s Avg Latency Success Rate |
|
||||||
---- ------ ----------- ----------- ------------ |
|
||||||
next-orly-badger OK 2911.52 3.938925ms 23.2% |
|
||||||
next-orly-dgraph OK 2661.66 4.795769ms 23.2% |
|
||||||
next-orly-neo4j OK 2827.54 4.203722ms 23.2% |
|
||||||
khatru-sqlite OK 2840.91 4.23095ms 23.2% |
|
||||||
khatru-badger OK 2885.30 3.985846ms 23.2% |
|
||||||
relayer-basic OK 2707.76 4.657987ms 23.2% |
|
||||||
strfry OK 2841.22 4.088506ms 23.2% |
|
||||||
nostr-rs-relay OK 2883.32 4.044321ms 23.2% |
|
||||||
|
|
||||||
================================================================ |
|
||||||
End of Report |
|
||||||
================================================================ |
|
||||||
@ -1,176 +0,0 @@ |
|||||||
================================================================ |
|
||||||
NOSTR RELAY BENCHMARK AGGREGATE REPORT |
|
||||||
================================================================ |
|
||||||
Generated: 2025-11-20T06:19:54+00:00 |
|
||||||
Benchmark Configuration: |
|
||||||
Events per test: 50000 |
|
||||||
Concurrent workers: 24 |
|
||||||
Test duration: 60s |
|
||||||
|
|
||||||
Relays tested: 8 |
|
||||||
|
|
||||||
================================================================ |
|
||||||
SUMMARY BY RELAY |
|
||||||
================================================================ |
|
||||||
|
|
||||||
Relay: next-orly-badger |
|
||||||
---------------------------------------- |
|
||||||
Status: COMPLETED |
|
||||||
Events/sec: 17207.24 |
|
||||||
Events/sec: 6359.22 |
|
||||||
Events/sec: 17207.24 |
|
||||||
Success Rate: 100.0% |
|
||||||
Success Rate: 100.0% |
|
||||||
Success Rate: 100.0% |
|
||||||
Avg Latency: 1.240424ms |
|
||||||
Bottom 10% Avg Latency: 680.755µs |
|
||||||
Avg Latency: 1.142716ms |
|
||||||
P95 Latency: 1.987721ms |
|
||||||
P95 Latency: 1.919402ms |
|
||||||
P95 Latency: 858.138µs |
|
||||||
|
|
||||||
Relay: next-orly-dgraph |
|
||||||
---------------------------------------- |
|
||||||
Status: COMPLETED |
|
||||||
Events/sec: 15975.41 |
|
||||||
Events/sec: 6275.40 |
|
||||||
Events/sec: 15975.41 |
|
||||||
Success Rate: 100.0% |
|
||||||
Success Rate: 100.0% |
|
||||||
Success Rate: 100.0% |
|
||||||
Avg Latency: 1.379901ms |
|
||||||
Bottom 10% Avg Latency: 705.38µs |
|
||||||
Avg Latency: 1.177806ms |
|
||||||
P95 Latency: 2.307115ms |
|
||||||
P95 Latency: 2.062351ms |
|
||||||
P95 Latency: 858.252µs |
|
||||||
|
|
||||||
Relay: next-orly-neo4j |
|
||||||
---------------------------------------- |
|
||||||
Status: COMPLETED |
|
||||||
Events/sec: 18050.59 |
|
||||||
Events/sec: 6274.46 |
|
||||||
Events/sec: 18050.59 |
|
||||||
Success Rate: 100.0% |
|
||||||
Success Rate: 100.0% |
|
||||||
Success Rate: 100.0% |
|
||||||
Avg Latency: 1.142811ms |
|
||||||
Bottom 10% Avg Latency: 648.4µs |
|
||||||
Avg Latency: 1.192885ms |
|
||||||
P95 Latency: 1.69225ms |
|
||||||
P95 Latency: 1.98103ms |
|
||||||
P95 Latency: 864.535µs |
|
||||||
|
|
||||||
Relay: khatru-sqlite |
|
||||||
---------------------------------------- |
|
||||||
Status: COMPLETED |
|
||||||
Events/sec: 16911.01 |
|
||||||
Events/sec: 6346.70 |
|
||||||
Events/sec: 16911.01 |
|
||||||
Success Rate: 100.0% |
|
||||||
Success Rate: 100.0% |
|
||||||
Success Rate: 100.0% |
|
||||||
Avg Latency: 1.278879ms |
|
||||||
Bottom 10% Avg Latency: 694.3µs |
|
||||||
Avg Latency: 1.145501ms |
|
||||||
P95 Latency: 2.058912ms |
|
||||||
P95 Latency: 1.860934ms |
|
||||||
P95 Latency: 857.964µs |
|
||||||
|
|
||||||
Relay: khatru-badger |
|
||||||
---------------------------------------- |
|
||||||
Status: COMPLETED |
|
||||||
Events/sec: 18095.48 |
|
||||||
Events/sec: 6260.92 |
|
||||||
Events/sec: 18095.48 |
|
||||||
Success Rate: 100.0% |
|
||||||
Success Rate: 100.0% |
|
||||||
Success Rate: 100.0% |
|
||||||
Avg Latency: 1.143282ms |
|
||||||
Bottom 10% Avg Latency: 651.813µs |
|
||||||
Avg Latency: 1.203274ms |
|
||||||
P95 Latency: 1.721751ms |
|
||||||
P95 Latency: 2.200764ms |
|
||||||
P95 Latency: 865.67µs |
|
||||||
|
|
||||||
Relay: relayer-basic |
|
||||||
---------------------------------------- |
|
||||||
Status: COMPLETED |
|
||||||
Events/sec: 17973.91 |
|
||||||
Events/sec: 6364.14 |
|
||||||
Events/sec: 17973.91 |
|
||||||
Success Rate: 100.0% |
|
||||||
Success Rate: 100.0% |
|
||||||
Success Rate: 100.0% |
|
||||||
Avg Latency: 1.159149ms |
|
||||||
Bottom 10% Avg Latency: 666.22µs |
|
||||||
Avg Latency: 1.075436ms |
|
||||||
P95 Latency: 1.737633ms |
|
||||||
P95 Latency: 1.805733ms |
|
||||||
P95 Latency: 865.831µs |
|
||||||
|
|
||||||
Relay: strfry |
|
||||||
---------------------------------------- |
|
||||||
Status: COMPLETED |
|
||||||
Events/sec: 17906.42 |
|
||||||
Events/sec: 6245.55 |
|
||||||
Events/sec: 17906.42 |
|
||||||
Success Rate: 100.0% |
|
||||||
Success Rate: 100.0% |
|
||||||
Success Rate: 100.0% |
|
||||||
Avg Latency: 1.165583ms |
|
||||||
Bottom 10% Avg Latency: 663.03µs |
|
||||||
Avg Latency: 1.143689ms |
|
||||||
P95 Latency: 1.781377ms |
|
||||||
P95 Latency: 2.088623ms |
|
||||||
P95 Latency: 852.326µs |
|
||||||
|
|
||||||
Relay: nostr-rs-relay |
|
||||||
---------------------------------------- |
|
||||||
Status: COMPLETED |
|
||||||
Events/sec: 18036.49 |
|
||||||
Events/sec: 6278.12 |
|
||||||
Events/sec: 18036.49 |
|
||||||
Success Rate: 100.0% |
|
||||||
Success Rate: 100.0% |
|
||||||
Success Rate: 100.0% |
|
||||||
Avg Latency: 1.14847ms |
|
||||||
Bottom 10% Avg Latency: 653.417µs |
|
||||||
Avg Latency: 1.18248ms |
|
||||||
P95 Latency: 1.723577ms |
|
||||||
P95 Latency: 2.000325ms |
|
||||||
P95 Latency: 849.41µs |
|
||||||
|
|
||||||
|
|
||||||
================================================================ |
|
||||||
DETAILED RESULTS |
|
||||||
================================================================ |
|
||||||
|
|
||||||
Individual relay reports are available in: |
|
||||||
- /reports/run_20251120_055257/khatru-badger_results.txt |
|
||||||
- /reports/run_20251120_055257/khatru-sqlite_results.txt |
|
||||||
- /reports/run_20251120_055257/next-orly-badger_results.txt |
|
||||||
- /reports/run_20251120_055257/next-orly-dgraph_results.txt |
|
||||||
- /reports/run_20251120_055257/next-orly-neo4j_results.txt |
|
||||||
- /reports/run_20251120_055257/nostr-rs-relay_results.txt |
|
||||||
- /reports/run_20251120_055257/relayer-basic_results.txt |
|
||||||
- /reports/run_20251120_055257/strfry_results.txt |
|
||||||
|
|
||||||
================================================================ |
|
||||||
BENCHMARK COMPARISON TABLE |
|
||||||
================================================================ |
|
||||||
|
|
||||||
Relay Status Peak Tput/s Avg Latency Success Rate |
|
||||||
---- ------ ----------- ----------- ------------ |
|
||||||
next-orly-badger OK 17207.24 1.240424ms 100.0% |
|
||||||
next-orly-dgraph OK 15975.41 1.379901ms 100.0% |
|
||||||
next-orly-neo4j OK 18050.59 1.142811ms 100.0% |
|
||||||
khatru-sqlite OK 16911.01 1.278879ms 100.0% |
|
||||||
khatru-badger OK 18095.48 1.143282ms 100.0% |
|
||||||
relayer-basic OK 17973.91 1.159149ms 100.0% |
|
||||||
strfry OK 17906.42 1.165583ms 100.0% |
|
||||||
nostr-rs-relay OK 18036.49 1.14847ms 100.0% |
|
||||||
|
|
||||||
================================================================ |
|
||||||
End of Report |
|
||||||
================================================================ |
|
||||||
@ -0,0 +1,176 @@ |
|||||||
|
================================================================ |
||||||
|
NOSTR RELAY BENCHMARK AGGREGATE REPORT |
||||||
|
================================================================ |
||||||
|
Generated: 2025-11-20T15:53:41+00:00 |
||||||
|
Benchmark Configuration: |
||||||
|
Events per test: 50000 |
||||||
|
Concurrent workers: 24 |
||||||
|
Test duration: 60s |
||||||
|
|
||||||
|
Relays tested: 8 |
||||||
|
|
||||||
|
================================================================ |
||||||
|
SUMMARY BY RELAY |
||||||
|
================================================================ |
||||||
|
|
||||||
|
Relay: next-orly-badger |
||||||
|
---------------------------------------- |
||||||
|
Status: COMPLETED |
||||||
|
Events/sec: 17836.33 |
||||||
|
Events/sec: 6340.29 |
||||||
|
Events/sec: 17836.33 |
||||||
|
Success Rate: 100.0% |
||||||
|
Success Rate: 100.0% |
||||||
|
Success Rate: 100.0% |
||||||
|
Avg Latency: 1.176626ms |
||||||
|
Bottom 10% Avg Latency: 659.571µs |
||||||
|
Avg Latency: 1.150109ms |
||||||
|
P95 Latency: 1.79182ms |
||||||
|
P95 Latency: 1.87572ms |
||||||
|
P95 Latency: 870.11µs |
||||||
|
|
||||||
|
Relay: next-orly-dgraph |
||||||
|
---------------------------------------- |
||||||
|
Status: COMPLETED |
||||||
|
Events/sec: 16687.23 |
||||||
|
Events/sec: 6230.59 |
||||||
|
Events/sec: 16687.23 |
||||||
|
Success Rate: 100.0% |
||||||
|
Success Rate: 100.0% |
||||||
|
Success Rate: 100.0% |
||||||
|
Avg Latency: 1.299973ms |
||||||
|
Bottom 10% Avg Latency: 703.285µs |
||||||
|
Avg Latency: 1.216351ms |
||||||
|
P95 Latency: 2.203343ms |
||||||
|
P95 Latency: 2.205777ms |
||||||
|
P95 Latency: 869.669µs |
||||||
|
|
||||||
|
Relay: next-orly-neo4j |
||||||
|
---------------------------------------- |
||||||
|
Status: COMPLETED |
||||||
|
Events/sec: 17497.93 |
||||||
|
Events/sec: 6254.20 |
||||||
|
Events/sec: 17497.93 |
||||||
|
Success Rate: 100.0% |
||||||
|
Success Rate: 100.0% |
||||||
|
Success Rate: 100.0% |
||||||
|
Avg Latency: 1.220061ms |
||||||
|
Bottom 10% Avg Latency: 689.107µs |
||||||
|
Avg Latency: 1.207729ms |
||||||
|
P95 Latency: 1.873592ms |
||||||
|
P95 Latency: 2.026464ms |
||||||
|
P95 Latency: 860.711µs |
||||||
|
|
||||||
|
Relay: khatru-sqlite |
||||||
|
---------------------------------------- |
||||||
|
Status: COMPLETED |
||||||
|
Events/sec: 15692.37 |
||||||
|
Events/sec: 6031.64 |
||||||
|
Events/sec: 15692.37 |
||||||
|
Success Rate: 100.0% |
||||||
|
Success Rate: 100.0% |
||||||
|
Success Rate: 100.0% |
||||||
|
Avg Latency: 1.434878ms |
||||||
|
Bottom 10% Avg Latency: 773.12µs |
||||||
|
Avg Latency: 1.438112ms |
||||||
|
P95 Latency: 2.364988ms |
||||||
|
P95 Latency: 2.530373ms |
||||||
|
P95 Latency: 869.767µs |
||||||
|
|
||||||
|
Relay: khatru-badger |
||||||
|
---------------------------------------- |
||||||
|
Status: COMPLETED |
||||||
|
Events/sec: 15459.86 |
||||||
|
Events/sec: 6208.94 |
||||||
|
Events/sec: 15459.86 |
||||||
|
Success Rate: 100.0% |
||||||
|
Success Rate: 100.0% |
||||||
|
Success Rate: 100.0% |
||||||
|
Avg Latency: 1.468719ms |
||||||
|
Bottom 10% Avg Latency: 802.399µs |
||||||
|
Avg Latency: 1.250479ms |
||||||
|
P95 Latency: 2.396216ms |
||||||
|
P95 Latency: 2.142422ms |
||||||
|
P95 Latency: 869.166µs |
||||||
|
|
||||||
|
Relay: relayer-basic |
||||||
|
---------------------------------------- |
||||||
|
Status: COMPLETED |
||||||
|
Events/sec: 15191.51 |
||||||
|
Events/sec: 6144.49 |
||||||
|
Events/sec: 15191.51 |
||||||
|
Success Rate: 100.0% |
||||||
|
Success Rate: 100.0% |
||||||
|
Success Rate: 100.0% |
||||||
|
Avg Latency: 1.494499ms |
||||||
|
Bottom 10% Avg Latency: 790.923µs |
||||||
|
Avg Latency: 1.322915ms |
||||||
|
P95 Latency: 2.461731ms |
||||||
|
P95 Latency: 2.255818ms |
||||||
|
P95 Latency: 888.112µs |
||||||
|
|
||||||
|
Relay: strfry |
||||||
|
---------------------------------------- |
||||||
|
Status: COMPLETED |
||||||
|
Events/sec: 16583.98 |
||||||
|
Events/sec: 5979.92 |
||||||
|
Events/sec: 16583.98 |
||||||
|
Success Rate: 100.0% |
||||||
|
Success Rate: 100.0% |
||||||
|
Success Rate: 100.0% |
||||||
|
Avg Latency: 1.325163ms |
||||||
|
Bottom 10% Avg Latency: 732.389µs |
||||||
|
Avg Latency: 1.467778ms |
||||||
|
P95 Latency: 2.114188ms |
||||||
|
P95 Latency: 2.793392ms |
||||||
|
P95 Latency: 878.634µs |
||||||
|
|
||||||
|
Relay: nostr-rs-relay |
||||||
|
---------------------------------------- |
||||||
|
Status: COMPLETED |
||||||
|
Events/sec: 15250.43 |
||||||
|
Events/sec: 6286.54 |
||||||
|
Events/sec: 15250.43 |
||||||
|
Success Rate: 100.0% |
||||||
|
Success Rate: 100.0% |
||||||
|
Success Rate: 100.0% |
||||||
|
Avg Latency: 1.477342ms |
||||||
|
Bottom 10% Avg Latency: 760.393µs |
||||||
|
Avg Latency: 1.167307ms |
||||||
|
P95 Latency: 2.527756ms |
||||||
|
P95 Latency: 2.003086ms |
||||||
|
P95 Latency: 868.365µs |
||||||
|
|
||||||
|
|
||||||
|
================================================================ |
||||||
|
DETAILED RESULTS |
||||||
|
================================================================ |
||||||
|
|
||||||
|
Individual relay reports are available in: |
||||||
|
- /reports/run_20251120_152640/khatru-badger_results.txt |
||||||
|
- /reports/run_20251120_152640/khatru-sqlite_results.txt |
||||||
|
- /reports/run_20251120_152640/next-orly-badger_results.txt |
||||||
|
- /reports/run_20251120_152640/next-orly-dgraph_results.txt |
||||||
|
- /reports/run_20251120_152640/next-orly-neo4j_results.txt |
||||||
|
- /reports/run_20251120_152640/nostr-rs-relay_results.txt |
||||||
|
- /reports/run_20251120_152640/relayer-basic_results.txt |
||||||
|
- /reports/run_20251120_152640/strfry_results.txt |
||||||
|
|
||||||
|
================================================================ |
||||||
|
BENCHMARK COMPARISON TABLE |
||||||
|
================================================================ |
||||||
|
|
||||||
|
Relay Status Peak Tput/s Avg Latency Success Rate |
||||||
|
---- ------ ----------- ----------- ------------ |
||||||
|
next-orly-badger OK 17836.33 1.176626ms 100.0% |
||||||
|
next-orly-dgraph OK 16687.23 1.299973ms 100.0% |
||||||
|
next-orly-neo4j OK 17497.93 1.220061ms 100.0% |
||||||
|
khatru-sqlite OK 15692.37 1.434878ms 100.0% |
||||||
|
khatru-badger OK 15459.86 1.468719ms 100.0% |
||||||
|
relayer-basic OK 15191.51 1.494499ms 100.0% |
||||||
|
strfry OK 16583.98 1.325163ms 100.0% |
||||||
|
nostr-rs-relay OK 15250.43 1.477342ms 100.0% |
||||||
|
|
||||||
|
================================================================ |
||||||
|
End of Report |
||||||
|
================================================================ |
||||||
@ -0,0 +1,3 @@ |
|||||||
|
RELAY: rely-sqlite |
||||||
|
STATUS: FAILED - Relay not responding |
||||||
|
ERROR: Connection failed |
||||||
@ -0,0 +1,3 @@ |
|||||||
|
RELAY: rely-sqlite |
||||||
|
STATUS: FAILED - Relay not responding |
||||||
|
ERROR: Connection failed |
||||||
@ -0,0 +1,194 @@ |
|||||||
|
================================================================ |
||||||
|
NOSTR RELAY BENCHMARK AGGREGATE REPORT |
||||||
|
================================================================ |
||||||
|
Generated: 2025-11-20T20:32:25+00:00 |
||||||
|
Benchmark Configuration: |
||||||
|
Events per test: 50000 |
||||||
|
Concurrent workers: 24 |
||||||
|
Test duration: 60s |
||||||
|
|
||||||
|
Relays tested: 9 |
||||||
|
|
||||||
|
================================================================ |
||||||
|
SUMMARY BY RELAY |
||||||
|
================================================================ |
||||||
|
|
||||||
|
Relay: rely-sqlite |
||||||
|
---------------------------------------- |
||||||
|
Status: COMPLETED |
||||||
|
Events/sec: 17507.10 |
||||||
|
Events/sec: 6243.12 |
||||||
|
Events/sec: 17507.10 |
||||||
|
Success Rate: 100.0% |
||||||
|
Success Rate: 100.0% |
||||||
|
Success Rate: 100.0% |
||||||
|
Avg Latency: 1.223582ms |
||||||
|
Bottom 10% Avg Latency: 698.877µs |
||||||
|
Avg Latency: 1.178662ms |
||||||
|
P95 Latency: 1.87223ms |
||||||
|
P95 Latency: 2.046981ms |
||||||
|
P95 Latency: 883.507µs |
||||||
|
|
||||||
|
Relay: next-orly-badger |
||||||
|
---------------------------------------- |
||||||
|
Status: COMPLETED |
||||||
|
Events/sec: 16840.34 |
||||||
|
Events/sec: 6128.23 |
||||||
|
Events/sec: 16840.34 |
||||||
|
Success Rate: 100.0% |
||||||
|
Success Rate: 100.0% |
||||||
|
Success Rate: 100.0% |
||||||
|
Avg Latency: 1.297596ms |
||||||
|
Bottom 10% Avg Latency: 722.094µs |
||||||
|
Avg Latency: 1.265918ms |
||||||
|
P95 Latency: 2.027536ms |
||||||
|
P95 Latency: 2.302166ms |
||||||
|
P95 Latency: 894.834µs |
||||||
|
|
||||||
|
Relay: next-orly-dgraph |
||||||
|
---------------------------------------- |
||||||
|
Status: COMPLETED |
||||||
|
Events/sec: 16563.45 |
||||||
|
Events/sec: 6132.86 |
||||||
|
Events/sec: 16563.45 |
||||||
|
Success Rate: 100.0% |
||||||
|
Success Rate: 100.0% |
||||||
|
Success Rate: 100.0% |
||||||
|
Avg Latency: 1.32589ms |
||||||
|
Bottom 10% Avg Latency: 726.176µs |
||||||
|
Avg Latency: 1.340819ms |
||||||
|
P95 Latency: 2.152481ms |
||||||
|
P95 Latency: 2.37338ms |
||||||
|
P95 Latency: 904.165µs |
||||||
|
|
||||||
|
Relay: next-orly-neo4j |
||||||
|
---------------------------------------- |
||||||
|
Status: COMPLETED |
||||||
|
Events/sec: 14622.22 |
||||||
|
Events/sec: 6182.48 |
||||||
|
Events/sec: 14622.22 |
||||||
|
Success Rate: 100.0% |
||||||
|
Success Rate: 100.0% |
||||||
|
Success Rate: 100.0% |
||||||
|
Avg Latency: 1.559545ms |
||||||
|
Bottom 10% Avg Latency: 795.698µs |
||||||
|
Avg Latency: 1.269605ms |
||||||
|
P95 Latency: 2.658118ms |
||||||
|
P95 Latency: 2.293256ms |
||||||
|
P95 Latency: 867.888µs |
||||||
|
|
||||||
|
Relay: khatru-sqlite |
||||||
|
---------------------------------------- |
||||||
|
Status: COMPLETED |
||||||
|
Events/sec: 16872.81 |
||||||
|
Events/sec: 6219.91 |
||||||
|
Events/sec: 16872.81 |
||||||
|
Success Rate: 100.0% |
||||||
|
Success Rate: 100.0% |
||||||
|
Success Rate: 100.0% |
||||||
|
Avg Latency: 1.294206ms |
||||||
|
Bottom 10% Avg Latency: 724.237µs |
||||||
|
Avg Latency: 1.28288ms |
||||||
|
P95 Latency: 2.011193ms |
||||||
|
P95 Latency: 2.16732ms |
||||||
|
P95 Latency: 868.521µs |
||||||
|
|
||||||
|
Relay: khatru-badger |
||||||
|
---------------------------------------- |
||||||
|
Status: COMPLETED |
||||||
|
Events/sec: 15204.92 |
||||||
|
Events/sec: 6277.98 |
||||||
|
Events/sec: 15204.92 |
||||||
|
Success Rate: 100.0% |
||||||
|
Success Rate: 100.0% |
||||||
|
Success Rate: 100.0% |
||||||
|
Avg Latency: 1.485679ms |
||||||
|
Bottom 10% Avg Latency: 768.979µs |
||||||
|
Avg Latency: 1.216531ms |
||||||
|
P95 Latency: 2.501619ms |
||||||
|
P95 Latency: 2.028348ms |
||||||
|
P95 Latency: 862.271µs |
||||||
|
|
||||||
|
Relay: relayer-basic |
||||||
|
---------------------------------------- |
||||||
|
Status: COMPLETED |
||||||
|
Events/sec: 17272.97 |
||||||
|
Events/sec: 6207.90 |
||||||
|
Events/sec: 17272.97 |
||||||
|
Success Rate: 100.0% |
||||||
|
Success Rate: 100.0% |
||||||
|
Success Rate: 100.0% |
||||||
|
Avg Latency: 1.255956ms |
||||||
|
Bottom 10% Avg Latency: 712.498µs |
||||||
|
Avg Latency: 1.21703ms |
||||||
|
P95 Latency: 1.909735ms |
||||||
|
P95 Latency: 2.233521ms |
||||||
|
P95 Latency: 871.278µs |
||||||
|
|
||||||
|
Relay: strfry |
||||||
|
---------------------------------------- |
||||||
|
Status: COMPLETED |
||||||
|
Events/sec: 15745.79 |
||||||
|
Events/sec: 6264.53 |
||||||
|
Events/sec: 15745.79 |
||||||
|
Success Rate: 100.0% |
||||||
|
Success Rate: 100.0% |
||||||
|
Success Rate: 100.0% |
||||||
|
Avg Latency: 1.415908ms |
||||||
|
Bottom 10% Avg Latency: 739.523µs |
||||||
|
Avg Latency: 1.153768ms |
||||||
|
P95 Latency: 2.340716ms |
||||||
|
P95 Latency: 2.007502ms |
||||||
|
P95 Latency: 855.87µs |
||||||
|
|
||||||
|
Relay: nostr-rs-relay |
||||||
|
---------------------------------------- |
||||||
|
Status: COMPLETED |
||||||
|
Events/sec: 17638.66 |
||||||
|
Events/sec: 6241.74 |
||||||
|
Events/sec: 17638.66 |
||||||
|
Success Rate: 100.0% |
||||||
|
Success Rate: 100.0% |
||||||
|
Success Rate: 100.0% |
||||||
|
Avg Latency: 1.18563ms |
||||||
|
Bottom 10% Avg Latency: 646.954µs |
||||||
|
Avg Latency: 1.182584ms |
||||||
|
P95 Latency: 1.847889ms |
||||||
|
P95 Latency: 2.120267ms |
||||||
|
P95 Latency: 866.51µs |
||||||
|
|
||||||
|
|
||||||
|
================================================================ |
||||||
|
DETAILED RESULTS |
||||||
|
================================================================ |
||||||
|
|
||||||
|
Individual relay reports are available in: |
||||||
|
- /reports/run_20251120_200202/khatru-badger_results.txt |
||||||
|
- /reports/run_20251120_200202/khatru-sqlite_results.txt |
||||||
|
- /reports/run_20251120_200202/next-orly-badger_results.txt |
||||||
|
- /reports/run_20251120_200202/next-orly-dgraph_results.txt |
||||||
|
- /reports/run_20251120_200202/next-orly-neo4j_results.txt |
||||||
|
- /reports/run_20251120_200202/nostr-rs-relay_results.txt |
||||||
|
- /reports/run_20251120_200202/relayer-basic_results.txt |
||||||
|
- /reports/run_20251120_200202/rely-sqlite_results.txt |
||||||
|
- /reports/run_20251120_200202/strfry_results.txt |
||||||
|
|
||||||
|
================================================================ |
||||||
|
BENCHMARK COMPARISON TABLE |
||||||
|
================================================================ |
||||||
|
|
||||||
|
Relay Status Peak Tput/s Avg Latency Success Rate |
||||||
|
---- ------ ----------- ----------- ------------ |
||||||
|
rely-sqlite OK 17507.10 1.223582ms 100.0% |
||||||
|
next-orly-badger OK 16840.34 1.297596ms 100.0% |
||||||
|
next-orly-dgraph OK 16563.45 1.32589ms 100.0% |
||||||
|
next-orly-neo4j OK 14622.22 1.559545ms 100.0% |
||||||
|
khatru-sqlite OK 16872.81 1.294206ms 100.0% |
||||||
|
khatru-badger OK 15204.92 1.485679ms 100.0% |
||||||
|
relayer-basic OK 17272.97 1.255956ms 100.0% |
||||||
|
strfry OK 15745.79 1.415908ms 100.0% |
||||||
|
nostr-rs-relay OK 17638.66 1.18563ms 100.0% |
||||||
|
|
||||||
|
================================================================ |
||||||
|
End of Report |
||||||
|
================================================================ |
||||||
Loading…
Reference in new issue