Skip to content

Commit 19756a5

Browse files
authored
fix: gofmt stellar watcher (#81)
1 parent 9117bde commit 19756a5

2 files changed

Lines changed: 42 additions & 9 deletions

File tree

node/pkg/watchers/stellar/watcher.go

Lines changed: 38 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -62,7 +62,7 @@ type WatcherConfig struct {
6262
PollInterval time.Duration
6363
ReadTimeout time.Duration
6464
StartLedger uint64
65-
MaxPerPoll int
65+
MaxPerPoll int
6666
}
6767

6868
func (wc *WatcherConfig) Create(
@@ -173,11 +173,8 @@ func (w *watcher) Run(ctx context.Context) error {
173173
w.logger = logger
174174

175175
if w.nextLedger == 0 {
176-
seq, err := w.getLatestLedger(ctx)
176+
seq, err := w.getInitialLedger(ctx, logger)
177177
if err != nil {
178-
stellarConnectionErrors.WithLabelValues(w.networkName, "initial_ledger").Inc()
179-
p2p.DefaultRegistry.AddErrorCount(w.chainID, 1)
180-
logger.Error("failed to get latest ledger", zap.Error(err))
181178
return err
182179
}
183180
w.nextLedger = seq
@@ -214,6 +211,42 @@ func (w *watcher) Run(ctx context.Context) error {
214211
}
215212
}
216213

214+
// getInitialLedger fetches the starting ledger, retrying with capped exponential
215+
// backoff. A transient RPC outage at startup (e.g. the Soroban RPC not yet
216+
// reachable when the guardian boots) must not kill the watcher, mirroring the
217+
// resilience of the poll loop. Returns an error only when the context is cancelled.
218+
func (w *watcher) getInitialLedger(ctx context.Context, logger *zap.Logger) (uint64, error) {
219+
backoff := w.pollInterval
220+
if backoff <= 0 {
221+
backoff = 700 * time.Millisecond
222+
}
223+
const maxBackoff = 60 * time.Second
224+
225+
for {
226+
seq, err := w.getLatestLedger(ctx)
227+
if err == nil {
228+
return seq, nil
229+
}
230+
231+
stellarConnectionErrors.WithLabelValues(w.networkName, "initial_ledger").Inc()
232+
p2p.DefaultRegistry.AddErrorCount(w.chainID, 1)
233+
logger.Warn("failed to get latest ledger, retrying", zap.Error(err), zap.Duration("backoff", backoff))
234+
235+
select {
236+
case <-ctx.Done():
237+
return 0, ctx.Err()
238+
case <-time.After(backoff):
239+
}
240+
241+
if backoff < maxBackoff {
242+
backoff *= 2
243+
if backoff > maxBackoff {
244+
backoff = maxBackoff
245+
}
246+
}
247+
}
248+
}
249+
217250
// runReobservationHandler handles incoming reobservation requests. Returns an error only on fatal failure.
218251
func (w *watcher) runReobservationHandler(ctx context.Context) error {
219252
logger := w.logger

node/pkg/watchers/stellar/watcher_test.go

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -239,8 +239,8 @@ func (m *mockSorobanRPC) methodCount(method string) int {
239239
// ---------------------------------------------------------------------------
240240

241241
const (
242-
testContract = "CBWQUIB4R65Z2DGC263FQ7BBI7TGIGOLFTYMLE6QPWBD5QDOUVJY3AKR"
243-
testNetworkID = "stellar-test"
242+
testContract = "CBWQUIB4R65Z2DGC263FQ7BBI7TGIGOLFTYMLE6QPWBD5QDOUVJY3AKR"
243+
testNetworkID = "stellar-test"
244244
testStartLedger = uint64(100)
245245
)
246246

@@ -562,8 +562,8 @@ func TestReobserve_UsesCustomEndpoint(t *testing.T) {
562562
txHash := "dead000000000000000000000000000000000000000000000000000000000000"
563563
createdAt := int64(1700000000)
564564

565-
primaryMock := newMockRPC(100) // primary server: no transactions
566-
customMock := newMockRPC(300) // custom server: has the transaction
565+
primaryMock := newMockRPC(100) // primary server: no transactions
566+
customMock := newMockRPC(300) // custom server: has the transaction
567567
customMock.transactions[txHash] = mockTx{status: "SUCCESS", ledger: 200, createdAt: createdAt}
568568
customMock.events = []mockEvent{
569569
{

0 commit comments

Comments
 (0)