Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,7 @@ Ref: https://keepachangelog.com/en/1.0.0/

### Bug Fixes

- (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.
- (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).
- (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.
- (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.
Expand Down
25 changes: 16 additions & 9 deletions server/indexer_service_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -88,7 +88,9 @@ func TestIndexerServiceRetriesAfterFetchError(t *testing.T) {
height: 1,
headerCh: make(chan coretypes.ResultEvent, 4),
}
client.failuresLeft.Store(2) // first two BlockResults calls fail, then succeed
// One failure → recovery needs exactly one wake-up token. (Two needed two, but the
// capacity-1 signal channel coalesces close headers into one → the old -race flake.)
client.failuresLeft.Store(1)
idxr := &mockIndexer{indexed: make(chan int64, 8)}

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

// Attempt 1 fails on startup catch-up (height 1). Each signal wakes the
// wait branch: attempt 2 fails, attempt 3 succeeds and must recover.
// Phase 1 — busy-loop check: startup catch-up (height 1) fails, no signal sent.
// Correct code parks; a busy-loop retries immediately and indexes without a wake-up.
select {
case h := <-idxr.indexed:
t.Fatalf("indexed height %d without a wake-up: busy-loop regression", h)
case <-time.After(1500 * time.Millisecond): // parked, as it should be
}

// Phase 2 — latch check: one signal = one retry token. Correct code clears the error
// and catches up (heights 1–2); the latched variant stays parked and trips the deadline.
signal(2)
signal(3)

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

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