Skip to content

RPC pool: park a node that keeps failing, drop the unreachable one, per-node stats - #77

Merged
feruzm merged 4 commits into
mainfrom
fix/ssr-rpc-pool-hygiene
Aug 21, 2026
Merged

RPC pool: park a node that keeps failing, drop the unreachable one, per-node stats#77
feruzm merged 4 commits into
mainfrom
fix/ssr-rpc-pool-hygiene

Conversation

@feruzm

@feruzm feruzm commented Aug 21, 2026

Copy link
Copy Markdown
Member

Closes #76.

Found while attributing the SSR cache's lookup timeouts on one origin: a single sample of the service's upstream sockets showed 83 half-open connects to hive-api.arcange.eu at once, with the failover target's connection count jumping right after. That node never completes a TCP connect from any host this service runs on. The tracker let it happen: a timeout below the 2s "slow failure" floor left no latency sample, so the node kept its unexplored standing (neutral 1s prior); only 429s parked a node, and a failure demoted one for 30s at most. So each time the leading nodes each recorded one transient failure, the dead node was next in line and every in-flight fill went to it at the full per-node timeout.

  • NodeHealthTracker: a timeout is recorded as a latency sample whatever the floor (the floor still tells instant refusals from slow 5xx); three consecutive failures park the node for 30s, doubling to 120s, a success clears the streak; a failure-parked node is skipped while any other node is available and probed once its park lapses; when every node is parked all are offered. Per-node lifetime counters (calls, ok, failures, timeouts, rate-limited) and a Snapshot(). Clock is an injectable seam per tracker (internal client constructor) so the windows are tested deterministically.
  • HiveRpcClient: the timeout branch tags its exception; HealthSnapshot() (host names only); hive-api.arcange.eu removed from the default pool with the reason next to the existing exclusions.
  • SsrRpc: slow_fill per method (fills that outran the budget; timeout stays per waiting reader, so one slow fill on a hot key is one slow fill and many timeouts) and a nodes array in /private-api/ssr/stats.
  • Tests: dead node parked after three timeouts and skipped when the leader hiccups, probed once after the park lapses and re-parked for twice as long, not probed inside that window; an all-parked pool is still tried; the default pool carries no arcange; five coalesced readers on one slow fill are five timeouts and one slow fill, with the node section reporting the serving node. 158 total.

Summary by CodeRabbit

  • New Features
    • Added node health information to the /stats response, including availability, latency, failures, timeouts, and rate limits.
    • Added tracking for slow upstream responses and shared request coalescing.
  • Bug Fixes
    • Improved failover by temporarily skipping repeatedly failing nodes when healthy alternatives are available.
    • Retains fallback behavior by retrying parked nodes when all available nodes are affected.
    • Removed an unreachable default node from the connection pool.

…drop the unreachable node, per-node stats

Closes #76
@qodo-code-review

qodo-code-review Bot commented Aug 21, 2026

Copy link
Copy Markdown

PR Summary by Qodo

RPC pool hygiene: failure parking, remove unreachable node, add per-node stats

🐞 Bug fix ✨ Enhancement 🧪 Tests 🕐 40+ Minutes

Grey Divider

AI Description

• Park RPC nodes after repeated failures/timeouts to avoid bursty retries to dead hosts.
• Expose per-node health snapshot in SSR stats and add slow_fill metric per method.
• Remove unreachable default Hive node and add deterministic tests for new behavior.
Diagram

graph TD
  A["SSR cache fill"] --> B["HiveRpcClient"] --> D{{"Hive RPC nodes"}}
  B --> C["NodeHealthTracker"]
  E["/private-api/ssr/stats"] --> B
  E --> F["SSR method counters"]
Loading
High-Level Assessment

The following are alternative approaches to this PR:

1. Adopt Polly circuit-breaker per node
  • ➕ Battle-tested failure/backoff semantics (open/half-open/closed) and telemetry hooks
  • ➕ Cleaner separation of policy vs client implementation details
  • ➖ Additional dependency and integration complexity (especially for per-node policies and ranking)
  • ➖ Would still need custom logic for latency EWMA ranking and “try all when all parked” semantics
2. Background health checks + remove nodes from rotation
  • ➕ Keeps hot-path selection simpler (only healthy nodes are in the active set)
  • ➕ Can use richer probes (TCP connect, HTTP HEAD) independent of request traffic
  • ➖ Adds another moving part (scheduler, probe failure modes, probe load)
  • ➖ Health checks may not match real request behavior (false positives/negatives)
3. Static allowlist only (config hygiene, no dynamic parking)
  • ➕ Lowest runtime complexity and least logic risk
  • ➕ Avoids flaky heuristics and time-window tuning
  • ➖ Does not handle transient regional outages or nodes degrading over time
  • ➖ Still vulnerable to burst routing when a node becomes unreachable unexpectedly

Recommendation: Keep the PR’s approach: lightweight, in-process failure parking with deterministic clock injection and explicit “try all when all parked” behavior. It directly addresses the observed failure mode (unreachable node capturing bursts) while preserving the existing latency EWMA ranking model, and the new tests lock down the tricky timing behavior without introducing a policy dependency.

Files changed (5) +260 / -19

Enhancement (1) +9 / -1
SsrRpc.csTrack per-method slow_fill and expose node health in SSR stats +9/-1

Track per-method slow_fill and expose node health in SSR stats

• Adds a 'SlowFill' counter per method to distinguish fills exceeding the SSR budget from per-reader timeouts. Extends the stats response to include 'slow_fill' per method and a 'nodes' section sourced from the RPC client health snapshot.

dotnet/EcencyApi/Handlers/SsrRpc.cs

Bug fix (2) +124 / -18
HiveRpcClient.csExpose node health snapshot and tag timeouts for health tracking +46/-5

Expose node health snapshot and tag timeouts for health tracking

• Adds an internal clock seam for deterministic health-tracker tests and a public 'HealthSnapshot()' that returns per-node counters/state (hostnames only). Tags per-node timeouts in the exception flow so timeouts can be counted and treated as latency samples; removes 'hive-api.arcange.eu' from the default node pool with rationale.

dotnet/EcencyApi/Infrastructure/HiveRpcClient.cs

NodeHealthTracker.csImplement failure parking, timeout-as-latency sampling, and per-node counters +78/-13

Implement failure parking, timeout-as-latency sampling, and per-node counters

• Introduces failure-parking after three consecutive failures with exponential backoff up to 120s, and changes selection to skip failure-parked nodes while any other node is available (but still try all when every node is parked). Records timeouts as latency samples regardless of the slow-failure floor, adds injectable clock for deterministic time-window tests, and exposes a 'Snapshot()' with lifetime per-node counters and current park/limit state.

dotnet/EcencyApi/Infrastructure/NodeHealthTracker.cs

Tests (2) +127 / -0
HiveRpcFailoverTests.csAdd tests for failure parking, all-parked behavior, and default pool hygiene +87/-0

Add tests for failure parking, all-parked behavior, and default pool hygiene

• Adds coverage to ensure a repeatedly timing-out node is parked after three failures, skipped while other nodes can serve, and probed only after the park expires (with backoff doubling). Also verifies an all-parked pool still attempts nodes and that the default node list no longer includes the unreachable arcange endpoint.

dotnet/EcencyApi.Tests/HiveRpcFailoverTests.cs

SsrRpcTests.csTest SSR stats: slow_fill vs reader timeouts and per-node reporting +40/-0

Test SSR stats: slow_fill vs reader timeouts and per-node reporting

• Introduces a concurrency/coalescing test asserting that multiple waiter timeouts map to a single slow_fill for one upstream fill. Validates that '/private-api/ssr/stats' includes a 'nodes' array and that it reports correct per-node counters for the serving stub.

dotnet/EcencyApi.Tests/SsrRpcTests.cs

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: e68bee4f84

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

{
RecordLatency(h, elapsedMs);
}
if (h.ConsecutiveFailures >= FailureParkThreshold)

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2 Badge Stop retrying a node once it becomes parked

When the default failoverThreshold of 2 is used and a node enters a call with two consecutive failures, the first failed attempt parks it here, but HiveRpcClient.Send has already captured the ordered node list and continues its inner retry loop because timeouts and connection failures do not set AdvanceImmediately. The supposedly parked node therefore receives a fourth attempt before failover, adding another full timeout and immediately extending its initial 30-second park to 60 seconds. The retry loop should stop when RecordFailure transitions the node into the parked state.

Useful? React with 👍 / 👎.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

Applied in a64dbf9: RecordFailure now returns whether the node is parked after this failure, and both failure branches in Send break out of the same-node retry on true. Test: with failoverThreshold 2 the third consecutive failure makes exactly one attempt and parks for 30s, not two attempts and 60s.

Comment thread dotnet/EcencyApi/Handlers/SsrRpc.cs Outdated
counter.RecordUpstream(Environment.TickCount64 - started);
var elapsed = Environment.TickCount64 - started;
counter.RecordUpstream(elapsed);
if (elapsed > BudgetMs) Interlocked.Increment(ref counter.SlowFill);

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2 Badge Count slow fills that end in an upstream error

