@ -3,6 +3,7 @@ package nostr
import (
import (
"context"
"context"
"fmt"
"fmt"
"log"
"time"
"time"
"github.com/nbd-wtf/go-nostr"
"github.com/nbd-wtf/go-nostr"
@ -22,38 +23,71 @@ func NewFeedService(client *Client, feedKind int) *FeedService {
}
}
}
}
// FetchFeedItems fetches recent feed events from a specific relay
// FetchFeedItems fetches recent feed events from the configured feed relay only, with retries
func ( fs * FeedService ) FetchFeedItems ( ctx context . Context , relay string , maxEvents int ) ( [ ] FeedItem , error ) {
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 {
filter := nostr . Filter {
Kinds : [ ] int { fs . feedKind } ,
Kinds : [ ] int { fs . feedKind } ,
Limit : maxEvents ,
Limit : maxEvents ,
}
}
logFilter ( filter , fmt . Sprintf ( "feed (kind %d)" , fs . feedKind ) )
logFilter ( filter , fmt . Sprintf ( "feed (kind %d)" , fs . feedKind ) )
// Connect to the specific feed relay (not the default client relays)
const maxRetries = 3
relayConn , err := fs . client . ConnectToRelay ( ctx , relay )
var lastErr error
if err != nil {
return nil , fmt . Errorf ( "failed to connect to feed relay %s: %w" , relay , err )
}
defer relayConn . Close ( )
events , err := relayConn . QuerySync ( ctx , filter )
// Retry up to 3 times for the configured feed relay only
if err != nil {
for attempt := 1 ; attempt <= maxRetries ; attempt ++ {
return nil , fmt . Errorf ( "failed to fetch feed events from %s: %w" , relay , err )
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 )
items := make ( [ ] FeedItem , 0 , len ( events ) )
// Connect to the relay
for _ , event := range events {
relayConn , err := fs . client . ConnectToRelay ( attemptCtx , feedRelay )
item := FeedItem {
if err != nil {
Author : event . PubKey ,
log . Printf ( "Failed to connect to feed relay %s (attempt %d/%d): %v" , feedRelay , attempt , maxRetries , err )
Content : event . Content ,
lastErr = err
Time : time . Unix ( int64 ( event . CreatedAt ) , 0 ) ,
cancel ( )
Link : fmt . Sprintf ( "https://alexandria.gitcitadel.eu/events?id=nevent1%s" , event . ID ) ,
continue // Try next attempt
}
}
items = append ( items , item )
// Try to fetch events
events , err := relayConn . QuerySync ( attemptCtx , filter )
relayConn . Close ( )
cancel ( )
if err != nil {
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 {
Author : event . PubKey ,
Content : event . Content ,
Time : time . Unix ( int64 ( event . CreatedAt ) , 0 ) ,
Link : fmt . Sprintf ( "https://alexandria.gitcitadel.eu/events?id=nevent1%s" , event . ID ) ,
}
items = append ( items , item )
}
log . Printf ( "Successfully fetched %d feed items from %s (attempt %d/%d)" , len ( items ) , feedRelay , attempt , maxRetries )
return items , nil
}
}
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
// FeedItem represents a feed item