feat(relay): dual-write transactions to sos.audius.co#736
Conversation
Fires a best-effort background write to https://sos.audius.co on every relay call, regardless of whether the main mainnet write succeeds. Hardcoded as a temporary fix. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- mainnet writes fire in a background goroutine (uses context.Background since request context cancels on response) - sos write is synchronous and returns the tx hash for the receipt - both writes share a single SendTransactionRequest Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This reverts commit 766444b.
There was a problem hiding this comment.
Pull request overview
This PR updates the relay transaction path to attempt a dual-write to a second OpenAudio endpoint (https://sos.audius.co) alongside the existing mainnet submission.
Changes:
- Adds a hardcoded SOS endpoint and constructs a separate OpenAudio SDK client for it.
- Refactors
handleRelayto send mainnet transactions in a goroutine and send SOS synchronously.
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| res, err := sosClient.Core.SendTransaction(ctx, connect.NewRequest(req)) | ||
| if err != nil { | ||
| sosLogger.Warn("sos dual-write failed", zap.Error(err)) | ||
| return nil, err | ||
| } |
There was a problem hiding this comment.
This makes the SOS send the synchronous/authoritative call: failures from sosClient.Core.SendTransaction are returned to the API caller, and the receipt is built from the SOS transaction hash. The PR description says SOS should be best-effort/background in addition to the existing mainnet write; to keep existing semantics, the mainnet send should remain the one that determines the response, and the SOS dual-write should run asynchronously and not fail the request (log errors only).
| go func() { | ||
| allClients := app.openAudioPool.GetAll() | ||
| for i, clientInfo := range allClients { | ||
| endpointLogger := logger.With(zap.String("openaudio_endpoint", clientInfo.Endpoint), zap.Int("attempt", i+1)) | ||
| res, err := clientInfo.Client.Core.SendTransaction(context.Background(), connect.NewRequest(req)) |
There was a problem hiding this comment.
The mainnet send is launched as a goroutine using context.Background() with no timeout. Under load, this can create unbounded concurrent goroutines and potentially hang indefinitely if an endpoint stalls (since it won't be canceled when the request ctx is canceled). Consider using a bounded context with timeout (e.g., context.WithTimeout) and/or a background worker/queue to control concurrency.
Reverts #736 DO NOT MERGE until mainnet stable
Fires the mainnet as best effort, always write to sos
Hardcoded as a temporary fix.
🤖 Generated with Claude Code