Skip to content

chore(test): drop redundant *Eventually wrappers obsoleted by PR #898#902

Merged
bootjp merged 1 commit into
mainfrom
chore/drop-redundant-eventually-helpers
Jun 2, 2026
Merged

chore(test): drop redundant *Eventually wrappers obsoleted by PR #898#902
bootjp merged 1 commit into
mainfrom
chore/drop-redundant-eventually-helpers

Conversation

@bootjp
Copy link
Copy Markdown
Owner

@bootjp bootjp commented Jun 1, 2026

Summary

Follow-up to PR #898. The readiness probe (waitForWriteableLeader) closes the startup leader-churn window at the readiness layer, so the per-test rpushEventually / lpushEventually wrappers that absorbed that window become dead code.

What's dropped

  • rpushEventually + lpushEventually (test_util.go): only callers were redis_lua_compat_test.go lines 128–129 (first writes immediately after createNode). Migrated to direct rdb.RPush / rdb.LPush with a comment pointing back to PR test(util): commit one no-op entry to prove leader writeable in waitForRaftReadiness #898.
  • doEventually: only used by the two helpers above; no other callers.
  • Unused github.com/redis/go-redis/v9 import in test_util.go.

What's kept

  • retryNotLeader: still used in grpc_test.go (9 sites) wrapping mid-test RPCs inside 9999-iteration consistency loops. The readiness probe does NOT help mid-test churn (a real re-election can fire halfway through a long-running loop), so this helper retains its purpose. The doc comment is refreshed to clarify the startup vs mid-test distinction.

Caller audit (per /loop semantic-change rule)

Repo-wide grep:

  • rpushEventually\b / lpushEventually\b: 0 callers remain (only historical comment refs in redis_lua_compat_test.go).
  • doEventually\b: 0 callers remain.
  • retryNotLeader\b: 9 callers, all in grpc_test.go. Unchanged.

Validation

  • go test ./adapter/ -run TestRedis_LuaRPopLPushBullMQLikeLists -race -count=3 → ok 5.1s (direct RPush/LPush inherits the writeable-leader gate from createNode; no flake)
  • gofmt + go vet + golangci-lint run → 0 issues

Scope

Closes the "*Eventually helper unnecessization audit" follow-up noted in PR #898's description.

@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented Jun 1, 2026

Warning

Review limit reached

@bootjp, we couldn't start this review because you've reached your PR review rate limit.

More reviews will be available in 8 minutes and 18 seconds. Learn how PR review limits work.

Your organization has run out of usage credits. Purchase more in the billing tab.

⌛ How to resolve this issue?

After more reviews become available, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

We recommend that you space out your commits to avoid hitting the rate limit.

🚦 How do rate limits work?

CodeRabbit enforces hourly rate limits for each developer per organization.

Our paid plans include higher PR review limits than trial, open-source, and free plans. In all cases, reviews become available again over time. During sustained high-volume PR review activity, CodeRabbit may temporarily slow when the next review becomes available.

Please see our Fair Usage Limits Policy for further information.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: f6a1f0d6-b91c-4e5b-9915-58af5aad3631

📥 Commits

Reviewing files that changed from the base of the PR and between 214d6d7 and 46cf740.

📒 Files selected for processing (2)
  • adapter/redis_lua_compat_test.go
  • adapter/test_util.go
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch chore/drop-redundant-eventually-helpers

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link
Copy Markdown
Contributor

@gemini-code-assist gemini-code-assist Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