When Client.CallMethod exceeds BudgetMs and then throws, such as after a node timeout or slow transport failure, execution jumps directly to the catch block before this increment. Every waiting reader can therefore time out while slow_fill remains zero, causing the new stats to hide slow fills precisely during upstream outages. Record the elapsed duration and update this counter on failed upstream calls as well.

Useful? React with 👍 / 👎.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

Applied in a64dbf9: the budget check moved into a finally around the upstream call, so a fill that outruns the budget and then throws increments slow_fill as well. Test: a 400ms upstream that answers an RPC error under a 100ms budget is one reader timeout and one slow fill.

@coderabbitai

coderabbitai Bot commented Aug 21, 2026

Copy link
Copy Markdown

Review Change Stack

Warning

Review limit reached

@feruzm, you've reached your PR review limit, so we couldn't start this review.

Next review available in: 41 minutes

Limit details: You’ve used the included review currently available.

You've used all free OSS reviews for now. Wait for the free limit to reset to keep reviewing this public repository.

How can I continue?

Wait for the limit to reset, then comment @coderabbitai review or push new commits to the PR.

An organization admin can change what happens after included review limits in Billing.

How do review limits work?

CodeRabbit enforces per-developer PR review limits within each organization.

For paid Pro and Pro+ reviews, CodeRabbit uses a developer's included PR review attempts over the past 7 days to set the current hourly allowance. At typical activity levels, the full plan allowance applies. Higher sustained activity can lower the allowance until earlier attempts leave the 7-day window.

Please refer docs for additional details.

Review details
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro Plus

Run ID: 3d46c33f-c8a4-4124-ae06-534e51fd4d8c

📥 Commits

Reviewing files that changed from the base of the PR and between e68bee4 and e98431b.

📒 Files selected for processing (5)
  • dotnet/EcencyApi.Tests/HiveRpcFailoverTests.cs
  • dotnet/EcencyApi.Tests/SsrRpcTests.cs
  • dotnet/EcencyApi/Handlers/SsrRpc.cs
  • dotnet/EcencyApi/Infrastructure/HiveRpcClient.cs
  • dotnet/EcencyApi/Infrastructure/NodeHealthTracker.cs

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro Plus

Run ID: 3412e1b4-1f56-47ce-9c9b-68c5354e9ede

📥 Commits

Reviewing files that changed from the base of the PR and between 76c120b and e68bee4.

📒 Files selected for processing (5)
  • dotnet/EcencyApi.Tests/HiveRpcFailoverTests.cs
  • dotnet/EcencyApi.Tests/SsrRpcTests.cs
  • dotnet/EcencyApi/Handlers/SsrRpc.cs
  • dotnet/EcencyApi/Infrastructure/HiveRpcClient.cs
  • dotnet/EcencyApi/Infrastructure/NodeHealthTracker.cs

Included review availability: Your plan provides up to 1 included review per hour; 0 remain after this review.


📝 Walkthrough

Walkthrough

The change adds injectable node-health tracking with failure parking, timeout classification, per-node statistics, and slow-fill metrics. It removes an unreachable default node and adds integration tests for failover, fallback, health reporting, and coalesced SSR requests.

Changes

Node health and failover

Layer / File(s) Summary
Failure parking and health tracking
dotnet/EcencyApi/Infrastructure/NodeHealthTracker.cs
NodeHealthTracker tracks calls, outcomes, timeout latency, rate limits, consecutive failures, escalating parking durations, node ordering, and health snapshots using injectable time.
Client failover integration
dotnet/EcencyApi/Infrastructure/HiveRpcClient.cs, dotnet/EcencyApi.Tests/HiveRpcFailoverTests.cs
HiveRpcClient classifies timeout failures, exposes node health, removes hive-api.arcange.eu from the default pool, and tests parking, fallback, re-parking, and node removal.

SSR statistics

Layer / File(s) Summary
Slow-fill and stats reporting
dotnet/EcencyApi/Handlers/SsrRpc.cs, dotnet/EcencyApi.Tests/SsrRpcTests.cs
SsrRpc records slow fills separately from reader timeouts and exposes node health. The integration test validates coalesced requests and per-node counters.

Estimated code review effort: 4 (Complex) | ~45 minutes

Merge Risk: ⚪ Minimal · up to e68be

The PR improves RPC node failure handling and adds per-node statistics without any identified merge-blocking issue; it is merge-ready after normal checks and review.

Poem

