diff --git a/cmd/asterism/main.go b/cmd/asterism/main.go index 597391b..674ba8f 100644 --- a/cmd/asterism/main.go +++ b/cmd/asterism/main.go @@ -5,12 +5,10 @@ import ( "flag" "fmt" "log/slog" - "net/http" "strings" "github.com/bluesky-social/indigo/atproto/identity" "github.com/bluesky-social/indigo/xrpc" - "github.com/gorilla/websocket" "github.com/alyraffauf/asterism/internal/api" "github.com/alyraffauf/asterism/internal/backfill" @@ -44,12 +42,6 @@ func main() { ctx := context.Background() logger := slog.Default() - conn, _, err := websocket.DefaultDialer.Dial(relayURL, http.Header{}) - if err != nil { - panic(err) - } - defer conn.Close() - linkStore, err := store.Open("asterism.db") if err != nil { panic(err) @@ -89,7 +81,8 @@ func main() { Backfill: bf, } - if err := consumer.Run(ctx, conn, logger); err != nil { + if err := consumer.Run(ctx, relayURL, logger); err != nil { panic(err) } + } diff --git a/internal/firehose/stream.go b/internal/firehose/stream.go index 21efa9a..60f1a75 100644 --- a/internal/firehose/stream.go +++ b/internal/firehose/stream.go @@ -3,6 +3,8 @@ package firehose import ( "context" "log/slog" + "net/http" + "time" "github.com/bluesky-social/indigo/api/atproto" "github.com/bluesky-social/indigo/events" @@ -10,7 +12,36 @@ import ( "github.com/gorilla/websocket" ) -func (c *Consumer) Run(ctx context.Context, conn *websocket.Conn, logger *slog.Logger) error { +const ( + minBackoff = 1 * time.Second + maxBackoff = 30 * time.Second +) + +func (c *Consumer) Run(ctx context.Context, relayURL string, logger *slog.Logger) error { + backoff := minBackoff + + for { + conn, _, err := websocket.DefaultDialer.DialContext(ctx, relayURL, http.Header{}) + if err != nil { + logger.Warn("dial failed", "err", err, "retry in", backoff) + } else { + backoff = minBackoff + c.stream(ctx, conn, logger) + conn.Close() + } + + select { + case <-time.After(backoff): + case <-ctx.Done(): + return ctx.Err() + } + + backoff = min(backoff*2, maxBackoff) + } + +} + +func (c *Consumer) stream(ctx context.Context, conn *websocket.Conn, logger *slog.Logger) { callbacks := &events.RepoStreamCallbacks{ RepoCommit: func(event *atproto.SyncSubscribeRepos_Commit) error { return c.HandleCommit(ctx, event) @@ -19,5 +50,7 @@ func (c *Consumer) Run(ctx context.Context, conn *websocket.Conn, logger *slog.L scheduler := sequential.NewScheduler("asterism", callbacks.EventHandler) - return events.HandleRepoStream(ctx, conn, scheduler, logger) + if err := events.HandleRepoStream(ctx, conn, scheduler, logger); err != nil { + logger.Warn("stream ended", "err", err) + } }