@ -3,6 +3,7 @@ package nostr
@@ -3,6 +3,7 @@ package nostr
import (
"context"
"fmt"
"log"
"time"
"github.com/nbd-wtf/go-nostr"
@ -22,26 +23,54 @@ func NewFeedService(client *Client, feedKind int) *FeedService {
@@ -22,26 +23,54 @@ func NewFeedService(client *Client, feedKind int) *FeedService {
}
}
// FetchFeedItems fetches recent feed events from a specific relay
func ( fs * FeedService ) FetchFeedItems ( ctx context . Context , relay string , maxEvents int ) ( [ ] FeedItem , error ) {
// FetchFeedItems fetches recent feed events from the configured feed relay only, with retries
func ( fs * FeedService ) FetchFeedItems ( ctx context . Context , feedRelay string , maxEvents int ) ( [ ] FeedItem , error ) {
if feedRelay == "" {
return nil , fmt . Errorf ( "feed relay not configured" )
}
filter := nostr . Filter {
Kinds : [ ] int { fs . feedKind } ,
Limit : maxEvents ,
}
logFilter ( filter , fmt . Sprintf ( "feed (kind %d)" , fs . feedKind ) )
// Connect to the specific feed relay (not the default client relays)
relayConn , err := fs . client . ConnectToRelay ( ctx , relay )
const maxRetries = 3
var lastErr error
// Retry up to 3 times for the configured feed relay only
for attempt := 1 ; attempt <= maxRetries ; attempt ++ {
if attempt > 1 {
log . Printf ( "Retrying feed relay %s (attempt %d/%d)" , feedRelay , attempt , maxRetries )
// Wait a bit before retrying (exponential backoff: 1s, 2s)
waitTime := time . Duration ( attempt - 1 ) * time . Second
time . Sleep ( waitTime )
}
// Create a context with timeout for this attempt
attemptCtx , cancel := context . WithTimeout ( ctx , 10 * time . Second )
// Connect to the relay
relayConn , err := fs . client . ConnectToRelay ( attemptCtx , feedRelay )
if err != nil {
return nil , fmt . Errorf ( "failed to connect to feed relay %s: %w" , relay , err )
log . Printf ( "Failed to connect to feed relay %s (attempt %d/%d): %v" , feedRelay , attempt , maxRetries , err )
lastErr = err
cancel ( )
continue // Try next attempt
}
defer relayConn . Close ( )
events , err := relayConn . QuerySync ( ctx , filter )
// Try to fetch events
events , err := relayConn . QuerySync ( attemptCtx , filter )
relayConn . Close ( )
cancel ( )
if err != nil {
return nil , fmt . Errorf ( "failed to fetch feed events from %s: %w" , relay , err )
log . Printf ( "Failed to fetch feed events from %s (attempt %d/%d): %v" , feedRelay , attempt , maxRetries , err )
lastErr = err
continue // Try next attempt
}
// Success! Convert events to feed items
items := make ( [ ] FeedItem , 0 , len ( events ) )
for _ , event := range events {
item := FeedItem {
@ -53,9 +82,14 @@ func (fs *FeedService) FetchFeedItems(ctx context.Context, relay string, maxEven
@@ -53,9 +82,14 @@ func (fs *FeedService) FetchFeedItems(ctx context.Context, relay string, maxEven
items = append ( items , item )
}
log . Printf ( "Successfully fetched %d feed items from %s (attempt %d/%d)" , len ( items ) , feedRelay , attempt , maxRetries )
return items , nil
}
// All retries failed
return nil , fmt . Errorf ( "failed to fetch feed from %s after %d retries (last error: %w)" , feedRelay , maxRetries , lastErr )
}
// FeedItem represents a feed item
type FeedItem struct {
Author string