I’m a rabbit watching nodes hop,
Park the slow ones, let the swift ones pop.
One fill, many readers wait,
Stats now show each node’s state.
Timeout tails are counted straight—
Hop, hop, health is up to date!

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 32.00% which is insufficient. The required threshold is 80.00%. Docstring coverage is scoped to functions touched by this diff. Analyzed 25 functions across 5 files. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly summarizes the main RPC pool and per-node statistics changes.
Linked Issues check ✅ Passed The changes satisfy issue [#76] by removing the unreachable node, exposing per-node health, and separating slow fills from waiter timeouts.
Out of Scope Changes check ✅ Passed The failover, parking, timeout, and deterministic test changes support the linked issue objectives and are not unrelated.
✨ Finishing Touches 💡 1
📝 Generate docstrings 💡
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch fix/ssr-rpc-pool-hygiene

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.

@qodo-code-review

qodo-code-review Bot commented Aug 21, 2026

Copy link
Copy Markdown

Code Review by Qodo

🐞 Bugs (2) 📘 Rule violations (6) 📎 Requirement gaps (0) 🎨 UX issues (0) 🔗 Cross-repo conflicts (0) 📜 Skill insights (0)

Grey Divider


Action required

1. Success leaves node parked ✓ Resolved 🐞 Bug ☼ Reliability
Description
RecordSuccess resets the failure-park streak but leaves FailureParkedUntilMs active, so a node
that succeeds when an all-parked pool is offered can still be excluded on the next call as soon as
any other node's park expires. This can suppress a just-proven healthy node and fail requests
through a worse node until the stale park deadline lapses.
Code

dotnet/EcencyApi/Infrastructure/NodeHealthTracker.cs[93]

+            h.FailureParkStreak = 0;
Relevance

●●● Strong

Concrete node-health state bug; similar tracker correctness fixes were accepted recently.

PR-#73

ⓘ Recommendations generated based on similar findings in past PRs

Evidence
All-parked pools deliberately return every node from OrderedNodeIndices, allowing an actively
parked node to succeed. RecordSuccess clears counters but not FailureParkedUntilMs; later
ordering defines deadness solely from that deadline and removes the recovered node whenever another
node is no longer parked.

dotnet/EcencyApi/Infrastructure/NodeHealthTracker.cs[84-95]
dotnet/EcencyApi/Infrastructure/NodeHealthTracker.cs[178-203]
dotnet/EcencyApi.Tests/HiveRpcFailoverTests.cs[244-260]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
A successful call resets the failure streak but does not clear the active failure-park deadline.
## Issue Context
Failure-parked nodes are attempted when every node is parked, so success during an active park is reachable and should immediately restore that node to normal ordering.
## Fix Focus Areas
- dotnet/EcencyApi/Infrastructure/NodeHealthTracker.cs[84-95]
- dotnet/EcencyApi/Infrastructure/NodeHealthTracker.cs[173-203]
- dotnet/EcencyApi.Tests/HiveRpcFailoverTests.cs[244-260]

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


2. Short timeouts improve dead ranking ✓ Resolved 🐞 Bug ≡ Correctness
Description
RecordFailure records the raw timeout duration as latency, so a valid timeout below the 1,000 ms
unproven prior gives an unreachable node a better score than every untouched node once its park
lapses. For example, the supported 300 ms timeout produces an approximately 300 ms score and causes
the dead node to be retried before unproven alternatives, undermining the intended demotion.
Code

dotnet/EcencyApi/Infrastructure/NodeHealthTracker.cs[R112-114]

+            if (timedOut || elapsedMs >= SlowFailureFloorMs)
          {
              RecordLatency(h, elapsedMs);
Relevance

●●● Strong

Concrete ranking inversion in new health logic; recent tracker latency fixes were accepted.

PR-#73

ⓘ Recommendations generated based on similar findings in past PRs

Evidence
Timeouts are newly passed into RecordFailure, which records their elapsed duration
unconditionally; ordering then compares that EWMA ascending against a fixed 1,000 ms score for
unproven nodes. The constructor accepts any positive configured timeout, and the new tests
themselves exercise a 300 ms timeout, proving this score inversion is reachable.

dotnet/EcencyApi/Infrastructure/HiveRpcClient.cs[204-214]
dotnet/EcencyApi/Infrastructure/NodeHealthTracker.cs[28-32]
dotnet/EcencyApi/Infrastructure/NodeHealthTracker.cs[101-115]
dotnet/EcencyApi/Infrastructure/NodeHealthTracker.cs[186-200]
dotnet/EcencyApi/Config.cs[48-50]
dotnet/EcencyApi.Tests/HiveRpcFailoverTests.cs[196-214]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
Timeout samples below the neutral latency prior currently improve an unreachable node's ordering instead of demoting it.
## Issue Context
Node ordering is ascending by latency score, and untouched nodes use a 1,000 ms prior. Valid configured/test timeouts may be shorter than that.
## Fix Focus Areas
- dotnet/EcencyApi/Infrastructure/NodeHealthTracker.cs[101-115]
- dotnet/EcencyApi/Infrastructure/NodeHealthTracker.cs[186-200]
- dotnet/EcencyApi.Tests/HiveRpcFailoverTests.cs[182-242]

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


3. Success leaves node parked ✓ Resolved 🐞 Bug ☼ Reliability
Description
RecordSuccess resets the failure-park streak but leaves FailureParkedUntilMs active, so a node
that succeeds when an all-parked pool is offered can still be excluded on the next call as soon as
any other node's park expires. This can suppress a just-proven healthy node and fail requests
through a worse node until the stale park deadline lapses.
Code

dotnet/EcencyApi/Infrastructure/NodeHealthTracker.cs[93]

+            h.FailureParkStreak = 0;
Relevance

●●● Strong

Concrete node-health state bug; similar tracker correctness fixes were accepted recently.

PR-#73

ⓘ Recommendations generated based on similar findings in past PRs

Evidence
All-parked pools deliberately return every node from OrderedNodeIndices, allowing an actively
parked node to succeed. RecordSuccess clears counters but not FailureParkedUntilMs; later
ordering defines deadness solely from that deadline and removes the recovered node whenever another
node is no longer parked.

dotnet/EcencyApi/Infrastructure/NodeHealthTracker.cs[84-95]
dotnet/EcencyApi/Infrastructure/NodeHealthTracker.cs[178-203]
dotnet/EcencyApi.Tests/HiveRpcFailoverTests.cs[244-260]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
A successful call resets the failure streak but does not clear the active failure-park deadline.
## Issue Context
Failure-parked nodes are attempted when every node is parked, so success during an active park is reachable and should immediately restore that node to normal ordering.
## Fix Focus Areas
- dotnet/EcencyApi/Infrastructure/NodeHealthTracker.cs[84-95]
- dotnet/EcencyApi/Infrastructure/NodeHealthTracker.cs[173-203]
- dotnet/EcencyApi.Tests/HiveRpcFailoverTests.cs[244-260]

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


View high (5)
4. Short timeouts improve dead ranking ✓ Resolved 🐞 Bug ≡ Correctness
Description
RecordFailure records the raw timeout duration as latency, so a valid timeout below the 1,000 ms
unproven prior gives an unreachable node a better score than every untouched node once its park
lapses. For example, the supported 300 ms timeout produces an approximately 300 ms score and causes
the dead node to be retried before unproven alternatives, undermining the intended demotion.
Code

dotnet/EcencyApi/Infrastructure/NodeHealthTracker.cs[R112-114]

+            if (timedOut || elapsedMs >= SlowFailureFloorMs)
         {
             RecordLatency(h, elapsedMs);
Relevance

●●● Strong

Concrete ranking inversion in new health logic; recent tracker latency fixes were accepted.

PR-#73

ⓘ Recommendations generated based on similar findings in past PRs

Evidence
Timeouts are newly passed into RecordFailure, which records their elapsed duration
unconditionally; ordering then compares that EWMA ascending against a fixed 1,000 ms score for
unproven nodes. The constructor accepts any positive configured timeout, and the new tests
themselves exercise a 300 ms timeout, proving this score inversion is reachable.

dotnet/EcencyApi/Infrastructure/HiveRpcClient.cs[204-214]
dotnet/EcencyApi/Infrastructure/NodeHealthTracker.cs[28-32]
dotnet/EcencyApi/Infrastructure/NodeHealthTracker.cs[101-115]
dotnet/EcencyApi/Infrastructure/NodeHealthTracker.cs[186-200]
dotnet/EcencyApi/Config.cs[48-50]
dotnet/EcencyApi.Tests/HiveRpcFailoverTests.cs[196-214]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
Timeout samples below the neutral latency prior currently improve an unreachable node's ordering instead of demoting it.
## Issue Context
Node ordering is ascending by latency score, and untouched nodes use a 1,000 ms prior. Valid configured/test timeouts may be shorter than that.
## Fix Focus Areas
- dotnet/EcencyApi/Infrastructure/NodeHealthTracker.cs[101-115]
- dotnet/EcencyApi/Infrastructure/NodeHealthTracker.cs[186-200]
- dotnet/EcencyApi.Tests/HiveRpcFailoverTests.cs[182-242]

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


5. Success leaves node parked ✓ Resolved 🐞 Bug ☼ Reliability
Description
RecordSuccess resets the failure-park streak but leaves FailureParkedUntilMs active, so a node
that succeeds when an all-parked pool is offered can still be excluded on the next call as soon as
any other node's park expires. This can suppress a just-proven healthy node and fail requests
through a worse node until the stale park deadline lapses.
Code

dotnet/EcencyApi/Infrastructure/NodeHealthTracker.cs[93]

+            h.FailureParkStreak = 0;
Relevance

●●● Strong

Concrete node-health state bug; similar tracker correctness fixes were accepted recently.

PR-#73

ⓘ Recommendations generated based on similar findings in past PRs

Evidence
All-parked pools deliberately return every node from OrderedNodeIndices, allowing an actively
parked node to succeed. RecordSuccess clears counters but not FailureParkedUntilMs; later
ordering defines deadness solely from that deadline and removes the recovered node whenever another
node is no longer parked.

dotnet/EcencyApi/Infrastructure/NodeHealthTracker.cs[84-95]
dotnet/EcencyApi/Infrastructure/NodeHealthTracker.cs[178-203]
dotnet/EcencyApi.Tests/HiveRpcFailoverTests.cs[244-260]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
A successful call resets the failure streak but does not clear the active failure-park deadline.
## Issue Context
Failure-parked nodes are attempted when every node is parked, so success during an active park is reachable and should immediately restore that node to normal ordering.
## Fix Focus Areas
- dotnet/EcencyApi/Infrastructure/NodeHealthTracker.cs[84-95]
- dotnet/EcencyApi/Infrastructure/NodeHealthTracker.cs[173-203]
- dotnet/EcencyApi.Tests/HiveRpcFailoverTests.cs[244-260]

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


6. Short timeouts improve dead ranking ✓ Resolved 🐞 Bug ≡ Correctness
Description
RecordFailure records the raw timeout duration as latency, so a valid timeout below the 1,000 ms
unproven prior gives an unreachable node a better score than every untouched node once its park
lapses. For example, the supported 300 ms timeout produces an approximately 300 ms score and causes
the dead node to be retried before unproven alternatives, undermining the intended demotion.
Code

dotnet/EcencyApi/Infrastructure/NodeHealthTracker.cs[R112-114]

+            if (timedOut || elapsedMs >= SlowFailureFloorMs)
          {
              RecordLatency(h, elapsedMs);
Relevance

●●● Strong

Concrete ranking inversion in new health logic; recent tracker latency fixes were accepted.

PR-#73

ⓘ Recommendations generated based on similar findings in past PRs

Evidence
Timeouts are newly passed into RecordFailure, which records their elapsed duration
unconditionally; ordering then compares that EWMA ascending against a fixed 1,000 ms score for
unproven nodes. The constructor accepts any positive configured timeout, and the new tests
themselves exercise a 300 ms timeout, proving this score inversion is reachable.

dotnet/EcencyApi/Infrastructure/HiveRpcClient.cs[204-214]
dotnet/EcencyApi/Infrastructure/NodeHealthTracker.cs[28-32]
dotnet/EcencyApi/Infrastructure/NodeHealthTracker.cs[101-115]
dotnet/EcencyApi/Infrastructure/NodeHealthTracker.cs[186-200]
dotnet/EcencyApi/Config.cs[48-50]
dotnet/EcencyApi.Tests/HiveRpcFailoverTests.cs[196-214]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
Timeout samples below the neutral latency prior currently improve an unreachable node's ordering instead of demoting it.
## Issue Context
Node ordering is ascending by latency score, and untouched nodes use a 1,000 ms prior. Valid configured/test timeouts may be shorter than that.
## Fix Focus Areas
- dotnet/EcencyApi/Infrastructure/NodeHealthTracker.cs[101-115]
- dotnet/EcencyApi/Infrastructure/NodeHealthTracker.cs[186-200]
- dotnet/EcencyApi.Tests/HiveRpcFailoverTests.cs[182-242]

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


7. Parking permits probe bursts ✓ Resolved 🐞 Bug ☼ Reliability
Description
Send materializes node ordering once, so concurrent requests that start just after a dead node's
park expires all retain that node and probe it after a leader failure even after the first probes
re-park it. This recreates the burst of half-open connections that failure parking is intended to
prevent.
Code

dotnet/EcencyApi/Infrastructure/NodeHealthTracker.cs[R193-195]

+            if (ranked.Any(x => !x.Dead))
+            {
+                ranked.RemoveAll(x => x.Dead);
Evidence
The client obtains one materialized ordering and never refreshes it while trying nodes. Failure
recording can re-park the node, but only future calls to OrderedNodeIndices observe the filter;
the new tests exercise this flow sequentially rather than with concurrent requests.

dotnet/EcencyApi/Infrastructure/HiveRpcClient.cs[155-159]
dotnet/EcencyApi/Infrastructure/HiveRpcClient.cs[204-225]
dotnet/EcencyApi/Infrastructure/NodeHealthTracker.cs[101-121]
dotnet/EcencyApi/Infrastructure/NodeHealthTracker.cs[173-203]
dotnet/EcencyApi.Tests/HiveRpcFailoverTests.cs[182-242]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
Failure-park filtering only runs when a request initially obtains its ordered node list. Concurrent requests can retain a newly re-parked node in stale lists and all probe it, recreating a connection burst.
## Issue Context
Node ordering is materialized once per RPC call. Parking updates made by one request therefore do not affect other requests already iterating their lists, and an expired park has no atomic single-probe/half-open gate.
## Fix Focus Areas
- dotnet/EcencyApi/Infrastructure/NodeHealthTracker.cs[173-203]
- dotnet/EcencyApi/Infrastructure/HiveRpcClient.cs[155-225]
- dotnet/EcencyApi.Tests/HiveRpcFailoverTests.cs[182-242]

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


8. Parking permits probe bursts ✓ Resolved 🐞 Bug ☼ Reliability
Description
Send materializes node ordering once, so concurrent requests that start just after a dead node's
park expires all retain that node and probe it after a leader failure even after the first probes
re-park it. This recreates the burst of half-open connections that failure parking is intended to
prevent.
Code

dotnet/EcencyApi/Infrastructure/NodeHealthTracker.cs[R193-195]

+            if (ranked.Any(x => !x.Dead))
+            {
+                ranked.RemoveAll(x => x.Dead);
Evidence
The client obtains one materialized ordering and never refreshes it while trying nodes. Failure
recording can re-park the node, but only future calls to OrderedNodeIndices observe the filter;
the new tests exercise this flow sequentially rather than with concurrent requests.

dotnet/EcencyApi/Infrastructure/HiveRpcClient.cs[155-159]
dotnet/EcencyApi/Infrastructure/HiveRpcClient.cs[204-225]
dotnet/EcencyApi/Infrastructure/NodeHealthTracker.cs[101-121]
dotnet/EcencyApi/Infrastructure/NodeHealthTracker.cs[173-203]
dotnet/EcencyApi.Tests/HiveRpcFailoverTests.cs[182-242]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
Failure-park filtering only runs when a request initially obtains its ordered node list. Concurrent requests can retain a newly re-parked node in stale lists and all probe it, recreating a connection burst.
## Issue Context
Node ordering is materialized once per RPC call. Parking updates made by one request therefore do not affect other requests already iterating their lists, and an expired park has no atomic single-probe/half-open gate.
## Fix Focus Areas
- dotnet/EcencyApi/Infrastructure/NodeHealthTracker.cs[173-203]
- dotnet/EcencyApi/Infrastructure/HiveRpcClient.cs[155-225]
- dotnet/EcencyApi.Tests/HiveRpcFailoverTests.cs[182-242]

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools



Remediation recommended

9. Rate limits trigger dead parking ✓ Resolved 🐞 Bug ≡ Correctness
Description
The new dead-node parking threshold relies on ConsecutiveFailures, but RecordRateLimited also
increments that counter, so a sequence like two 429s plus one transport/response failure can
hard-park a responsive throttled node for 30 seconds. This conflates the separate rate-limit
backoff/parking state with true consecutive failure detection and can remove an otherwise reachable
fallback even after its rate-limit window ends.
Code

dotnet/EcencyApi/Infrastructure/NodeHealthTracker.cs[R116-120]

+            if (h.ConsecutiveFailures >= FailureParkThreshold)
+            {
+                var parkMs = Math.Min(FailureParkBaseMs << Math.Min(h.FailureParkStreak, 2), FailureParkMaxMs);
+                h.FailureParkedUntilMs = now + parkMs;
+                h.FailureParkStreak++;
Relevance

●●● Strong

Shared failure streak conflates rate limits with real failures, undermining new parking feature
intent.

PR-#73

ⓘ Recommendations generated based on similar findings in past PRs

Evidence
In HiveRpcClient, HTTP 429 outcomes are routed to RecordRateLimited, while other unavailable
outcomes go to RecordFailure. Both of these paths mutate the shared ConsecutiveFailures counter
in NodeHealthTracker, and the newly added hard-parking threshold is evaluated on the next
RecordFailure. As a result, a 429 can advance the same streak that is intended to represent
consecutive ordinary failures, allowing a later normal failure to trigger hard parking and node
exclusion even though the node’s only “streak” includes throttling events, despite the
code/documentation treating throttled nodes as a distinct, potentially usable state with separate
backoff (RateLimitedUntilMs).

dotnet/EcencyApi/Infrastructure/HiveRpcClient.cs[204-214]
dotnet/EcencyApi/Infrastructure/NodeHealthTracker.cs[101-144]
dotnet/EcencyApi/Infrastructure/NodeHealthTracker.cs[164-203]
dotnet/EcencyApi/Infrastructure/NodeHealthTracker.cs[101-121]
dotnet/EcencyApi/Infrastructure/NodeHealthTracker.cs[125-144]
dotnet/EcencyApi/Infrastructure/NodeHealthTracker.cs[193-203]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
Rate-limit (429) events currently increment `ConsecutiveFailures`, which is the same counter used by the new dead-node hard-parking threshold, causing throttling to contribute to failure-parking decisions.
## Issue Context
429s already have their own independent parking/backoff state (e.g., `RateLimitedUntilMs`), and failure parking is intended to represent a node that is not answering (transport/5xx/etc.). Because both `RecordRateLimited` and `RecordFailure` mutate `ConsecutiveFailures`, and the new threshold is checked when recording a normal failure, sequences that include throttles (e.g., 429s) can incorrectly trigger hard parking and remove a merely rate-limited but responsive node from selection while other nodes exist, potentially even after its rate-limit window expires.
## Fix Focus Areas
- dotnet/EcencyApi/Infrastructure/NodeHealthTracker.cs[101-144]
- dotnet/EcencyApi/Infrastructure/NodeHealthTracker.cs[164-203]
- dotnet/EcencyApi/Infrastructure/HiveRpcClient.cs[204-214]

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


10. SsrRpc.Stats missing parity entry 📘 Rule violation ▣ Testability
Description
/private-api/ssr/stats response now includes new observable fields (slow_fill, nodes) but
there is no corresponding update to the parity divergence documentation as required. This can cause
parity diffs to be unexplained and makes regressions harder to triage.
Code

dotnet/EcencyApi/Handlers/SsrRpc.cs[R467-468]

          ["methods"] = methods,
+            ["nodes"] = Client.HealthSnapshot(),
Relevance

●●● Strong

Recent parity-divergence documentation findings for observable endpoint changes were accepted.

PR-#60
PR-#62

ⓘ Recommendations generated based on similar findings in past PRs

Evidence
The checklist requires parity divergence documentation whenever an endpoint’s HTTP-visible behavior
changes. This PR changes the stats payload by adding nodes (and slow_fill earlier in the same
response), but dotnet/parity/driver.py has no KNOWN_DIVERGENCES entry for
/private-api/ssr/stats cases.

Rule 2667942: Require tests and parity divergence docs for observable endpoint behavior changes
dotnet/EcencyApi/Handlers/SsrRpc.cs[465-469]
dotnet/parity/driver.py[241-259]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
`/private-api/ssr/stats` output contract changed (new `nodes` and method-level `slow_fill`) but there is no documented parity divergence update.
## Issue Context
The parity harness documents deterministic, intentional behavior differences from the Node reference build via `dotnet/parity/driver.py` `KNOWN_DIVERGENCES` (or equivalent). Any HTTP-visible behavior change must be paired with both tests and parity divergence documentation.
## Fix Focus Areas
- dotnet/EcencyApi/Handlers/SsrRpc.cs[450-469]
- dotnet/parity/driver.py[240-269]

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


11. Retries immediately extend parking ✓ Resolved 🐞 Bug ☼ Reliability
Description
Once the third failure creates a 30-second park, HiveRpcClient.Send continues its existing
same-node retry loop and the next failure immediately replaces it with a 60-second park while
incrementing the backoff streak again. With the default failoverThreshold of 2, the initial park
therefore lasts 60 seconds rather than 30, and each post-park probe can issue two attempts instead
of the documented single probe.
Code

dotnet/EcencyApi/Infrastructure/NodeHealthTracker.cs[R118-120]

+                var parkMs = Math.Min(FailureParkBaseMs << Math.Min(h.FailureParkStreak, 2), FailureParkMaxMs);
+                h.FailureParkedUntilMs = now + parkMs;
+                h.FailureParkStreak++;
Relevance

●●● Strong

Retry loop can repeatedly extend parking, contradicting documented single-probe behavior.

PR-#73

ⓘ Recommendations generated based on similar findings in past PRs

Evidence
The tracker reassigns FailureParkedUntilMs and increments FailureParkStreak on every failure at
or above the threshold, without checking whether the node is already parked. Send retries the same
node twice by default and does not recalculate ordering or inspect the newly created park between
attempts; the added tests set failoverThreshold: 1, so they do not cover production's default
behavior.

dotnet/EcencyApi/Infrastructure/NodeHealthTracker.cs[101-121]
dotnet/EcencyApi/Infrastructure/HiveRpcClient.cs[28-41]
dotnet/EcencyApi/Infrastructure/HiveRpcClient.cs[155-225]
dotnet/EcencyApi.Tests/HiveRpcFailoverTests.cs[196-205]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
Failures from retries already in progress repeatedly extend a newly active failure park and advance its backoff streak.
## Issue Context
The node list is selected before the same-node retry loop, so parking a node does not stop the remaining retry. A park should be created or escalated only when no failure park is currently active, or the client should stop retrying once parking is triggered.
## Fix Focus Areas
- dotnet/EcencyApi/Infrastructure/NodeHealthTracker.cs[101-121]
- dotnet/EcencyApi/Infrastructure/HiveRpcClient.cs[155-225]
- dotnet/EcencyApi.Tests/HiveRpcFailoverTests.cs[182-242]

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


View medium (17)
12. Failed slow fills go uncounted ✓ Resolved 🐞 Bug ◔ Observability
Description
slow_fill is incremented only after Client.CallMethod returns successfully, so a fill that
exceeds the lookup budget and then times out or fails never contributes to the new metric. In the
configured SSR client, the default per-node timeout is 1200 ms while the lookup budget is 1500 ms;
failover or a longer configured node timeout readily produces this missing slow-fill observation.
Code

dotnet/EcencyApi/Handlers/SsrRpc.cs[R363-365]

+            var elapsed = Environment.TickCount64 - started;
+            counter.RecordUpstream(elapsed);
+            if (elapsed > BudgetMs) Interlocked.Increment(ref counter.SlowFill);
Relevance

●●● Strong

Recent SsrRpc review history accepts observability/timeout accounting fixes with test coverage.

PR-#73
PR-#74

ⓘ Recommendations generated based on similar findings in past PRs

Evidence
The added increment is sequenced after the awaited upstream call and is bypassed by the surrounding
exception handler. Fill catches that exception and completes the pending task exceptionally, while
Resolve independently records reader timeouts; consequently an over-budget failing fill is not
counted as slow_fill.

dotnet/EcencyApi/Handlers/SsrRpc.cs[315-379]
dotnet/EcencyApi/Handlers/SsrRpc.cs[266-305]
dotnet/EcencyApi/Config.cs[42-50]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
`SlowFill` is updated only on successful RPC results. Record the elapsed fill duration and increment the metric even when the upstream call throws after exceeding the lookup budget.
## Issue Context
The metric is documented as fills that outran the lookup budget. Preserve successful-result caching and existing error handling while ensuring failures/timeouts are represented.
## Fix Focus Areas
- dotnet/EcencyApi/Handlers/SsrRpc.cs[315-379]
- dotnet/EcencyApi/Config.cs[42-50]

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


13. hive-api.arcange.eu in comment 📘 Rule violation ⛨ Security
Description
A real hostname (hive-api.arcange.eu) was added in a code comment, which violates the rule against
hard-coded infrastructure identifiers in code/docs. This can leak operational details into the repo
and complicate compliance/audit reviews.
Code

dotnet/EcencyApi/Infrastructure/HiveRpcClient.cs[R406-408]

+    // hive-api.arcange.eu is absent too: it never completes a TCP connect from
+    // any host this service runs on (SYN, no answer), so every attempt cost the
+    // full per-node timeout and, in bursts, took every in-flight fill with it.
Relevance

●●● Strong

Removing an unneeded real infrastructure hostname from a comment matches repo's no-hardcoded-infra
rule.

ⓘ Recommendations generated based on similar findings in past PRs

Evidence
The checklist forbids hard-coded infrastructure identifiers in code/docs. The added comment
explicitly names a real domain (hive-api.arcange.eu).

Rule 2667957: No hard-coded infrastructure identifiers or secrets in code or docs
dotnet/EcencyApi/Infrastructure/HiveRpcClient.cs[406-408]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
A real infrastructure identifier (the hostname `hive-api.arcange.eu`) was added to a source comment.
## Issue Context
Compliance requires avoiding real/realistic infrastructure identifiers in code and docs. If the rationale for excluding a node must be preserved, prefer a generic description or link to an issue without embedding the hostname.
## Fix Focus Areas
- dotnet/EcencyApi/Infrastructure/HiveRpcClient.cs[406-408]

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


14. Production metric 83 in comment ✓ Resolved 📘 Rule violation ⛨ Security
Description
A specific operational production metric (83 half-open connects) was added in a code comment,
which violates the rule against embedding real infrastructure/capacity details in the repo. This can
unintentionally disclose sensitive operational context.
Code

dotnet/EcencyApi/Infrastructure/NodeHealthTracker.cs[R36-39]

+    // "unexplored" standing: only 429s parked, and a failure demoted for 30s at
+    // most, so each time the leading nodes hiccupped the dead node took the
+    // whole in-flight burst at the full per-node timeout (observed: 83
+    // half-open connects at once to one unreachable node).
Relevance

●●● Strong

Removing a specific production capacity figure from a comment matches repo's infra-detail rule.

ⓘ Recommendations generated based on similar findings in past PRs

Evidence
The checklist disallows explicit traffic/capacity numbers describing production infrastructure. The
new comment includes a specific observed production value (83 half-open connects).

Rule 2667957: No hard-coded infrastructure identifiers or secrets in code or docs
dotnet/EcencyApi/Infrastructure/NodeHealthTracker.cs[33-40]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
A production-observed metric (`83 half-open connects`) is embedded in a source comment.
## Issue Context
Compliance requires avoiding explicit capacity/traffic/operational numbers tied to real infrastructure in code/docs.
## Fix Focus Areas
- dotnet/EcencyApi/Infrastructure/NodeHealthTracker.cs[33-40]

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


15. Rate limits trigger dead parking ✓ Resolved 🐞 Bug ≡ Correctness
Description
The new dead-node parking threshold relies on ConsecutiveFailures, but RecordRateLimited also
increments that counter, so a sequence like two 429s plus one transport/response failure can
hard-park a responsive throttled node for 30 seconds. This conflates the separate rate-limit
backoff/parking state with true consecutive failure detection and can remove an otherwise reachable
fallback even after its rate-limit window ends.
Code

dotnet/EcencyApi/Infrastructure/NodeHealthTracker.cs[R116-120]

+            if (h.ConsecutiveFailures >= FailureParkThreshold)
+            {
+                var parkMs = Math.Min(FailureParkBaseMs << Math.Min(h.FailureParkStreak, 2), FailureParkMaxMs);
+                h.FailureParkedUntilMs = now + parkMs;
+                h.FailureParkStreak++;
Relevance

●●● Strong

Shared failure streak conflates rate limits with real failures, undermining new parking feature
intent.

PR-#73

ⓘ Recommendations generated based on similar findings in past PRs

Evidence
In HiveRpcClient, HTTP 429 outcomes are routed to RecordRateLimited, while other unavailable
outcomes go to RecordFailure. Both of these paths mutate the shared ConsecutiveFailures counter
in NodeHealthTracker, and the newly added hard-parking threshold is evaluated on the next
RecordFailure. As a result, a 429 can advance the same streak that is intended to represent
consecutive ordinary failures, allowing a later normal failure to trigger hard parking and node
exclusion even though the node’s only “streak” includes throttling events, despite the
code/documentation treating throttled nodes as a distinct, potentially usable state with separate
backoff (RateLimitedUntilMs).

dotnet/EcencyApi/Infrastructure/HiveRpcClient.cs[204-214]
dotnet/EcencyApi/Infrastructure/NodeHealthTracker.cs[101-144]
dotnet/EcencyApi/Infrastructure/NodeHealthTracker.cs[164-203]
dotnet/EcencyApi/Infrastructure/NodeHealthTracker.cs[101-121]
dotnet/EcencyApi/Infrastructure/NodeHealthTracker.cs[125-144]
dotnet/EcencyApi/Infrastructure/NodeHealthTracker.cs[193-203]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
Rate-limit (429) events currently increment `ConsecutiveFailures`, which is the same counter used by the new dead-node hard-parking threshold, causing throttling to contribute to failure-parking decisions.
## Issue Context
429s already have their own independent parking/backoff state (e.g., `RateLimitedUntilMs`), and failure parking is intended to represent a node that is not answering (transport/5xx/etc.). Because both `RecordRateLimited` and `RecordFailure` mutate `ConsecutiveFailures`, and the new threshold is checked when recording a normal failure, sequences that include throttles (e.g., 429s) can incorrectly trigger hard parking and remove a merely rate-limited but responsive node from selection while other nodes exist, potentially even after its rate-limit window expires.
## Fix Focus Areas
- dotnet/EcencyApi/Infrastructure/NodeHealthTracker.cs[101-144]
- dotnet/EcencyApi/Infrastructure/NodeHealthTracker.cs[164-203]
- dotnet/EcencyApi/Infrastructure/HiveRpcClient.cs[204-214]

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


16. SsrRpc.Stats missing parity entry 📘 Rule violation ▣ Testability
Description
/private-api/ssr/stats response now includes new observable fields (slow_fill, nodes) but
there is no corresponding update to the parity divergence documentation as required. This can cause
parity diffs to be unexplained and makes regressions harder to triage.
Code

dotnet/EcencyApi/Handlers/SsrRpc.cs[R467-468]

         ["methods"] = methods,
+            ["nodes"] = Client.HealthSnapshot(),
Relevance

●●● Strong

Recent parity-divergence documentation findings for observable endpoint changes were accepted.

PR-#60
PR-#62

ⓘ Recommendations generated based on similar findings in past PRs

Evidence
The checklist requires parity divergence documentation whenever an endpoint’s HTTP-visible behavior
changes. This PR changes the stats payload by adding nodes (and slow_fill earlier in the same
response), but dotnet/parity/driver.py has no KNOWN_DIVERGENCES entry for
/private-api/ssr/stats cases.

Rule 2667942: Require tests and parity divergence docs for observable endpoint behavior changes
dotnet/EcencyApi/Handlers/SsrRpc.cs[465-469]
dotnet/parity/driver.py[241-259]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
`/private-api/ssr/stats` output contract changed (new `nodes` and method-level `slow_fill`) but there is no documented parity divergence update.
## Issue Context
The parity harness documents deterministic, intentional behavior differences from the Node reference build via `dotnet/parity/driver.py` `KNOWN_DIVERGENCES` (or equivalent). Any HTTP-visible behavior change must be paired with both tests and parity divergence documentation.
## Fix Focus Areas
- dotnet/EcencyApi/Handlers/SsrRpc.cs[450-469]
- dotnet/parity/driver.py[240-269]

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


17. Retries immediately extend parking ✓ Resolved 🐞 Bug ☼ Reliability
Description
Once the third failure creates a 30-second park, HiveRpcClient.Send continues its existing
same-node retry loop and the next failure immediately replaces it with a 60-second park while
incrementing the backoff streak again. With the default failoverThreshold of 2, the initial park
therefore lasts 60 seconds rather than 30, and each post-park probe can issue two attempts instead
of the documented single probe.
Code

dotnet/EcencyApi/Infrastructure/NodeHealthTracker.cs[R118-120]

+                var parkMs = Math.Min(FailureParkBaseMs << Math.Min(h.FailureParkStreak, 2), FailureParkMaxMs);
+                h.FailureParkedUntilMs = now + parkMs;
+                h.FailureParkStreak++;
Relevance

●●● Strong

Retry loop can repeatedly extend parking, contradicting documented single-probe behavior.

PR-#73

ⓘ Recommendations generated based on similar findings in past PRs

Evidence
The tracker reassigns FailureParkedUntilMs and increments FailureParkStreak on every failure at
or above the threshold, without checking whether the node is already parked. Send retries the same
node twice by default and does not recalculate ordering or inspect the newly created park between
attempts; the added tests set failoverThreshold: 1, so they do not cover production's default
behavior.

dotnet/EcencyApi/Infrastructure/NodeHealthTracker.cs[101-121]
dotnet/EcencyApi/Infrastructure/HiveRpcClient.cs[28-41]
dotnet/EcencyApi/Infrastructure/HiveRpcClient.cs[155-225]
dotnet/EcencyApi.Tests/HiveRpcFailoverTests.cs[196-205]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
Failures from retries already in progress repeatedly extend a newly active failure park and advance its backoff streak.
## Issue Context
The node list is selected before the same-node retry loop, so parking a node does not stop the remaining retry. A park should be created or escalated only when no failure park is currently active, or the client should stop retrying once parking is triggered.
## Fix Focus Areas
- dotnet/EcencyApi/Infrastructure/NodeHealthTracker.cs[101-121]
- dotnet/EcencyApi/Infrastructure/HiveRpcClient.cs[155-225]
- dotnet/EcencyApi.Tests/HiveRpcFailoverTests.cs[182-242]

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


18. Failed slow fills go uncounted ✓ Resolved 🐞 Bug ◔ Observability
Description
slow_fill is incremented only after Client.CallMethod returns successfully, so a fill that
exceeds the lookup budget and then times out or fails never contributes to the new metric. In the
configured SSR client, the default per-node timeout is 1200 ms while the lookup budget is 1500 ms;
failover or a longer configured node timeout readily produces this missing slow-fill observation.
Code

dotnet/EcencyApi/Handlers/SsrRpc.cs[R363-365]

+            var elapsed = Environment.TickCount64 - started;
+            counter.RecordUpstream(elapsed);
+            if (elapsed > BudgetMs) Interlocked.Increment(ref counter.SlowFill);
Relevance

●●● Strong

Recent SsrRpc review history accepts observability/timeout accounting fixes with test coverage.

PR-#73
PR-#74

ⓘ Recommendations generated based on similar findings in past PRs

Evidence
The added increment is sequenced after the awaited upstream call and is bypassed by the surrounding
exception handler. Fill catches that exception and completes the pending task exceptionally, while
Resolve independently records reader timeouts; consequently an over-budget failing fill is not
counted as slow_fill.

dotnet/EcencyApi/Handlers/SsrRpc.cs[315-379]
dotnet/EcencyApi/Handlers/SsrRpc.cs[266-305]
dotnet/EcencyApi/Config.cs[42-50]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## ...

Comment thread dotnet/EcencyApi/Handlers/SsrRpc.cs
Comment thread dotnet/EcencyApi/Infrastructure/HiveRpcClient.cs
Comment thread dotnet/EcencyApi/Infrastructure/NodeHealthTracker.cs Outdated
Comment thread dotnet/EcencyApi/Infrastructure/NodeHealthTracker.cs Outdated
Comment thread dotnet/EcencyApi/Infrastructure/NodeHealthTracker.cs
Comment thread dotnet/EcencyApi/Infrastructure/NodeHealthTracker.cs
Comment thread dotnet/EcencyApi/Infrastructure/NodeHealthTracker.cs Outdated
Comment thread dotnet/EcencyApi/Handlers/SsrRpc.cs Outdated
@qodo-free-for-open-source-projects

Copy link
Copy Markdown

Code Review by Qodo

🐞 Bugs (2) 📘 Rule violations (2) 📎 Requirement gaps (0) 📜 Skill insights (0)

Grey Divider


Action required

1. Parking permits probe bursts 🐞 Bug ☼ Reliability ⭐ New
Description
Send materializes node ordering once, so concurrent requests that start just after a dead node's
park expires all retain that node and probe it after a leader failure even after the first probes
re-park it. This recreates the burst of half-open connections that failure parking is intended to
prevent.
Code

dotnet/EcencyApi/Infrastructure/NodeHealthTracker.cs[R193-195]

+            if (ranked.Any(x => !x.Dead))
+            {
+                ranked.RemoveAll(x => x.Dead);
Evidence
The client obtains one materialized ordering and never refreshes it while trying nodes. Failure
recording can re-park the node, but only future calls to OrderedNodeIndices observe the filter;
the new tests exercise this flow sequentially rather than with concurrent requests.

dotnet/EcencyApi/Infrastructure/HiveRpcClient.cs[155-159]
dotnet/EcencyApi/Infrastructure/HiveRpcClient.cs[204-225]
dotnet/EcencyApi/Infrastructure/NodeHealthTracker.cs[101-121]
dotnet/EcencyApi/Infrastructure/NodeHealthTracker.cs[173-203]
dotnet/EcencyApi.Tests/HiveRpcFailoverTests.cs[182-242]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
Failure-park filtering only runs when a request initially obtains its ordered node list. Concurrent requests can retain a newly re-parked node in stale lists and all probe it, recreating a connection burst.

## Issue Context
Node ordering is materialized once per RPC call. Parking updates made by one request therefore do not affect other requests already iterating their lists, and an expired park has no atomic single-probe/half-open gate.

## Fix Focus Areas
- dotnet/EcencyApi/Infrastructure/NodeHealthTracker.cs[173-203]
- dotnet/EcencyApi/Infrastructure/HiveRpcClient.cs[155-225]
- dotnet/EcencyApi.Tests/HiveRpcFailoverTests.cs[182-242]

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


2. Success leaves node parked ✓ Resolved 🐞 Bug ☼ Reliability
Description
RecordSuccess resets the failure-park streak but leaves FailureParkedUntilMs active, so a node
that succeeds when an all-parked pool is offered can still be excluded on the next call as soon as
any other node's park expires. This can suppress a just-proven healthy node and fail requests
through a worse node until the stale park deadline lapses.
Code

dotnet/EcencyApi/Infrastructure/NodeHealthTracker.cs[93]

+            h.FailureParkStreak = 0;
Relevance

●●● Strong

Concrete node-health state bug; similar tracker correctness fixes were accepted recently.

PR-#73

ⓘ Recommendations generated based on similar findings in past PRs

Evidence
All-parked pools deliberately return every node from OrderedNodeIndices, allowing an actively
parked node to succeed. RecordSuccess clears counters but not FailureParkedUntilMs; later
ordering defines deadness solely from that deadline and removes the recovered node whenever another
node is no longer parked.

dotnet/EcencyApi/Infrastructure/NodeHealthTracker.cs[84-95]
dotnet/EcencyApi/Infrastructure/NodeHealthTracker.cs[178-203]
dotnet/EcencyApi.Tests/HiveRpcFailoverTests.cs[244-260]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
A successful call resets the failure streak but does not clear the active failure-park deadline.
## Issue Context
Failure-parked nodes are attempted when every node is parked, so success during an active park is reachable and should immediately restore that node to normal ordering.
## Fix Focus Areas
- dotnet/EcencyApi/Infrastructure/NodeHealthTracker.cs[84-95]
- dotnet/EcencyApi/Infrastructure/NodeHealthTracker.cs[173-203]
- dotnet/EcencyApi.Tests/HiveRpcFailoverTests.cs[244-260]

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


3. Short timeouts improve dead ranking ✓ Resolved 🐞 Bug ≡ Correctness
Description
RecordFailure records the raw timeout duration as latency, so a valid timeout below the 1,000 ms
unproven prior gives an unreachable node a better score than every untouched node once its park
lapses. For example, the supported 300 ms timeout produces an approximately 300 ms score and causes
the dead node to be retried before unproven alternatives, undermining the intended demotion.
Code

dotnet/EcencyApi/Infrastructure/NodeHealthTracker.cs[R112-114]

+            if (timedOut || elapsedMs >= SlowFailureFloorMs)
           {
               RecordLatency(h, elapsedMs);
Relevance

●●● Strong

Concrete ranking inversion in new health logic; recent tracker latency fixes were accepted.

PR-#73

ⓘ Recommendations generated based on similar findings in past PRs

Evidence
Timeouts are newly passed into RecordFailure, which records their elapsed duration
unconditionally; ordering then compares that EWMA ascending against a fixed 1,000 ms score for
unproven nodes. The constructor accepts any positive configured timeout, and the new tests
themselves exercise a 300 ms timeout, proving this score inversion is reachable.

dotnet/EcencyApi/Infrastructure/HiveRpcClient.cs[204-214]
dotnet/EcencyApi/Infrastructure/NodeHealthTracker.cs[28-32]
dotnet/EcencyApi/Infrastructure/NodeHealthTracker.cs[101-115]
dotnet/EcencyApi/Infrastructure/NodeHealthTracker.cs[186-200]
dotnet/EcencyApi/Config.cs[48-50]
dotnet/EcencyApi.Tests/HiveRpcFailoverTests.cs[196-214]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
Timeout samples below the neutral latency prior currently improve an unreachable node's ordering instead of demoting it.
## Issue Context
Node ordering is ascending by latency score, and untouched nodes use a 1,000 ms prior. Valid configured/test timeouts may be shorter than that.
## Fix Focus Areas
- dotnet/EcencyApi/Infrastructure/NodeHealthTracker.cs[101-115]
- dotnet/EcencyApi/Infrastructure/NodeHealthTracker.cs[186-200]
- dotnet/EcencyApi.Tests/HiveRpcFailoverTests.cs[182-242]

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools



Remediation recommended

4. Failed slow fills omitted 🐞 Bug ◔ Observability ⭐ New
Description
Fill increments SlowFill only after Client.CallMethod succeeds, so an upstream attempt that
exceeds BudgetMs, times out its readers, and then throws is never counted as a slow fill. The
stats consequently underreport the slow upstream work responsible for waiter timeouts whenever that
work ends unsuccessfully.
Code

dotnet/EcencyApi/Handlers/SsrRpc.cs[R363-365]

+            var elapsed = Environment.TickCount64 - started;
+            counter.RecordUpstream(elapsed);
+            if (elapsed > BudgetMs) Interlocked.Increment(ref counter.SlowFill);
Evidence
Readers independently return timeout while the detached fill remains active, but elapsed time and
SlowFill are recorded only after the RPC task returns normally. The exception path bypasses both
statements and only faults the pending task.

dotnet/EcencyApi/Handlers/SsrRpc.cs[266-305]
dotnet/EcencyApi/Handlers/SsrRpc.cs[355-373]
dotnet/EcencyApi/Infrastructure/HiveRpcClient.cs[142-235]
dotnet/EcencyApi.Tests/SsrRpcTests.cs[439-470]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
Slow-fill accounting runs only on successful upstream completion. Over-budget fills that eventually throw can produce reader timeouts but never increment `slow_fill`.

## Issue Context
Start timing only after a fill acquires the gate, then ensure the elapsed-budget check runs for both successful and exceptional completion of the upstream call. Queue rejection and pre-call cache hits should not be counted as upstream slow fills.

## Fix Focus Areas
- dotnet/EcencyApi/Handlers/SsrRpc.cs[315-379]
- dotnet/EcencyApi.Tests/SsrRpcTests.cs[439-477]

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


5. Rate limits trigger dead parking ✓ Resolved 🐞 Bug ≡ Correctness
Description
The new dead-node parking threshold relies on ConsecutiveFailures, but RecordRateLimited also
increments that counter, so a sequence like two 429s plus one transport/response failure can
hard-park a responsive throttled node for 30 seconds. This conflates the separate rate-limit
backoff/parking state with true consecutive failure detection and can remove an otherwise reachable
fallback even after its rate-limit window ends.
Code

dotnet/EcencyApi/Infrastructure/NodeHealthTracker.cs[R116-120]

+            if (h.ConsecutiveFailures >= FailureParkThreshold)
+            {
+                var parkMs = Math.Min(FailureParkBaseMs << Math.Min(h.FailureParkStreak, 2), FailureParkMaxMs);
+                h.FailureParkedUntilMs = now + parkMs;
+                h.FailureParkStreak++;
Relevance

●●● Strong

Shared failure streak conflates rate limits with real failures, undermining new parking feature
intent.

PR-#73

ⓘ Recommendations generated based on similar findings in past PRs

Evidence
In HiveRpcClient, HTTP 429 outcomes are routed to RecordRateLimited, while other unavailable
outcomes go to RecordFailure. Both of these paths mutate the shared ConsecutiveFailures counter
in NodeHealthTracker, and the newly added hard-parking threshold is evaluated on the next
RecordFailure. As a result, a 429 can advance the same streak that is intended to represent
consecutive ordinary failures, allowing a later normal failure to trigger hard parking and node
exclusion even though the node’s only “streak” includes throttling events, despite the
code/documentation treating throttled nodes as a distinct, potentially usable state with separate
backoff (RateLimitedUntilMs).

dotnet/EcencyApi/Infrastructure/HiveRpcClient.cs[204-214]
dotnet/EcencyApi/Infrastructure/NodeHealthTracker.cs[101-144]
dotnet/EcencyApi/Infrastructure/NodeHealthTracker.cs[164-203]
dotnet/EcencyApi/Infrastructure/NodeHealthTracker.cs[101-121]
dotnet/EcencyApi/Infrastructure/NodeHealthTracker.cs[125-144]
dotnet/EcencyApi/Infrastructure/NodeHealthTracker.cs[193-203]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
Rate-limit (429) events currently increment `ConsecutiveFailures`, which is the same counter used by the new dead-node hard-parking threshold, causing throttling to contribute to failure-parking decisions.
## Issue Context
429s already have their own independent parking/backoff state (e.g., `RateLimitedUntilMs`), and failure parking is intended to represent a node that is not answering (transport/5xx/etc.). Because both `RecordRateLimited` and `RecordFailure` mutate `ConsecutiveFailures`, and the new threshold is checked when recording a normal failure, sequences that include throttles (e.g., 429s) can incorrectly trigger hard parking and remove a merely rate-limited but responsive node from selection while other nodes exist, potentially even after its rate-limit window expires.
## Fix Focus Areas
- dotnet/EcencyApi/Infrastructure/NodeHealthTracker.cs[101-144]
- dotnet/EcencyApi/Infrastructure/NodeHealthTracker.cs[164-203]
- dotnet/EcencyApi/Infrastructure/HiveRpcClient.cs[204-214]

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


6. SsrRpc.Stats missing parity entry 📘 Rule violation ▣ Testability
Description
/private-api/ssr/stats response now includes new observable fields (slow_fill, nodes) but
there is no corresponding update to the parity divergence documentation as required. This can cause
parity diffs to be unexplained and makes regressions harder to triage.
Code

dotnet/EcencyApi/Handlers/SsrRpc.cs[R467-468]

           ["methods"] = methods,
+            ["nodes"] = Client.HealthSnapshot(),
Relevance

●●● Strong

Recent parity-divergence documentation findings for observable endpoint changes were accepted.

PR-#60
PR-#62

ⓘ Recommendations generated based on similar findings in past PRs

Evidence
The checklist requires parity divergence documentation whenever an endpoint’s HTTP-visible behavior
changes. This PR changes the stats payload by adding nodes (and slow_fill earlier in the same
response), but dotnet/parity/driver.py has no KNOWN_DIVERGENCES entry for
/private-api/ssr/stats cases.

Rule 2667942: Require tests and parity divergence docs for observable endpoint behavior changes
dotnet/EcencyApi/Handlers/SsrRpc.cs[465-469]
dotnet/parity/driver.py[241-259]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
`/private-api/ssr/stats` output contract changed (new `nodes` and method-level `slow_fill`) but there is no documented parity divergence update.
## Issue Context
The parity harness documents deterministic, intentional behavior differences from the Node reference build via `dotnet/parity/driver.py` `KNOWN_DIVERGENCES` (or equivalent). Any HTTP-visible behavior change must be paired with both tests and parity divergence documentation.
## Fix Focus Areas
- dotnet/EcencyApi/Handlers/SsrRpc.cs[450-469]
- dotnet/parity/driver.py[240-269]

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


View medium (4)
7. Retries immediately extend parking ✓ Resolved 🐞 Bug ☼ Reliability
Description
Once the third failure creates a 30-second park, HiveRpcClient.Send continues its existing
same-node retry loop and the next failure immediately replaces it with a 60-second park while
incrementing the backoff streak again. With the default failoverThreshold of 2, the initial park
therefore lasts 60 seconds rather than 30, and each post-park probe can issue two attempts instead
of the documented single probe.
Code

dotnet/EcencyApi/Infrastructure/NodeHealthTracker.cs[R118-120]

+                var parkMs = Math.Min(FailureParkBaseMs << Math.Min(h.FailureParkStreak, 2), FailureParkMaxMs);
+                h.FailureParkedUntilMs = now + parkMs;
+                h.FailureParkStreak++;
Relevance

●●● Strong

Retry loop can repeatedly extend parking, contradicting documented single-probe behavior.

PR-#73

ⓘ Recommendations generated based on similar findings in past PRs

Evidence
The tracker reassigns FailureParkedUntilMs and increments FailureParkStreak on every failure at
or above the threshold, without checking whether the node is already parked. Send retries the same
node twice by default and does not recalculate ordering or inspect the newly created park between
attempts; the added tests set failoverThreshold: 1, so they do not cover production's default
behavior.

dotnet/EcencyApi/Infrastructure/NodeHealthTracker.cs[101-121]
dotnet/EcencyApi/Infrastructure/HiveRpcClient.cs[28-41]
dotnet/EcencyApi/Infrastructure/HiveRpcClient.cs[155-225]
dotnet/EcencyApi.Tests/HiveRpcFailoverTests.cs[196-205]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
Failures from retries already in progress repeatedly extend a newly active failure park and advance its backoff streak.
## Issue Context
The node list is selected before the same-node retry loop, so parking a node does not stop the remaining retry. A park should be created or escalated only when no failure park is currently active, or the client should stop retrying once parking is triggered.
## Fix Focus Areas
- dotnet/EcencyApi/Infrastructure/NodeHealthTracker.cs[101-121]
- dotnet/EcencyApi/Infrastructure/HiveRpcClient.cs[155-225]
- dotnet/EcencyApi.Tests/HiveRpcFailoverTests.cs[182-242]

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


8. Failed slow fills go uncounted ✓ Resolved 🐞 Bug ◔ Observability
Description
slow_fill is incremented only after Client.CallMethod returns successfully, so a fill that
exceeds the lookup budget and then times out or fails never contributes to the new metric. In the
configured SSR client, the default per-node timeout is 1200 ms while the lookup budget is 1500 ms;
failover or a longer configured node timeout readily produces this missing slow-fill observation.
Code

dotnet/EcencyApi/Handlers/SsrRpc.cs[R363-365]

+            var elapsed = Environment.TickCount64 - started;
+            counter.RecordUpstream(elapsed);
+            if (elapsed > BudgetMs) Interlocked.Increment(ref counter.SlowFill);
Relevance

●●● Strong

Recent SsrRpc review history accepts observability/timeout accounting fixes with test coverage.

PR-#73
PR-#74

ⓘ Recommendations generated based on similar findings in past PRs

Evidence
The added increment is sequenced after the awaited upstream call and is bypassed by the surrounding
exception handler. Fill catches that exception and completes the pending task exceptionally, while
Resolve independently records reader timeouts; consequently an over-budget failing fill is not
counted as slow_fill.

dotnet/EcencyApi/Handlers/SsrRpc.cs[315-379]
dotnet/EcencyApi/Handlers/SsrRpc.cs[266-305]
dotnet/EcencyApi/Config.cs[42-50]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
`SlowFill` is updated only on successful RPC results. Record the elapsed fill duration and increment the metric even when the upstream call throws after exceeding the lookup budget.
## Issue Context
The metric is documented as fills that outran the lookup budget. Preserve successful-result caching and existing error handling while ensuring failures/timeouts are represented.
## Fix Focus Areas
- dotnet/EcencyApi/Handlers/SsrRpc.cs[315-379]
- dotnet/EcencyApi/Config.cs[42-50]

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


9. hive-api.arcange.eu in comment 📘 Rule violation ⛨ Security
Description
A real hostname (hive-api.arcange.eu) was added in a code comment, which violates the rule against
hard-coded infrastructure identifiers in code/docs. This can leak operational details into the repo
and complicate compliance/audit reviews.
Code

dotnet/EcencyApi/Infrastructure/HiveRpcClient.cs[R406-408]

+    // hive-api.arcange.eu is absent too: it never completes a TCP connect from
+    // any host this service runs on (SYN, no answer), so every attempt cost the
+    // full per-node timeout and, in bursts, took every in-flight fill with it.
Relevance

●●● Strong

Removing an unneeded real infrastructure hostname from a comment matches repo's no-hardcoded-infra
rule.

ⓘ Recommendations generated based on similar findings in past PRs

Evidence
The checklist forbids hard-coded infrastructure identifiers in code/docs. The added comment
explicitly names a real domain (hive-api.arcange.eu).

Rule 2667957: No hard-coded infrastructure identifiers or secrets in code or docs
dotnet/EcencyApi/Infrastructure/HiveRpcClient.cs[406-408]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
A real infrastructure identifier (the hostname `hive-api.arcange.eu`) was added to a source comment.
## Issue Context
Compliance requires avoiding real/realistic infrastructure identifiers in code and docs. If the rationale for excluding a node must be preserved, prefer a generic description or link to an issue without embedding the hostname.
## Fix Focus Areas
- dotnet/EcencyApi/Infrastructure/HiveRpcClient.cs[406-408]

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


10. Production metric 83 in comment ✓ Resolved 📘 Rule violation ⛨ Security
Description
A specific operational production metric (83 half-open connects) was added in a code comment,
which violates the rule against embedding real infrastructure/capacity details in the repo. This can
unintentionally disclose sensitive operational context.
Code

dotnet/EcencyApi/Infrastructure/NodeHealthTracker.cs[R36-39]

+    // "unexplored" standing: only 429s parked, and a failure demoted for 30s at
+    // most, so each time the leading nodes hiccupped the dead node took the
+    // whole in-flight burst at the full per-node timeout (observed: 83
+    // half-open connects at once to one unreachable node).
Relevance

●●● Strong

Removing a specific production capacity figure from a comment matches repo's infra-detail rule.

ⓘ Recommendations generated based on similar findings in past PRs

Evidence
The checklist disallows explicit traffic/capacity numbers describing production infrastructure. The
new comment includes a specific observed production value (83 half-open connects).

Rule 2667957: No hard-coded infrastructure identifiers or secrets in code or docs
dotnet/EcencyApi/Infrastructure/NodeHealthTracker.cs[33-40]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
A production-observed metric (`83 half-open connects`) is embedded in a source comment.
## Issue Context
Compliance requires avoiding explicit capacity/traffic/operational numbers tied to real infrastructure in code/docs.
## Fix Focus Areas
- dotnet/EcencyApi/Infrastructure/NodeHealthTracker.cs[33-40]

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


Grey Divider

Context sources
Review mode: 🧠 Deep: This is a behavior-heavy RPC failover and health-state change spanning client logic, node ranking/parking, timeout accounting, stats API, and tests, with many independent paths where subtle defects could be missed in one pass.

Grey Divider

Tip of the day
💡 Did you know, you can tweak Display preferences with a live preview to see your comment before it ships

More tips ↗ | Customize Qodo ↗ | Qodo docs ↗

Grey Divider

Qodo Logo

Comment thread dotnet/EcencyApi/Infrastructure/NodeHealthTracker.cs
Comment thread dotnet/EcencyApi/Handlers/SsrRpc.cs Outdated
@feruzm
feruzm merged commit 92cc3f8 into main Aug 21, 2026
4 checks passed
@feruzm
feruzm deleted the fix/ssr-rpc-pool-hygiene branch August 21, 2026 16:45
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.

SSR RPC cache: drop the unreachable pool node and expose per-node health in stats

1 participant