diff --git a/app/handle-event.go b/app/handle-event.go index c978d4d..701217c 100644 --- a/app/handle-event.go +++ b/app/handle-event.go @@ -27,7 +27,10 @@ func (l *Listener) HandleEvent(msg []byte) (err error) { log.E.F("HandleEvent: failed to unmarshal event: %v", err) return } - log.I.F("HandleEvent: successfully unmarshaled event, kind: %d, pubkey: %s", env.E.Kind, hex.Enc(env.E.Pubkey)) + log.I.F( + "HandleEvent: successfully unmarshaled event, kind: %d, pubkey: %s", + env.E.Kind, hex.Enc(env.E.Pubkey), + ) defer func() { if env != nil && env.E != nil { env.E.Free() @@ -45,7 +48,8 @@ func (l *Listener) HandleEvent(msg []byte) (err error) { // Sprocket is disabled due to failure - reject all events log.W.F("sprocket is disabled, rejecting event %0x", env.E.ID) if err = Ok.Error( - l, env, "sprocket disabled - events rejected until sprocket is restored", + l, env, + "sprocket disabled - events rejected until sprocket is restored", ); chk.E(err) { return } @@ -54,9 +58,13 @@ func (l *Listener) HandleEvent(msg []byte) (err error) { if !l.sprocketManager.IsRunning() { // Sprocket is enabled but not running - reject all events - log.W.F("sprocket is enabled but not running, rejecting event %0x", env.E.ID) + log.W.F( + "sprocket is enabled but not running, rejecting event %0x", + env.E.ID, + ) if err = Ok.Error( - l, env, "sprocket not running - events rejected until sprocket starts", + l, env, + "sprocket not running - events rejected until sprocket starts", ); chk.E(err) { return } @@ -134,13 +142,19 @@ func (l *Listener) HandleEvent(msg []byte) (err error) { return } // check permissions of user - log.I.F("HandleEvent: checking ACL permissions for pubkey: %s", hex.Enc(l.authedPubkey.Load())) + log.I.F( + "HandleEvent: checking ACL permissions for pubkey: %s", + hex.Enc(l.authedPubkey.Load()), + ) // If ACL mode is "none" and no pubkey is set, use the event's pubkey var pubkeyForACL []byte if len(l.authedPubkey.Load()) == 0 && acl.Registry.Active.Load() == "none" { pubkeyForACL = env.E.Pubkey - log.I.F("HandleEvent: ACL mode is 'none', using event pubkey for ACL check: %s", hex.Enc(pubkeyForACL)) + log.I.F( + "HandleEvent: ACL mode is 'none', using event pubkey for ACL check: %s", + hex.Enc(pubkeyForACL), + ) } else { pubkeyForACL = l.authedPubkey.Load() } @@ -174,7 +188,8 @@ func (l *Listener) HandleEvent(msg []byte) (err error) { switch accessLevel { case "none": log.D.F( - "handle event: sending 'OK,false,auth-required...' to %s", l.remote, + "handle event: sending 'OK,false,auth-required...' to %s", + l.remote, ) if err = okenvelope.NewFrom( env.Id(), false, @@ -242,16 +257,24 @@ func (l *Listener) HandleEvent(msg []byte) (err error) { } } // if the event is a delete, process the delete - log.I.F("HandleEvent: checking if event is delete - kind: %d, EventDeletion.K: %d", env.E.Kind, kind.EventDeletion.K) + log.I.F( + "HandleEvent: checking if event is delete - kind: %d, EventDeletion.K: %d", + env.E.Kind, kind.EventDeletion.K, + ) if env.E.Kind == kind.EventDeletion.K { log.I.F("processing delete event %0x", env.E.ID) // Store the delete event itself FIRST to ensure it's available for queries - saveCtx, cancel := context.WithTimeout(context.Background(), 30*time.Second) + saveCtx, cancel := context.WithTimeout( + context.Background(), 30*time.Second, + ) defer cancel() - log.I.F("attempting to save delete event %0x from pubkey %0x", env.E.ID, env.E.Pubkey) + log.I.F( + "attempting to save delete event %0x from pubkey %0x", env.E.ID, + env.E.Pubkey, + ) log.I.F("delete event pubkey hex: %s", hex.Enc(env.E.Pubkey)) - if _, _, err = l.SaveEvent(saveCtx, env.E); err != nil { + if err, _ = l.SaveEvent(saveCtx, env.E); err != nil { log.E.F("failed to save delete event %0x: %v", env.E.ID, err) if strings.HasPrefix(err.Error(), "blocked:") { errStr := err.Error()[len("blocked: "):len(err.Error())] @@ -282,7 +305,9 @@ func (l *Listener) HandleEvent(msg []byte) (err error) { // For non-blocked errors, still send OK but log the error log.W.F("Delete processing failed but continuing: %v", err) } else { - log.I.F("HandleDelete completed successfully for event %0x", env.E.ID) + log.I.F( + "HandleDelete completed successfully for event %0x", env.E.ID, + ) } // Send OK response for delete events @@ -314,7 +339,7 @@ func (l *Listener) HandleEvent(msg []byte) (err error) { saveCtx, cancel := context.WithTimeout(context.Background(), 30*time.Second) defer cancel() // log.I.F("saving event %0x, %s", env.E.ID, env.E.Serialize()) - if _, _, err = l.SaveEvent(saveCtx, env.E); err != nil { + if err, _ = l.SaveEvent(saveCtx, env.E); err != nil { if strings.HasPrefix(err.Error(), "blocked:") { errStr := err.Error()[len("blocked: "):len(err.Error())] if err = Ok.Error( diff --git a/app/payment_processor.go b/app/payment_processor.go index c3a694a..45d8894 100644 --- a/app/payment_processor.go +++ b/app/payment_processor.go @@ -166,7 +166,7 @@ func (pp *PaymentProcessor) syncFollowList() error { } // sign and save ev.Sign(sign) - if _, _, err := pp.db.SaveEvent(pp.ctx, ev); err != nil { + if err, _ := pp.db.SaveEvent(pp.ctx, ev); err != nil { return err } log.I.F( @@ -224,7 +224,7 @@ func (pp *PaymentProcessor) checkSubscriptionStatus() error { key := item.KeyCopy(nil) // key format: sub: hexpub := string(key[len(prefix):]) - + var sub database.Subscription if err := item.Value( func(val []byte) error { @@ -233,23 +233,23 @@ func (pp *PaymentProcessor) checkSubscriptionStatus() error { ); err != nil { continue // skip invalid subscription records } - + pubkey, err := hex.Dec(hexpub) if err != nil { continue // skip invalid pubkey } - + // Check if paid subscription is expiring in 7 days if !sub.PaidUntil.IsZero() { // Format dates for comparison (ignore time component) paidUntilDate := sub.PaidUntil.Truncate(24 * time.Hour) sevenDaysDate := sevenDaysFromNow.Truncate(24 * time.Hour) - + if paidUntilDate.Equal(sevenDaysDate) { go pp.createExpiryWarningNote(pubkey, sub.PaidUntil) } } - + // Check if user is on trial (no paid subscription, trial not expired) if sub.PaidUntil.IsZero() && now.Before(sub.TrialEnd) { go pp.createTrialReminderNote(pubkey, sub.TrialEnd) @@ -261,7 +261,9 @@ func (pp *PaymentProcessor) checkSubscriptionStatus() error { } // createExpiryWarningNote creates a warning note for users whose paid subscription expires in 7 days -func (pp *PaymentProcessor) createExpiryWarningNote(userPubkey []byte, expiryTime time.Time) error { +func (pp *PaymentProcessor) createExpiryWarningNote( + userPubkey []byte, expiryTime time.Time, +) error { // Get relay identity secret to sign the note skb, err := pp.db.GetRelayIdentitySecret() if err != nil || len(skb) != 32 { @@ -286,7 +288,8 @@ func (pp *PaymentProcessor) createExpiryWarningNote(userPubkey []byte, expiryTim } // Create the warning note content - content := fmt.Sprintf(`⚠️ Subscription Expiring Soon ⚠️ + content := fmt.Sprintf( + `⚠️ Subscription Expiring Soon ⚠️ Your paid subscription to this relay will expire in 7 days on %s. @@ -304,8 +307,10 @@ Don't lose access to your private relay! Extend your subscription today. Relay: nostr:%s -Log in to the relay dashboard to access your configuration at: %s`, - expiryTime.Format("2006-01-02 15:04:05 UTC"), monthlyPrice, monthlyPrice, string(relayNpubForContent), pp.getDashboardURL()) +Log in to the relay dashboard to access your configuration at: %s`, + expiryTime.Format("2006-01-02 15:04:05 UTC"), monthlyPrice, + monthlyPrice, string(relayNpubForContent), pp.getDashboardURL(), + ) // Build the event ev := event.New() @@ -320,17 +325,20 @@ Log in to the relay dashboard to access your configuration at: %s`, // Add expiration tag (5 days from creation) noteExpiry := time.Now().AddDate(0, 0, 5) - *ev.Tags = append(*ev.Tags, tag.NewFromAny("expiration", fmt.Sprintf("%d", noteExpiry.Unix()))) + *ev.Tags = append( + *ev.Tags, + tag.NewFromAny("expiration", fmt.Sprintf("%d", noteExpiry.Unix())), + ) // Add "private" tag with authorized npubs (user and relay) var authorizedNpubs []string - + // Add user npub userNpub, err := bech32encoding.BinToNpub(userPubkey) if err == nil { authorizedNpubs = append(authorizedNpubs, string(userNpub)) } - + // Add relay npub relayNpub, err := bech32encoding.BinToNpub(sign.Pub()) if err == nil { @@ -344,20 +352,27 @@ Log in to the relay dashboard to access your configuration at: %s`, } // Add a special tag to mark this as an expiry warning - *ev.Tags = append(*ev.Tags, tag.NewFromAny("warning", "subscription-expiry")) + *ev.Tags = append( + *ev.Tags, tag.NewFromAny("warning", "subscription-expiry"), + ) // Sign and save the event ev.Sign(sign) - if _, _, err := pp.db.SaveEvent(pp.ctx, ev); err != nil { + if err, _ := pp.db.SaveEvent(pp.ctx, ev); err != nil { return fmt.Errorf("failed to save expiry warning note: %w", err) } - log.I.F("created expiry warning note for user %s (expires %s)", hex.Enc(userPubkey), expiryTime.Format("2006-01-02")) + log.I.F( + "created expiry warning note for user %s (expires %s)", + hex.Enc(userPubkey), expiryTime.Format("2006-01-02"), + ) return nil } // createTrialReminderNote creates a reminder note for users on trial to support the relay -func (pp *PaymentProcessor) createTrialReminderNote(userPubkey []byte, trialEnd time.Time) error { +func (pp *PaymentProcessor) createTrialReminderNote( + userPubkey []byte, trialEnd time.Time, +) error { // Get relay identity secret to sign the note skb, err := pp.db.GetRelayIdentitySecret() if err != nil || len(skb) != 32 { @@ -385,7 +400,8 @@ func (pp *PaymentProcessor) createTrialReminderNote(userPubkey []byte, trialEnd } // Create the reminder note content - content := fmt.Sprintf(`🆓 Free Trial Reminder 🆓 + content := fmt.Sprintf( + `🆓 Free Trial Reminder 🆓 You're currently using this relay for FREE! Your trial expires on %s. @@ -407,8 +423,10 @@ Thank you for considering supporting decentralized communication! Relay: nostr:%s -Log in to the relay dashboard to access your configuration at: %s`, - trialEnd.Format("2006-01-02 15:04:05 UTC"), monthlyPrice, dailyRate, monthlyPrice, string(relayNpubForContent), pp.getDashboardURL()) +Log in to the relay dashboard to access your configuration at: %s`, + trialEnd.Format("2006-01-02 15:04:05 UTC"), monthlyPrice, dailyRate, + monthlyPrice, string(relayNpubForContent), pp.getDashboardURL(), + ) // Build the event ev := event.New() @@ -423,17 +441,20 @@ Log in to the relay dashboard to access your configuration at: %s`, // Add expiration tag (5 days from creation) noteExpiry := time.Now().AddDate(0, 0, 5) - *ev.Tags = append(*ev.Tags, tag.NewFromAny("expiration", fmt.Sprintf("%d", noteExpiry.Unix()))) + *ev.Tags = append( + *ev.Tags, + tag.NewFromAny("expiration", fmt.Sprintf("%d", noteExpiry.Unix())), + ) // Add "private" tag with authorized npubs (user and relay) var authorizedNpubs []string - + // Add user npub userNpub, err := bech32encoding.BinToNpub(userPubkey) if err == nil { authorizedNpubs = append(authorizedNpubs, string(userNpub)) } - + // Add relay npub relayNpub, err := bech32encoding.BinToNpub(sign.Pub()) if err == nil { @@ -451,11 +472,14 @@ Log in to the relay dashboard to access your configuration at: %s`, // Sign and save the event ev.Sign(sign) - if _, _, err := pp.db.SaveEvent(pp.ctx, ev); err != nil { + if err, _ := pp.db.SaveEvent(pp.ctx, ev); err != nil { return fmt.Errorf("failed to save trial reminder note: %w", err) } - log.I.F("created trial reminder note for user %s (trial ends %s)", hex.Enc(userPubkey), trialEnd.Format("2006-01-02")) + log.I.F( + "created trial reminder note for user %s (trial ends %s)", + hex.Enc(userPubkey), trialEnd.Format("2006-01-02"), + ) return nil } @@ -501,8 +525,13 @@ func (pp *PaymentProcessor) handleNotification( if skb, err := pp.db.GetRelayIdentitySecret(); err == nil && len(skb) == 32 { var signer p256k.Signer if err := signer.InitSec(skb); err == nil { - if !strings.EqualFold(hex.Enc(rpk), hex.Enc(signer.Pub())) { - log.W.F("relay_pubkey in payment metadata does not match this relay identity: got %s want %s", hex.Enc(rpk), hex.Enc(signer.Pub())) + if !strings.EqualFold( + hex.Enc(rpk), hex.Enc(signer.Pub()), + ) { + log.W.F( + "relay_pubkey in payment metadata does not match this relay identity: got %s want %s", + hex.Enc(rpk), hex.Enc(signer.Pub()), + ) } } } @@ -557,9 +586,15 @@ func (pp *PaymentProcessor) handleNotification( // Log helpful identifiers var payerHex = hex.Enc(pubkey) if userNpub == "" { - log.I.F("payment processed: payer %s %d sats -> %d days", payerHex, satsReceived, days) + log.I.F( + "payment processed: payer %s %d sats -> %d days", payerHex, + satsReceived, days, + ) } else { - log.I.F("payment processed: %s (%s) %d sats -> %d days", userNpub, payerHex, satsReceived, days) + log.I.F( + "payment processed: %s (%s) %d sats -> %d days", userNpub, payerHex, + satsReceived, days, + ) } // Update ACL follows cache and relay follow list immediately @@ -578,7 +613,9 @@ func (pp *PaymentProcessor) handleNotification( } // createPaymentNote creates a note recording the payment with private tag for authorization -func (pp *PaymentProcessor) createPaymentNote(payerPubkey []byte, satsReceived int64, days int) error { +func (pp *PaymentProcessor) createPaymentNote( + payerPubkey []byte, satsReceived int64, days int, +) error { // Get relay identity secret to sign the note skb, err := pp.db.GetRelayIdentitySecret() if err != nil || len(skb) != 32 { @@ -611,8 +648,11 @@ func (pp *PaymentProcessor) createPaymentNote(payerPubkey []byte, satsReceived i } // Create the note content with nostr:npub link and dashboard link - content := fmt.Sprintf("Payment received: %d sats for %d days. Subscription expires: %s\n\nRelay: nostr:%s\n\nLog in to the relay dashboard to access your configuration at: %s", - satsReceived, days, expiryTime.Format("2006-01-02 15:04:05 UTC"), string(relayNpubForContent), pp.getDashboardURL()) + content := fmt.Sprintf( + "Payment received: %d sats for %d days. Subscription expires: %s\n\nRelay: nostr:%s\n\nLog in to the relay dashboard to access your configuration at: %s", + satsReceived, days, expiryTime.Format("2006-01-02 15:04:05 UTC"), + string(relayNpubForContent), pp.getDashboardURL(), + ) // Build the event ev := event.New() @@ -627,17 +667,20 @@ func (pp *PaymentProcessor) createPaymentNote(payerPubkey []byte, satsReceived i // Add expiration tag (5 days from creation) noteExpiry := time.Now().AddDate(0, 0, 5) - *ev.Tags = append(*ev.Tags, tag.NewFromAny("expiration", fmt.Sprintf("%d", noteExpiry.Unix()))) + *ev.Tags = append( + *ev.Tags, + tag.NewFromAny("expiration", fmt.Sprintf("%d", noteExpiry.Unix())), + ) // Add "private" tag with authorized npubs (payer and relay) var authorizedNpubs []string - + // Add payer npub payerNpub, err := bech32encoding.BinToNpub(payerPubkey) if err == nil { authorizedNpubs = append(authorizedNpubs, string(payerNpub)) } - + // Add relay npub relayNpub, err := bech32encoding.BinToNpub(sign.Pub()) if err == nil { @@ -652,11 +695,14 @@ func (pp *PaymentProcessor) createPaymentNote(payerPubkey []byte, satsReceived i // Sign and save the event ev.Sign(sign) - if _, _, err := pp.db.SaveEvent(pp.ctx, ev); err != nil { + if err, _ := pp.db.SaveEvent(pp.ctx, ev); err != nil { return fmt.Errorf("failed to save payment note: %w", err) } - log.I.F("created payment note for %s with private authorization", hex.Enc(payerPubkey)) + log.I.F( + "created payment note for %s with private authorization", + hex.Enc(payerPubkey), + ) return nil } @@ -686,7 +732,8 @@ func (pp *PaymentProcessor) CreateWelcomeNote(userPubkey []byte) error { } // Create the welcome note content with nostr:npub link - content := fmt.Sprintf(`Welcome to the relay! 🎉 + content := fmt.Sprintf( + `Welcome to the relay! 🎉 You have a FREE 30-day trial that started when you first logged in. @@ -706,7 +753,9 @@ Relay: nostr:%s Log in to the relay dashboard to access your configuration at: %s -Enjoy your time on the relay!`, monthlyPrice, monthlyPrice, string(relayNpubForContent), pp.getDashboardURL()) +Enjoy your time on the relay!`, monthlyPrice, monthlyPrice, + string(relayNpubForContent), pp.getDashboardURL(), + ) // Build the event ev := event.New() @@ -721,17 +770,20 @@ Enjoy your time on the relay!`, monthlyPrice, monthlyPrice, string(relayNpubForC // Add expiration tag (5 days from creation) noteExpiry := time.Now().AddDate(0, 0, 5) - *ev.Tags = append(*ev.Tags, tag.NewFromAny("expiration", fmt.Sprintf("%d", noteExpiry.Unix()))) + *ev.Tags = append( + *ev.Tags, + tag.NewFromAny("expiration", fmt.Sprintf("%d", noteExpiry.Unix())), + ) // Add "private" tag with authorized npubs (user and relay) var authorizedNpubs []string - + // Add user npub userNpub, err := bech32encoding.BinToNpub(userPubkey) if err == nil { authorizedNpubs = append(authorizedNpubs, string(userNpub)) } - + // Add relay npub relayNpub, err := bech32encoding.BinToNpub(sign.Pub()) if err == nil { @@ -749,7 +801,7 @@ Enjoy your time on the relay!`, monthlyPrice, monthlyPrice, string(relayNpubForC // Sign and save the event ev.Sign(sign) - if _, _, err := pp.db.SaveEvent(pp.ctx, ev); err != nil { + if err, _ := pp.db.SaveEvent(pp.ctx, ev); err != nil { return fmt.Errorf("failed to save welcome note: %w", err) } @@ -846,13 +898,15 @@ func (pp *PaymentProcessor) UpdateRelayProfile() error { relayURL := strings.Replace(pp.getDashboardURL(), "https://", "wss://", 1) // Create profile content as JSON - profileContent := fmt.Sprintf(`{ + profileContent := fmt.Sprintf( + `{ "name": "Relay Bot", "about": "This relay requires a subscription to access. Zap any of my notes to pay for access. Monthly price: %d sats (%d sats/day). Relay: %s", "lud16": "", "nip05": "", "website": "%s" -}`, monthlyPrice, dailyRate, relayURL, pp.getDashboardURL()) +}`, monthlyPrice, dailyRate, relayURL, pp.getDashboardURL(), + ) // Build the profile event ev := event.New() @@ -864,7 +918,7 @@ func (pp *PaymentProcessor) UpdateRelayProfile() error { // Sign and save the event ev.Sign(sign) - if _, _, err := pp.db.SaveEvent(pp.ctx, ev); err != nil { + if err, _ := pp.db.SaveEvent(pp.ctx, ev); err != nil { return fmt.Errorf("failed to save relay profile: %w", err) } diff --git a/cmd/benchmark/main.go b/cmd/benchmark/main.go index 2f2428e..659ea6d 100644 --- a/cmd/benchmark/main.go +++ b/cmd/benchmark/main.go @@ -370,7 +370,7 @@ func (b *Benchmark) RunPeakThroughputTest() { for ev := range eventChan { eventStart := time.Now() - _, _, err := b.db.SaveEvent(ctx, ev) + err, _ := b.db.SaveEvent(ctx, ev) latency := time.Since(eventStart) mu.Lock() @@ -460,7 +460,7 @@ func (b *Benchmark) RunBurstPatternTest() { defer wg.Done() eventStart := time.Now() - _, _, err := b.db.SaveEvent(ctx, ev) + err, _ := b.db.SaveEvent(ctx, ev) latency := time.Since(eventStart) mu.Lock() @@ -554,7 +554,7 @@ func (b *Benchmark) RunMixedReadWriteTest() { if eventIndex%2 == 0 { // Write operation writeStart := time.Now() - _, _, err := b.db.SaveEvent(ctx, events[eventIndex]) + err, _ := b.db.SaveEvent(ctx, events[eventIndex]) writeLatency := time.Since(writeStart) mu.Lock() @@ -878,7 +878,7 @@ func (b *Benchmark) RunConcurrentQueryStoreTest() { for time.Since(start) < b.config.TestDuration && eventIndex < len(writeEvents) { // Write operation writeStart := time.Now() - _, _, err := b.db.SaveEvent(ctx, writeEvents[eventIndex]) + err, _ := b.db.SaveEvent(ctx, writeEvents[eventIndex]) writeLatency := time.Since(writeStart) mu.Lock() diff --git a/pkg/acl/follows.go b/pkg/acl/follows.go index 5bfca33..c2f2f7a 100644 --- a/pkg/acl/follows.go +++ b/pkg/acl/follows.go @@ -422,7 +422,7 @@ func (f *Follows) startSubscriptions(ctx context.Context) { ) } - if _, _, err = f.D.SaveEvent( + if err, _ = f.D.SaveEvent( ctx, res.Event, ); err != nil { if !strings.HasPrefix( diff --git a/pkg/database/export_test.go b/pkg/database/export_test.go index 53e6b63..acd9eff 100644 --- a/pkg/database/export_test.go +++ b/pkg/database/export_test.go @@ -55,7 +55,7 @@ func TestExport(t *testing.T) { } // Save the event to the database - if _, _, err = db.SaveEvent(ctx, ev); err != nil { + if err, _ = db.SaveEvent(ctx, ev); err != nil { t.Fatalf("Failed to save event: %v", err) } diff --git a/pkg/database/fetch-event-by-serial_test.go b/pkg/database/fetch-event-by-serial_test.go index 3015a73..4f6c42b 100644 --- a/pkg/database/fetch-event-by-serial_test.go +++ b/pkg/database/fetch-event-by-serial_test.go @@ -58,7 +58,7 @@ func TestFetchEventBySerial(t *testing.T) { events = append(events, ev) // Save the event to the database - if _, _, err = db.SaveEvent(ctx, ev); err != nil { + if err, _ = db.SaveEvent(ctx, ev); err != nil { t.Fatalf("Failed to save event #%d: %v", eventCount+1, err) } diff --git a/pkg/database/get-serial-by-id_test.go b/pkg/database/get-serial-by-id_test.go index b54717b..d9978de 100644 --- a/pkg/database/get-serial-by-id_test.go +++ b/pkg/database/get-serial-by-id_test.go @@ -52,11 +52,11 @@ func TestGetSerialById(t *testing.T) { t.Fatal(err) } ev.Free() - + events = append(events, ev) // Save the event to the database - if _, _, err = db.SaveEvent(ctx, ev); err != nil { + if err, _ = db.SaveEvent(ctx, ev); err != nil { t.Fatalf("Failed to save event #%d: %v", eventCount+1, err) } diff --git a/pkg/database/get-serials-by-range_test.go b/pkg/database/get-serials-by-range_test.go index 0526697..809202b 100644 --- a/pkg/database/get-serials-by-range_test.go +++ b/pkg/database/get-serials-by-range_test.go @@ -63,7 +63,7 @@ func TestGetSerialsByRange(t *testing.T) { events = append(events, ev) // Save the event to the database - if _, _, err = db.SaveEvent(ctx, ev); err != nil { + if err, _ = db.SaveEvent(ctx, ev); err != nil { t.Fatalf("Failed to save event #%d: %v", eventCount+1, err) } diff --git a/pkg/database/import.go b/pkg/database/import.go index 6173703..dbaed84 100644 --- a/pkg/database/import.go +++ b/pkg/database/import.go @@ -59,7 +59,7 @@ func (d *D) Import(rr io.Reader) { continue } - if _, _, err = d.SaveEvent(d.ctx, ev); err != nil { + if err, _ = d.SaveEvent(d.ctx, ev); err != nil { // return the pooled buffer on error paths too ev.Free() continue diff --git a/pkg/database/query-events-multiple-param-replaceable_test.go b/pkg/database/query-events-multiple-param-replaceable_test.go index 18adac3..0d14d30 100644 --- a/pkg/database/query-events-multiple-param-replaceable_test.go +++ b/pkg/database/query-events-multiple-param-replaceable_test.go @@ -43,7 +43,7 @@ func TestMultipleParameterizedReplaceableEvents(t *testing.T) { baseEvent.Sign(sign) // Save the base parameterized replaceable event - if _, _, err := db.SaveEvent(ctx, baseEvent); err != nil { + if err, _ := db.SaveEvent(ctx, baseEvent); err != nil { t.Fatalf("Failed to save base parameterized replaceable event: %v", err) } @@ -61,7 +61,7 @@ func TestMultipleParameterizedReplaceableEvents(t *testing.T) { newerEvent.Sign(sign) // Save the newer parameterized replaceable event - if _, _, err := db.SaveEvent(ctx, newerEvent); err != nil { + if err, _ := db.SaveEvent(ctx, newerEvent); err != nil { t.Fatalf( "Failed to save newer parameterized replaceable event: %v", err, ) @@ -81,7 +81,7 @@ func TestMultipleParameterizedReplaceableEvents(t *testing.T) { newestEvent.Sign(sign) // Save the newest parameterized replaceable event - if _, _, err := db.SaveEvent(ctx, newestEvent); err != nil { + if err, _ := db.SaveEvent(ctx, newestEvent); err != nil { t.Fatalf( "Failed to save newest parameterized replaceable event: %v", err, ) diff --git a/pkg/database/query-events-search_test.go b/pkg/database/query-events-search_test.go index d935858..8c9128c 100644 --- a/pkg/database/query-events-search_test.go +++ b/pkg/database/query-events-search_test.go @@ -1,194 +1,196 @@ package database import ( - "context" - "os" - "testing" - "time" + "context" + "os" + "testing" + "time" - "lol.mleku.dev/chk" - "next.orly.dev/pkg/crypto/p256k" - "next.orly.dev/pkg/encoders/event" - "next.orly.dev/pkg/encoders/filter" - "next.orly.dev/pkg/encoders/kind" - "next.orly.dev/pkg/encoders/tag" - "next.orly.dev/pkg/encoders/timestamp" + "lol.mleku.dev/chk" + "next.orly.dev/pkg/crypto/p256k" + "next.orly.dev/pkg/encoders/event" + "next.orly.dev/pkg/encoders/filter" + "next.orly.dev/pkg/encoders/kind" + "next.orly.dev/pkg/encoders/tag" + "next.orly.dev/pkg/encoders/timestamp" ) // helper to create a fresh DB func newTestDB(t *testing.T) (*D, context.Context, context.CancelFunc, string) { - t.Helper() - tempDir, err := os.MkdirTemp("", "search-db-*") - if err != nil { - t.Fatalf("Failed to create temp dir: %v", err) - } - ctx, cancel := context.WithCancel(context.Background()) - db, err := New(ctx, cancel, tempDir, "error") - if err != nil { - cancel() - os.RemoveAll(tempDir) - t.Fatalf("Failed to init DB: %v", err) - } - return db, ctx, cancel, tempDir + t.Helper() + tempDir, err := os.MkdirTemp("", "search-db-*") + if err != nil { + t.Fatalf("Failed to create temp dir: %v", err) + } + ctx, cancel := context.WithCancel(context.Background()) + db, err := New(ctx, cancel, tempDir, "error") + if err != nil { + cancel() + os.RemoveAll(tempDir) + t.Fatalf("Failed to init DB: %v", err) + } + return db, ctx, cancel, tempDir } // TestQueryEventsBySearchTerms creates a small set of events with content and tags, // saves them, then queries using filter.Search to ensure the word index works. func TestQueryEventsBySearchTerms(t *testing.T) { - db, ctx, cancel, tempDir := newTestDB(t) - defer func() { - // cancel context first to stop background routines cleanly - cancel() - db.Close() - os.RemoveAll(tempDir) - }() + db, ctx, cancel, tempDir := newTestDB(t) + defer func() { + // cancel context first to stop background routines cleanly + cancel() + db.Close() + os.RemoveAll(tempDir) + }() - // signer for all events - sign := new(p256k.Signer) - if err := sign.Generate(); chk.E(err) { - t.Fatalf("signer generate: %v", err) - } + // signer for all events + sign := new(p256k.Signer) + if err := sign.Generate(); chk.E(err) { + t.Fatalf("signer generate: %v", err) + } - now := timestamp.Now().V + now := timestamp.Now().V - // Events to cover tokenizer rules: - // - regular words - // - URLs ignored - // - 64-char hex ignored - // - nostr: URIs ignored - // - #[n] mentions ignored - // - tag fields included in search + // Events to cover tokenizer rules: + // - regular words + // - URLs ignored + // - 64-char hex ignored + // - nostr: URIs ignored + // - #[n] mentions ignored + // - tag fields included in search - // 1. Contains words: "alpha beta", plus URL and hex (ignored) - ev1 := event.New() - ev1.Kind = kind.TextNote.K - ev1.Pubkey = sign.Pub() - ev1.CreatedAt = now - 5 - ev1.Content = []byte("Alpha beta visit https://example.com deadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeef") - ev1.Tags = tag.NewS() - ev1.Sign(sign) - if _, _, err := db.SaveEvent(ctx, ev1); err != nil { - t.Fatalf("save ev1: %v", err) - } + // 1. Contains words: "alpha beta", plus URL and hex (ignored) + ev1 := event.New() + ev1.Kind = kind.TextNote.K + ev1.Pubkey = sign.Pub() + ev1.CreatedAt = now - 5 + ev1.Content = []byte("Alpha beta visit https://example.com deadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeef") + ev1.Tags = tag.NewS() + ev1.Sign(sign) + if err, _ := db.SaveEvent(ctx, ev1); err != nil { + t.Fatalf("save ev1: %v", err) + } - // 2. Contains overlap word "beta" and unique "gamma" and nostr: URI ignored - ev2 := event.New() - ev2.Kind = kind.TextNote.K - ev2.Pubkey = sign.Pub() - ev2.CreatedAt = now - 4 - ev2.Content = []byte("beta and GAMMA with nostr:nevent1qqqqq") - ev2.Tags = tag.NewS() - ev2.Sign(sign) - if _, _, err := db.SaveEvent(ctx, ev2); err != nil { - t.Fatalf("save ev2: %v", err) - } + // 2. Contains overlap word "beta" and unique "gamma" and nostr: URI ignored + ev2 := event.New() + ev2.Kind = kind.TextNote.K + ev2.Pubkey = sign.Pub() + ev2.CreatedAt = now - 4 + ev2.Content = []byte("beta and GAMMA with nostr:nevent1qqqqq") + ev2.Tags = tag.NewS() + ev2.Sign(sign) + if err, _ := db.SaveEvent(ctx, ev2); err != nil { + t.Fatalf("save ev2: %v", err) + } - // 3. Contains only a URL (should not create word tokens) and mention #[1] (ignored) - ev3 := event.New() - ev3.Kind = kind.TextNote.K - ev3.Pubkey = sign.Pub() - ev3.CreatedAt = now - 3 - ev3.Content = []byte("see www.example.org #[1]") - ev3.Tags = tag.NewS() - ev3.Sign(sign) - if _, _, err := db.SaveEvent(ctx, ev3); err != nil { - t.Fatalf("save ev3: %v", err) - } + // 3. Contains only a URL (should not create word tokens) and mention #[1] (ignored) + ev3 := event.New() + ev3.Kind = kind.TextNote.K + ev3.Pubkey = sign.Pub() + ev3.CreatedAt = now - 3 + ev3.Content = []byte("see www.example.org #[1]") + ev3.Tags = tag.NewS() + ev3.Sign(sign) + if err, _ := db.SaveEvent(ctx, ev3); err != nil { + t.Fatalf("save ev3: %v", err) + } - // 4. No content words, but tag value has searchable words: "delta epsilon" - ev4 := event.New() - ev4.Kind = kind.TextNote.K - ev4.Pubkey = sign.Pub() - ev4.CreatedAt = now - 2 - ev4.Content = []byte("") - ev4.Tags = tag.NewS() - *ev4.Tags = append(*ev4.Tags, tag.NewFromAny("t", "delta epsilon")) - ev4.Sign(sign) - if _, _, err := db.SaveEvent(ctx, ev4); err != nil { - t.Fatalf("save ev4: %v", err) - } + // 4. No content words, but tag value has searchable words: "delta epsilon" + ev4 := event.New() + ev4.Kind = kind.TextNote.K + ev4.Pubkey = sign.Pub() + ev4.CreatedAt = now - 2 + ev4.Content = []byte("") + ev4.Tags = tag.NewS() + *ev4.Tags = append(*ev4.Tags, tag.NewFromAny("t", "delta epsilon")) + ev4.Sign(sign) + if err, _ := db.SaveEvent(ctx, ev4); err != nil { + t.Fatalf("save ev4: %v", err) + } - // 5. Another event with both content and tag tokens for ordering checks - ev5 := event.New() - ev5.Kind = kind.TextNote.K - ev5.Pubkey = sign.Pub() - ev5.CreatedAt = now - 1 - ev5.Content = []byte("alpha DELTA mixed-case and link http://foo.bar") - ev5.Tags = tag.NewS() - *ev5.Tags = append(*ev5.Tags, tag.NewFromAny("t", "zeta")) - ev5.Sign(sign) - if _, _, err := db.SaveEvent(ctx, ev5); err != nil { - t.Fatalf("save ev5: %v", err) - } + // 5. Another event with both content and tag tokens for ordering checks + ev5 := event.New() + ev5.Kind = kind.TextNote.K + ev5.Pubkey = sign.Pub() + ev5.CreatedAt = now - 1 + ev5.Content = []byte("alpha DELTA mixed-case and link http://foo.bar") + ev5.Tags = tag.NewS() + *ev5.Tags = append(*ev5.Tags, tag.NewFromAny("t", "zeta")) + ev5.Sign(sign) + if err, _ := db.SaveEvent(ctx, ev5); err != nil { + t.Fatalf("save ev5: %v", err) + } - // Small sleep to ensure created_at ordering is the only factor - time.Sleep(5 * time.Millisecond) + // Small sleep to ensure created_at ordering is the only factor + time.Sleep(5 * time.Millisecond) - // Helper to run a search and return IDs - run := func(q string) ([]*event.E, error) { - f := &filter.F{Search: []byte(q)} - return db.QueryEvents(ctx, f) - } + // Helper to run a search and return IDs + run := func(q string) ([]*event.E, error) { + f := &filter.F{Search: []byte(q)} + return db.QueryEvents(ctx, f) + } - // Single-term search: alpha -> should match ev1 and ev5 ordered by created_at desc (ev5 newer) - if evs, err := run("alpha"); err != nil { - t.Fatalf("search alpha: %v", err) - } else { - if len(evs) != 2 { - t.Fatalf("alpha expected 2 results, got %d", len(evs)) - } - if !(evs[0].CreatedAt >= evs[1].CreatedAt) { - t.Fatalf("results not ordered by created_at desc") - } - } + // Single-term search: alpha -> should match ev1 and ev5 ordered by created_at desc (ev5 newer) + if evs, err := run("alpha"); err != nil { + t.Fatalf("search alpha: %v", err) + } else { + if len(evs) != 2 { + t.Fatalf("alpha expected 2 results, got %d", len(evs)) + } + if !(evs[0].CreatedAt >= evs[1].CreatedAt) { + t.Fatalf("results not ordered by created_at desc") + } + } - // Overlap term beta -> ev1 and ev2 - if evs, err := run("beta"); err != nil { - t.Fatalf("search beta: %v", err) - } else if len(evs) != 2 { - t.Fatalf("beta expected 2 results, got %d", len(evs)) - } + // Overlap term beta -> ev1 and ev2 + if evs, err := run("beta"); err != nil { + t.Fatalf("search beta: %v", err) + } else if len(evs) != 2 { + t.Fatalf("beta expected 2 results, got %d", len(evs)) + } - // Unique term gamma -> only ev2 - if evs, err := run("gamma"); err != nil { - t.Fatalf("search gamma: %v", err) - } else if len(evs) != 1 { - t.Fatalf("gamma expected 1 result, got %d", len(evs)) - } + // Unique term gamma -> only ev2 + if evs, err := run("gamma"); err != nil { + t.Fatalf("search gamma: %v", err) + } else if len(evs) != 1 { + t.Fatalf("gamma expected 1 result, got %d", len(evs)) + } - // URL terms should be ignored: example -> appears only as URL in ev1/ev3/ev5; tokenizer ignores URLs so expect 0 - if evs, err := run("example"); err != nil { - t.Fatalf("search example: %v", err) - } else if len(evs) != 0 { - t.Fatalf("example expected 0 results (URL tokens ignored), got %d", len(evs)) - } + // URL terms should be ignored: example -> appears only as URL in ev1/ev3/ev5; tokenizer ignores URLs so expect 0 + if evs, err := run("example"); err != nil { + t.Fatalf("search example: %v", err) + } else if len(evs) != 0 { + t.Fatalf( + "example expected 0 results (URL tokens ignored), got %d", len(evs), + ) + } - // Tag words searchable: delta should match ev4 and ev5 (delta in tag for ev4, in content for ev5) - if evs, err := run("delta"); err != nil { - t.Fatalf("search delta: %v", err) - } else if len(evs) != 2 { - t.Fatalf("delta expected 2 results, got %d", len(evs)) - } + // Tag words searchable: delta should match ev4 and ev5 (delta in tag for ev4, in content for ev5) + if evs, err := run("delta"); err != nil { + t.Fatalf("search delta: %v", err) + } else if len(evs) != 2 { + t.Fatalf("delta expected 2 results, got %d", len(evs)) + } - // Very short token ignored: single-letter should yield 0 - if evs, err := run("a"); err != nil { - t.Fatalf("search short token: %v", err) - } else if len(evs) != 0 { - t.Fatalf("single-letter expected 0 results, got %d", len(evs)) - } + // Very short token ignored: single-letter should yield 0 + if evs, err := run("a"); err != nil { + t.Fatalf("search short token: %v", err) + } else if len(evs) != 0 { + t.Fatalf("single-letter expected 0 results, got %d", len(evs)) + } - // 64-char hex should be ignored - hex64 := "0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef" - if evs, err := run(hex64); err != nil { - t.Fatalf("search hex64: %v", err) - } else if len(evs) != 0 { - t.Fatalf("hex64 expected 0 results, got %d", len(evs)) - } + // 64-char hex should be ignored + hex64 := "0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef" + if evs, err := run(hex64); err != nil { + t.Fatalf("search hex64: %v", err) + } else if len(evs) != 0 { + t.Fatalf("hex64 expected 0 results, got %d", len(evs)) + } - // nostr: scheme ignored - if evs, err := run("nostr:nevent1qqqqq"); err != nil { - t.Fatalf("search nostr: %v", err) - } else if len(evs) != 0 { - t.Fatalf("nostr: expected 0 results, got %d", len(evs)) - } + // nostr: scheme ignored + if evs, err := run("nostr:nevent1qqqqq"); err != nil { + t.Fatalf("search nostr: %v", err) + } else if len(evs) != 0 { + t.Fatalf("nostr: expected 0 results, got %d", len(evs)) + } } diff --git a/pkg/database/query-events_test.go b/pkg/database/query-events_test.go index 0a721a4..4efffe2 100644 --- a/pkg/database/query-events_test.go +++ b/pkg/database/query-events_test.go @@ -64,7 +64,7 @@ func setupTestDB(t *testing.T) ( events = append(events, ev) // Save the event to the database - if _, _, err = db.SaveEvent(ctx, ev); err != nil { + if err, _ = db.SaveEvent(ctx, ev); err != nil { t.Fatalf("Failed to save event #%d: %v", eventCount+1, err) } @@ -204,7 +204,7 @@ func TestReplaceableEventsAndDeletion(t *testing.T) { replaceableEvent.Tags = tag.NewS() replaceableEvent.Sign(sign) // Save the replaceable event - if _, _, err := db.SaveEvent(ctx, replaceableEvent); err != nil { + if err, _ := db.SaveEvent(ctx, replaceableEvent); err != nil { t.Errorf("Failed to save replaceable event: %v", err) } @@ -217,7 +217,7 @@ func TestReplaceableEventsAndDeletion(t *testing.T) { newerEvent.Tags = tag.NewS() newerEvent.Sign(sign) // Save the newer event - if _, _, err := db.SaveEvent(ctx, newerEvent); err != nil { + if err, _ := db.SaveEvent(ctx, newerEvent); err != nil { t.Errorf("Failed to save newer event: %v", err) } @@ -286,7 +286,7 @@ func TestReplaceableEventsAndDeletion(t *testing.T) { ) // Save the deletion event - if _, _, err = db.SaveEvent(ctx, deletionEvent); err != nil { + if err, _ = db.SaveEvent(ctx, deletionEvent); err != nil { t.Fatalf("Failed to save deletion event: %v", err) } @@ -371,7 +371,7 @@ func TestParameterizedReplaceableEventsAndDeletion(t *testing.T) { paramEvent.Sign(sign) // Save the parameterized replaceable event - if _, _, err := db.SaveEvent(ctx, paramEvent); err != nil { + if err, _ := db.SaveEvent(ctx, paramEvent); err != nil { t.Fatalf("Failed to save parameterized replaceable event: %v", err) } @@ -397,7 +397,7 @@ func TestParameterizedReplaceableEventsAndDeletion(t *testing.T) { paramDeletionEvent.Sign(sign) // Save the parameterized deletion event - if _, _, err := db.SaveEvent(ctx, paramDeletionEvent); err != nil { + if err, _ := db.SaveEvent(ctx, paramDeletionEvent); err != nil { t.Fatalf("Failed to save parameterized deletion event: %v", err) } @@ -430,7 +430,7 @@ func TestParameterizedReplaceableEventsAndDeletion(t *testing.T) { paramDeletionEvent2.Sign(sign) // Save the parameterized deletion event with e-tag - if _, _, err := db.SaveEvent(ctx, paramDeletionEvent2); err != nil { + if err, _ := db.SaveEvent(ctx, paramDeletionEvent2); err != nil { t.Fatalf( "Failed to save parameterized deletion event with e-tag: %v", err, ) diff --git a/pkg/database/query-for-authors-tags_test.go b/pkg/database/query-for-authors-tags_test.go index c27f3f2..ee2f3a3 100644 --- a/pkg/database/query-for-authors-tags_test.go +++ b/pkg/database/query-for-authors-tags_test.go @@ -58,7 +58,7 @@ func TestQueryForAuthorsTags(t *testing.T) { events = append(events, ev) // Save the event to the database - if _, _, err = db.SaveEvent(ctx, ev); err != nil { + if err, _ = db.SaveEvent(ctx, ev); err != nil { t.Fatalf("Failed to save event #%d: %v", eventCount+1, err) } diff --git a/pkg/database/query-for-ids_test.go b/pkg/database/query-for-ids_test.go index fd89c00..3405474 100644 --- a/pkg/database/query-for-ids_test.go +++ b/pkg/database/query-for-ids_test.go @@ -60,7 +60,7 @@ func TestQueryForIds(t *testing.T) { events = append(events, ev) // Save the event to the database - if _, _, err = db.SaveEvent(ctx, ev); err != nil { + if err, _ = db.SaveEvent(ctx, ev); err != nil { t.Fatalf("Failed to save event #%d: %v", eventCount+1, err) } diff --git a/pkg/database/query-for-kinds-authors-tags_test.go b/pkg/database/query-for-kinds-authors-tags_test.go index 0d2fc6e..d33e382 100644 --- a/pkg/database/query-for-kinds-authors-tags_test.go +++ b/pkg/database/query-for-kinds-authors-tags_test.go @@ -59,7 +59,7 @@ func TestQueryForKindsAuthorsTags(t *testing.T) { events = append(events, ev) // Save the event to the database - if _, _, err = db.SaveEvent(ctx, ev); err != nil { + if err, _ = db.SaveEvent(ctx, ev); err != nil { t.Fatalf("Failed to save event #%d: %v", eventCount+1, err) } diff --git a/pkg/database/query-for-kinds-authors_test.go b/pkg/database/query-for-kinds-authors_test.go index 2eb2052..270ac4d 100644 --- a/pkg/database/query-for-kinds-authors_test.go +++ b/pkg/database/query-for-kinds-authors_test.go @@ -59,7 +59,7 @@ func TestQueryForKindsAuthors(t *testing.T) { events = append(events, ev) // Save the event to the database - if _, _, err = db.SaveEvent(ctx, ev); err != nil { + if err, _ = db.SaveEvent(ctx, ev); err != nil { t.Fatalf("Failed to save event #%d: %v", eventCount+1, err) } diff --git a/pkg/database/query-for-kinds-tags_test.go b/pkg/database/query-for-kinds-tags_test.go index e70e722..aa7350b 100644 --- a/pkg/database/query-for-kinds-tags_test.go +++ b/pkg/database/query-for-kinds-tags_test.go @@ -59,7 +59,7 @@ func TestQueryForKindsTags(t *testing.T) { events = append(events, ev) // Save the event to the database - if _, _, err = db.SaveEvent(ctx, ev); err != nil { + if err, _ = db.SaveEvent(ctx, ev); err != nil { t.Fatalf("Failed to save event #%d: %v", eventCount+1, err) } diff --git a/pkg/database/query-for-kinds_test.go b/pkg/database/query-for-kinds_test.go index a5acad2..39ea767 100644 --- a/pkg/database/query-for-kinds_test.go +++ b/pkg/database/query-for-kinds_test.go @@ -58,7 +58,7 @@ func TestQueryForKinds(t *testing.T) { events = append(events, ev) // Save the event to the database - if _, _, err = db.SaveEvent(ctx, ev); err != nil { + if err, _ = db.SaveEvent(ctx, ev); err != nil { t.Fatalf("Failed to save event #%d: %v", eventCount+1, err) } diff --git a/pkg/database/query-for-serials_test.go b/pkg/database/query-for-serials_test.go index b568f61..e09725e 100644 --- a/pkg/database/query-for-serials_test.go +++ b/pkg/database/query-for-serials_test.go @@ -61,7 +61,7 @@ func TestQueryForSerials(t *testing.T) { events = append(events, ev) // Save the event to the database - if _, _, err = db.SaveEvent(ctx, ev); err != nil { + if err, _ = db.SaveEvent(ctx, ev); err != nil { t.Fatalf("Failed to save event #%d: %v", eventCount+1, err) } diff --git a/pkg/database/query-for-tags_test.go b/pkg/database/query-for-tags_test.go index 3f84ae9..cf6a65e 100644 --- a/pkg/database/query-for-tags_test.go +++ b/pkg/database/query-for-tags_test.go @@ -58,7 +58,7 @@ func TestQueryForTags(t *testing.T) { events = append(events, ev) // Save the event to the database - if _, _, err = db.SaveEvent(ctx, ev); err != nil { + if err, _ = db.SaveEvent(ctx, ev); err != nil { t.Fatalf("Failed to save event #%d: %v", eventCount+1, err) } diff --git a/pkg/database/save-event.go b/pkg/database/save-event.go index 96d3510..0fa8129 100644 --- a/pkg/database/save-event.go +++ b/pkg/database/save-event.go @@ -9,7 +9,6 @@ import ( "github.com/dgraph-io/badger/v4" "lol.mleku.dev/chk" - "lol.mleku.dev/log" "next.orly.dev/pkg/database/indexes" "next.orly.dev/pkg/database/indexes/types" "next.orly.dev/pkg/encoders/event" @@ -103,7 +102,9 @@ func (d *D) WouldReplaceEvent(ev *event.E) (bool, types.Uint40s, error) { } // SaveEvent saves an event to the database, generating all the necessary indexes. -func (d *D) SaveEvent(c context.Context, ev *event.E) (kc, vc int, err error) { +func (d *D) SaveEvent(c context.Context, ev *event.E) ( + err error, replaced bool, +) { if ev == nil { err = errors.New("nil event") return @@ -136,10 +137,9 @@ func (d *D) SaveEvent(c context.Context, ev *event.E) (kc, vc int, err error) { } // check for replacement (separated check vs deletion) if kind.IsReplaceable(ev.Kind) || kind.IsParameterizedReplaceable(ev.Kind) { - var wouldReplace bool var sers types.Uint40s var werr error - if wouldReplace, sers, werr = d.WouldReplaceEvent(ev); werr != nil { + if replaced, sers, werr = d.WouldReplaceEvent(ev); werr != nil { if errors.Is(werr, ErrOlderThanExisting) { if kind.IsReplaceable(ev.Kind) { err = errors.New("blocked: event is older than existing replaceable event") @@ -156,7 +156,7 @@ func (d *D) SaveEvent(c context.Context, ev *event.E) (kc, vc int, err error) { // any other error return } - if wouldReplace { + if replaced { for _, s := range sers { var oldEv *event.E if oldEv, err = d.FetchEventBySerial(s); chk.E(err) { @@ -178,10 +178,6 @@ func (d *D) SaveEvent(c context.Context, ev *event.E) (kc, vc int, err error) { if idxs, err = GetIndexesForEvent(ev, serial); chk.E(err) { return } - // log.I.S(idxs) - for _, k := range idxs { - kc += len(k) - } // Start a transaction to save the event and all its indexes err = d.Update( func(txn *badger.Txn) (err error) { @@ -209,23 +205,11 @@ func (d *D) SaveEvent(c context.Context, ev *event.E) (kc, vc int, err error) { v := new(bytes.Buffer) ev.MarshalBinary(v) kb, vb := k.Bytes(), v.Bytes() - kc += len(kb) - vc += len(vb) - // log.I.S(kb, vb) if err = txn.Set(kb, vb); chk.E(err) { return } return }, ) - log.T.F( - "total data written: %d bytes keys %d bytes values for event ID %s", kc, - vc, hex.Enc(ev.ID), - ) - // log.T.C( - // func() string { - // return fmt.Sprintf("event:\n%s\n", ev.Serialize()) - // }, - // ) return } diff --git a/pkg/database/save-event_test.go b/pkg/database/save-event_test.go index 8b496ac..f00b5a2 100644 --- a/pkg/database/save-event_test.go +++ b/pkg/database/save-event_test.go @@ -65,7 +65,7 @@ func TestSaveEvents(t *testing.T) { // Save the event to the database var k, v int - if k, v, err = db.SaveEvent(ctx, ev); err != nil { + if err, _ = db.SaveEvent(ctx, ev); err != nil { t.Fatalf("Failed to save event #%d: %v", eventCount+1, err) } kc += k @@ -125,7 +125,7 @@ func TestDeletionEventWithETagRejection(t *testing.T) { regularEvent.Sign(sign) // Save the regular event - if _, _, err := db.SaveEvent(ctx, regularEvent); err != nil { + if err, _ := db.SaveEvent(ctx, regularEvent); err != nil { t.Fatalf("Failed to save regular event: %v", err) } @@ -151,7 +151,7 @@ func TestDeletionEventWithETagRejection(t *testing.T) { err = errorf.E("deletion events referencing other events with 'e' tag are not allowed") } else { // Try to save the deletion event - _, _, err = db.SaveEvent(ctx, deletionEvent) + err, _ = db.SaveEvent(ctx, deletionEvent) } if err == nil { @@ -204,12 +204,12 @@ func TestSaveExistingEvent(t *testing.T) { ev.Sign(sign) // Save the event for the first time - if _, _, err := db.SaveEvent(ctx, ev); err != nil { + if err, _ := db.SaveEvent(ctx, ev); err != nil { t.Fatalf("Failed to save event: %v", err) } // Try to save the same event again, it should be rejected - _, _, err = db.SaveEvent(ctx, ev) + err, _ = db.SaveEvent(ctx, ev) if err == nil { t.Fatal("Expected error when saving an existing event, but got nil") } diff --git a/pkg/interfaces/store/store_interface.go b/pkg/interfaces/store/store_interface.go index a04eae6..46744a8 100644 --- a/pkg/interfaces/store/store_interface.go +++ b/pkg/interfaces/store/store_interface.go @@ -84,7 +84,7 @@ 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) (kc, vc int, err error) + SaveEvent(c context.Context, ev *event.E) (err error, replaced bool) } type Importer interface { diff --git a/pkg/spider/spider.go b/pkg/spider/spider.go index 8e75591..649e530 100644 --- a/pkg/spider/spider.go +++ b/pkg/spider/spider.go @@ -293,7 +293,10 @@ func (s *Spider) calculateOptimalChunkSize() int { chunkSize = 10 } - log.D.F("Spider: calculated optimal chunk size: %d pubkeys (max would be %d)", chunkSize, maxPubkeys) + log.D.F( + "Spider: calculated optimal chunk size: %d pubkeys (max would be %d)", + chunkSize, maxPubkeys, + ) return chunkSize } @@ -301,7 +304,10 @@ func (s *Spider) calculateOptimalChunkSize() int { func (s *Spider) queryRelayForEvents( relayURL string, followedPubkeys [][]byte, startTime, endTime time.Time, ) (int, error) { - log.T.F("Spider sync: querying relay %s with %d pubkeys", relayURL, len(followedPubkeys)) + log.T.F( + "Spider sync: querying relay %s with %d pubkeys", relayURL, + len(followedPubkeys), + ) // Connect to the relay with a timeout context ctx, cancel := context.WithTimeout(s.ctx, 30*time.Second) @@ -324,8 +330,10 @@ func (s *Spider) queryRelayForEvents( } chunk := followedPubkeys[i:end] - log.T.F("Spider sync: processing chunk %d-%d (%d pubkeys) for relay %s", - i, end-1, len(chunk), relayURL) + log.T.F( + "Spider sync: processing chunk %d-%d (%d pubkeys) for relay %s", + i, end-1, len(chunk), relayURL, + ) // Create filter for this chunk of pubkeys f := &filter.F{ @@ -338,8 +346,10 @@ func (s *Spider) queryRelayForEvents( // Subscribe to get events for this chunk sub, err := client.Subscribe(ctx, filter.NewS(f)) if err != nil { - log.E.F("Spider sync: failed to subscribe to chunk %d-%d for relay %s: %v", - i, end-1, relayURL, err) + log.E.F( + "Spider sync: failed to subscribe to chunk %d-%d for relay %s: %v", + i, end-1, relayURL, err, + ) continue } @@ -385,7 +395,7 @@ func (s *Spider) queryRelayForEvents( } // Save the event to the database - if _, _, err := s.db.SaveEvent(s.ctx, ev); err != nil { + if err, _ := s.db.SaveEvent(s.ctx, ev); err != nil { if !strings.HasPrefix(err.Error(), "blocked:") { log.T.F( "Spider sync: error saving event from relay %s: %v", @@ -410,12 +420,16 @@ func (s *Spider) queryRelayForEvents( sub.Unsub() totalEventsSaved += chunkEventsSaved - log.T.F("Spider sync: completed chunk %d-%d for relay %s, saved %d events", - i, end-1, relayURL, chunkEventsSaved) + log.T.F( + "Spider sync: completed chunk %d-%d for relay %s, saved %d events", + i, end-1, relayURL, chunkEventsSaved, + ) } - log.T.F("Spider sync: completed all chunks for relay %s, total saved %d events", - relayURL, totalEventsSaved) + log.T.F( + "Spider sync: completed all chunks for relay %s, total saved %d events", + relayURL, totalEventsSaved, + ) return totalEventsSaved, nil } diff --git a/pkg/version/version b/pkg/version/version index 1af39b3..045d738 100644 --- a/pkg/version/version +++ b/pkg/version/version @@ -1 +1 @@ -v0.12.3 \ No newline at end of file +v0.14.0 \ No newline at end of file