Skip to content

Commit 7efecf2

Browse files
authored
Merge pull request #325 from mocachain/fix/deflake-indexer-service-test
test(server): de-flake the indexer-service retry test
2 parents dd17981 + d4a70ee commit 7efecf2

2 files changed

Lines changed: 17 additions & 9 deletions

File tree

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -77,6 +77,7 @@ Ref: https://keepachangelog.com/en/1.0.0/
7777

7878
### Bug Fixes
7979

80+
- (tests) [#325](https://github.com/mocachain/moca/pull/325) De-flake `TestIndexerServiceRetriesAfterFetchError`: recovery needed two wake-up tokens but the new-block signal channel coalesces to one, stranding the second retry on the 60s timeout under the `-race` scheduler. Restructured to a deterministic two-phase design (quiescence check catches the busy-loop regression; a single-token recovery catches the latch) — verified 30× under `-race` and still failing on both historical defects.
8081
- (e2e) [#319](https://github.com/mocachain/moca/pull/319) Route `log_error`/`log_warn` to stderr in the kind e2e harness so error/warning text isn't swallowed into `x=$(fn)` command substitutions (which masked failures as silent "Test exited early" and polluted captured values).
8182
- (server) [#311](https://github.com/mocachain/moca/pull/311) Harden the EVM tx indexer service's fetch loop: back off on transient `Block`/`BlockResults` fetch errors instead of busy-looping, clear the error before retrying so indexing cannot stall until restart (upstream cosmos/evm as of v0.6.0 latches it), and make the shared latest-height access atomic (data race between the new-block subscription goroutine and the indexing loop). Guarded by a mock-driven regression test that fails on all three defects.
8283
- (virtualgroup,storage) [#306](https://github.com/mocachain/moca/pull/306) Tighten storage provider exit preconditions and make discontinued-resource cleanup resolve its primary SP defensively.

server/indexer_service_test.go

Lines changed: 16 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -88,7 +88,9 @@ func TestIndexerServiceRetriesAfterFetchError(t *testing.T) {
8888
height: 1,
8989
headerCh: make(chan coretypes.ResultEvent, 4),
9090
}
91-
client.failuresLeft.Store(2) // first two BlockResults calls fail, then succeed
91+
// One failure → recovery needs exactly one wake-up token. (Two needed two, but the
92+
// capacity-1 signal channel coalesces close headers into one → the old -race flake.)
93+
client.failuresLeft.Store(1)
9294
idxr := &mockIndexer{indexed: make(chan int64, 8)}
9395

9496
svc := NewEVMIndexerService(idxr, client)
@@ -104,10 +106,17 @@ func TestIndexerServiceRetriesAfterFetchError(t *testing.T) {
104106
}
105107
}
106108

107-
// Attempt 1 fails on startup catch-up (height 1). Each signal wakes the
108-
// wait branch: attempt 2 fails, attempt 3 succeeds and must recover.
109+
// Phase 1 — busy-loop check: startup catch-up (height 1) fails, no signal sent.
110+
// Correct code parks; a busy-loop retries immediately and indexes without a wake-up.
111+
select {
112+
case h := <-idxr.indexed:
113+
t.Fatalf("indexed height %d without a wake-up: busy-loop regression", h)
114+
case <-time.After(1500 * time.Millisecond): // parked, as it should be
115+
}
116+
117+
// Phase 2 — latch check: one signal = one retry token. Correct code clears the error
118+
// and catches up (heights 1–2); the latched variant stays parked and trips the deadline.
109119
signal(2)
110-
signal(3)
111120

112121
deadline := time.After(10 * time.Second)
113122
got := map[int64]bool{}
@@ -122,9 +131,7 @@ func TestIndexerServiceRetriesAfterFetchError(t *testing.T) {
122131
}
123132
require.True(t, got[1] && got[2], "heights 1 and 2 must be indexed after recovery, got %v", got)
124133

125-
// No busy-loop: while erroring, exactly one fetch attempt per wake-up.
126-
// Catch-up + two signaled retries + the follow-up block ≈ 4 attempts;
127-
// leave slack for scheduling, but orders of magnitude below a busy loop.
128-
require.LessOrEqual(t, client.attempts.Load(), int64(6),
129-
"fetch attempts should be bounded by wake-ups (busy-loop regression)")
134+
// Sanity bound: catch-up failure + signaled retry + follow-up block = 3.
135+
require.LessOrEqual(t, client.attempts.Load(), int64(4),
136+
"fetch attempts should be bounded by wake-ups")
130137
}

0 commit comments

Comments
 (0)