From e79f9ad89556000521b43ce5ff4eb59dd00768b0 Mon Sep 17 00:00:00 2001 From: bndw Date: Sat, 7 Feb 2026 21:22:51 -0800 Subject: refactor: race-safe Subscribe/Fetch API with channel-based Publish - Add mutex-guarded send/stop on Subscription to prevent send-on-closed-channel panics and data races - Split Subscribe (streams after EOSE) and Fetch (closes on EOSE) per NIP-01 - Rewrite Publish to use channel-based OK dispatch instead of calling Receive directly, which raced with the auto-started Listen goroutine - Clean up all subscriptions when Listen exits so range loops terminate - Update tests and examples for new API --- example_test.go | 35 ++++++++++------------------------- 1 file changed, 10 insertions(+), 25 deletions(-) (limited to 'example_test.go') diff --git a/example_test.go b/example_test.go index 90dae0f..6d10ced 100644 --- a/example_test.go +++ b/example_test.go @@ -53,8 +53,7 @@ func Example_basic() { // ExampleRelay demonstrates connecting to a relay (requires network). // This is a documentation example - run with: go test -v -run ExampleRelay func ExampleRelay() { - ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second) - defer cancel() + ctx := context.Background() // Connect to a public relay relay, err := nostr.Connect(ctx, "wss://relay.damus.io") @@ -66,35 +65,21 @@ func ExampleRelay() { fmt.Println("Connected to relay!") - // Subscribe to recent text notes + ctx, cancel := context.WithTimeout(ctx, 10*time.Second) + defer cancel() + + // Fetch recent text notes (closes on EOSE) since := time.Now().Add(-1 * time.Hour).Unix() - sub, err := relay.Subscribe(ctx, "my-sub", nostr.Filter{ + sub := relay.Fetch(ctx, nostr.Filter{ Kinds: []int{nostr.KindTextNote}, Since: &since, Limit: 5, }) - if err != nil { - fmt.Printf("Failed to subscribe: %v\n", err) - return - } - - // Listen for events in the background - go relay.Listen(ctx) - // Collect events until EOSE eventCount := 0 - for { - select { - case event := <-sub.Events: - eventCount++ - fmt.Printf("Received event from %s...\n", event.PubKey[:8]) - case <-sub.EOSE: - fmt.Printf("Received %d events before EOSE\n", eventCount) - sub.Close(ctx) - return - case <-ctx.Done(): - fmt.Println("Timeout") - return - } + for event := range sub.Events { + eventCount++ + fmt.Printf("Received event from %s...\n", event.PubKey[:8]) } + fmt.Printf("Received %d events\n", eventCount) } -- cgit v1.2.3