This pull request removes the obsolete helper functions doEventually, rpushEventually, and lpushEventually from adapter/test_util.go and replaces their usage in adapter/redis_lua_compat_test.go with direct Redis calls. This cleanup is possible because startup leader churn is now handled at the readiness layer (via waitForWriteableLeader introduced in PR #898). There are no review comments, so I have no feedback to provide.

@bootjp
Copy link
Copy Markdown
Owner Author

bootjp commented Jun 2, 2026

@claude review

PR-β: drop redundant *Eventually wrappers (obsoleted by PR #898's waitForWriteableLeader).

gemini-code-assist already reviewed: "There are no review comments, so I have no feedback to provide." — no findings.

Verify: (a) only 2 first-write-after-createNode sites (in redis_lua_compat_test.go) used the wrappers; both migrated to direct calls; (b) doEventually/rpushEventually/lpushEventually deleted, retryNotLeader kept (still used by grpc_test.go mid-loop).

@claude
Copy link
Copy Markdown

claude Bot commented Jun 2, 2026

Claude finished @bootjp's task in 1m 14s —— View job


Review: chore(test): drop redundant *Eventually wrappers

  • Read changed files (adapter/test_util.go, adapter/redis_lua_compat_test.go)
  • Verify: only 2 first-write-after-createNode sites used the wrappers; both migrated to direct calls
  • Verify: doEventually/rpushEventually/lpushEventually fully deleted, no remaining callers
  • Verify: retryNotLeader kept, still used in grpc_test.go mid-loop
  • Summarize findings

Verification results

Claim (a): Only 2 first-write-after-createNode sites in redis_lua_compat_test.go used the wrappers; both migrated to direct calls.

Confirmed. TestRedis_LuaRPopLPushBullMQLikeLists at adapter/redis_lua_compat_test.go:131-132 now reads:

require.NoError(t, rdb.RPush(ctx, "bull:test:wait", "job-1", "job-2", "job-3").Err())
require.NoError(t, rdb.LPush(ctx, "bull:test:active", "job-0").Err())

These were the only two call sites. The comment on lines 124–130 accurately explains why direct calls now suffice (the waitForWriteableLeader readiness gate closes the startup churn window before returning).

Claim (b): doEventually/rpushEventually/lpushEventually deleted with 0 remaining callers; retryNotLeader kept.

Confirmed by repo-wide grep:

  • rpushEventually, lpushEventually, doEventually — 0 occurrences anywhere. Completely excised.
  • retryNotLeader — defined at adapter/test_util.go:722, with call sites at adapter/grpc_test.go:207, 219, 228, 262, 273, 283, 291 (7 actual call sites inside 9999-iteration consistency loops). The PR description says "9 callers" but grep finds 7 actual invocations and 3 comment/doc references. Minor description inaccuracy — does not affect correctness.
  • The github.com/redis/go-redis/v9 import has been removed from test_util.go as claimed; the client import now lives only in the test files that actually use it.

retryNotLeader doc comment (adapter/test_util.go:711-721) correctly distinguishes startup churn (now closed by waitForWriteableLeader) from mid-test churn (still a real risk in long loops), and gives callers clear guidance on when each mechanism applies.

Assessment

The change is correct and clean. The logic is sound: waitForWriteableLeader already commits one no-op Raft entry through full quorum before createNode returns, so the first write from any test is guaranteed to land on a proven leader — no per-callsite retry wrapper needed. retryNotLeader is correctly retained for mid-test churn that can't be pre-empted at setup time.

No issues found. LGTM.

PR #898 added waitForWriteableLeader to waitForRaftReadiness, which
drives one no-op Raft entry through full quorum before createNode
returns. The post-readiness leader-churn window the
rpushEventually / lpushEventually wrappers absorbed is now closed at
the readiness layer instead. The wrappers are dead code.

Changes:
  - Drop rpushEventually + lpushEventually from test_util.go (the
    only two callers, in redis_lua_compat_test.go, were first-write
    -after-createNode sites — replaced with direct RPush/LPush
    calls + a comment pointing back to PR #898).
  - Drop doEventually too: its only callers were the two helpers
    above. retryNotLeader (the underlying classifier loop) stays —
    grpc_test.go still uses it for *mid-test* leader churn inside
    its 9999-iteration consistency loops, which PR #898 does not
    address.
  - Drop the now-unused redis import from test_util.go.
  - Refresh the leaderChurnRetryTimeout / retryNotLeader doc
    comments to call out that startup-window churn is closed at
    the readiness layer, and retryNotLeader is for mid-test loops.

Caller audit per /loop semantic-change rule
============================================

  - rpushEventually / lpushEventually: grep across the repo
    confirms zero remaining call sites after the migration. Safe
    to delete.
  - doEventually: only called by the two helpers above; also safe
    to delete.
  - retryNotLeader: kept. Sole external caller is
    adapter/grpc_test.go (9 sites inside two consistency-loop
    tests). All those wrap mid-test RPCs that can race a real
    re-election under CI load — the readiness probe does not
    help mid-test churn, so the helper retains its purpose.

Validation
==========

  go test ./adapter/ -run TestRedis_LuaRPopLPushBullMQLikeLists
    -race -count=3 -> ok 5.1s
    (the direct RPush/LPush calls inherit the writeable-leader
     gate from createNode, no flake)
  gofmt + go vet + golangci-lint run -> 0 issues
@bootjp bootjp force-pushed the chore/drop-redundant-eventually-helpers branch from b611ce9 to 46cf740 Compare June 2, 2026 07:13
@bootjp
Copy link
Copy Markdown
Owner Author

bootjp commented Jun 2, 2026

@claude review

Rebased onto main after PR #903 (eventuallyExpired helper) merged. Conflict was in adapter/test_util.go where PR #903 added eventuallyExpired while this PR deleted doEventually/rpushEventually/lpushEventually in the same region. Resolution: kept eventuallyExpired (from main) and dropped the *Eventually trio (PR-β intent).

Head: 46cf740. Rebased diff is 1 commit, only adapter/test_util.go + adapter/redis_lua_compat_test.go changes (same scope as before rebase, just on top of newer main).

go test ./adapter/ -run 'TestRedis_LuaRPopLPushBullMQLikeLists|TestRedis_HGET_TTLExpired|TestLua_HGET_HashTTL' -race -count=2 passes. gofmt + golangci-lint clean.

@claude
Copy link
Copy Markdown

claude Bot commented Jun 2, 2026

Claude finished @bootjp's task in 1m 0s —— View job


Review: chore(test): drop redundant *Eventually wrappers (post-rebase onto #903)

  • Read changed files (adapter/test_util.go, adapter/redis_lua_compat_test.go)
  • Check diff against origin/main
  • Verify rebase conflict resolution (kept eventuallyExpired, dropped *Eventually trio)
  • Confirm no remaining callers of deleted helpers
  • Summarize findings

Verification results

Rebase conflict resolution — correct.
The merge conflict in adapter/test_util.go between this PR (deleting doEventually/rpushEventually/lpushEventually) and PR #903 (adding eventuallyExpired in the same region) was resolved correctly:

  • eventuallyExpired at test_util.go:735 — present and intact. The full helper body from test(redis): structural fix — eventuallyExpired helper for TTL-expiry tests #903 is preserved verbatim including its doc comment chain (lines 715–751).
  • doEventually, rpushEventually, lpushEventually — fully removed from test_util.go. Zero remaining call sites anywhere in the repo. The only occurrences of those names in the tree are the comment lines in redis_lua_compat_test.go:128-129 explaining the migration, which is appropriate.

Diff scope — unchanged from pre-rebase.
Only adapter/test_util.go and adapter/redis_lua_compat_test.go are in the diff, same as before the rebase.

retryNotLeader kept — correct.
7 actual call sites in grpc_test.go (lines 207, 219, 228, 262, 273, 283, 291). The updated doc comment at test_util.go:757-764 correctly distinguishes mid-test churn (where retryNotLeader is needed) from startup churn (now closed by waitForWriteableLeader). Good guidance for future callers.

Import cleanup — correct.
github.com/redis/go-redis/v9 removed from test_util.go imports; it's no longer needed there since neither rpushEventually nor lpushEventually exist.

Minor note (description only, not code): The PR description says "retryNotLeader — 9 callers" but grep finds 7 actual call sites (lines 207, 219, 228, 262, 273, 283, 291) plus 2 comment/doc references. No impact on correctness.

Assessment

The rebase was handled correctly. The intended change — dropping the *Eventually startup-churn trio while preserving eventuallyExpired from #903 — is exactly what the diff shows. LGTM.

bootjp added a commit that referenced this pull request Jun 2, 2026
…gatorRaceFree (#906)

## Summary

Fixes the CI flake observed in [Actions run
26765510693](https://github.com/bootjp/elastickv/actions/runs/26765510693/job/78890657730?pr=902):

```
--- FAIL: TestHotKeysAggregatorRaceFree (0.11s)
    hot_keys_test.go:356: Expected value not to be nil.
```

Surfaced on PR #902's CI run but **unrelated to PR #902** — the failing
test is on `main` in `keyviz/`, which PR #902 (Redis adapter
`*Eventually` helper cleanup) doesn't touch.

## Root cause

Same wall-clock-racing pattern as the SQS-throttle (PR #891) and
Redis-TTL (PR #903) flake series. The test:

1. Launches an aggregator goroutine (Step=5ms tick).
2. Spawns 8 workers each calling `Observe` 500 times.
3. `time.Sleep(50 * time.Millisecond)`.
4. Asserts both per-route snapshots are non-nil.

The aggregator publishes a snapshot only on a tick (or on ctx-done
drain). Under `-race` on a slow CI runner, the `Run` goroutine itself
can be slow to schedule — the 50ms wait may not contain a single actual
tick worth of scheduler time, so `hotKeysSnap` stays at its initial
`nil` `atomic.Pointer` load and the assertion fires.

## Fix

`require.Eventually` with a 3-second budget + 5ms poll cadence,
asserting both snapshots non-nil:

```go
require.Eventually(t, func() bool {
    return s.HotKeysSnapshot(1) != nil && s.HotKeysSnapshot(2) != nil
}, 3*time.Second, 5*time.Millisecond, "aggregator must publish a snapshot for each route within the budget")
```

The test still pins the load-bearing property (snapshot reads are
lock-free; the `atomic.Pointer.Load` works without contention with the
publisher); only the **wait mechanism** changes from "sleep blindly and
hope" to "poll until ready or fail". Total time bound is at most 3s on a
slow runner, ~5–50ms in the common case.

## Validation

- `go test ./keyviz/ -run TestHotKeysAggregatorRaceFree -race -count=5
-timeout 120s` → ok 1.1s (5/5 iterations green)
- `gofmt` + `golangci-lint run` → 0 issues

## Pattern continuity

This is the same kind of structural fix as PR #891 / #903: **replace
fixed-time-window sleep with `require.Eventually`** for any condition
that depends on a background goroutine's progress under `-race` on CI.
Future flakes in this category should follow the same pattern.
@bootjp bootjp merged commit 8415ce0 into main Jun 2, 2026
9 checks passed
@bootjp bootjp deleted the chore/drop-redundant-eventually-helpers branch June 2, 2026 12:28
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant