Skip to content

fix(chunk-post): key sorted-peer memo by set, not length#804

Closed
vilenarios wants to merge 1 commit into
developfrom
fix/chunk-post-peer-memo-key
Closed

fix(chunk-post): key sorted-peer memo by set, not length#804
vilenarios wants to merge 1 commit into
developfrom
fix/chunk-post-peer-memo-key

Conversation

@vilenarios

Copy link
Copy Markdown
Contributor

What

ArweaveCompositeClient.getSortedChunkPostPeers memoizes its weighted peer ordering with a normalizer of eligiblePeers.length. Two different eligible-peer sets of equal size therefore share one cached ordering for the full CHUNK_POST_SORTED_PEERS_CACHE_DURATION_MS window (10s default).

This keys the memo by the set of peer ids instead (order-independent slice().sort().join()).

Why it matters

The length-only key quietly narrows chunk-POST seeding diversity: a churning-but-same-size peer set keeps reusing the first set's ordering, so the same peers get prioritized for up to 10s even as the eligible set changes. For a gateway whose job is to be a good seeding target, fanout diversity is exactly what we don't want to silently pin.

Surfaced during an architecture review of chunk fanout (the broader durability work concluded the gateway should optimize fanout quality, not duplicate the bundler's durability engine — this is one of those quality fixes).

Cost

Still cheap: one sort+join over the bounded postChunk peer set (tens–low hundreds of entries), far less than the weighted selectPeers + filtering the memo guards. The 10s maxAge still absorbs gradual weight drift. Does not mutate the caller's array.

Tests

Extracted the keying as the pure, exported chunkPostPeersCacheKey and unit-tested it directly:

  • distinct same-length sets ⇒ distinct keys (the bug)
  • order-independent for the same set
  • no input mutation
  • empty set

yarn test:file src/arweave/composite-client.test.ts → 15/15 pass; eslint clean.

🤖 Generated with Claude Code

getSortedChunkPostPeers memoized its weighted peer ordering with a normalizer
of `eligiblePeers.length`, so two *different* eligible-peer sets of equal size
shared one cached ordering for the full CHUNK_POST_SORTED_PEERS_CACHE_DURATION_MS
window (10s default). That quietly narrowed chunk-POST seeding diversity: a
churning-but-same-size peer set kept reusing the first set's ordering.

Key by the set of peer ids instead (order-independent sort+join). Still cheap —
a sort+join over the bounded postChunk peer set, far less than the weighted
selection it guards — and the 10s maxAge still absorbs gradual weight drift.

Extracted as the pure, exported `chunkPostPeersCacheKey` so the keying is
unit-tested directly (distinct same-length sets ⇒ distinct keys; order-
independent; no input mutation; empty set).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01XQPK4TXcVoXoyFp6sNW2Lr
@coderabbitai

coderabbitai Bot commented Jun 29, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro

Run ID: 0fe8dbe4-b95b-40d3-8970-df6889e570ae

📥 Commits

Reviewing files that changed from the base of the PR and between 55ef923 and d43b86b.

📒 Files selected for processing (2)
  • src/arweave/composite-client.test.ts
  • src/arweave/composite-client.ts

📝 Walkthrough

Walkthrough

Adds an exported chunkPostPeersCacheKey helper that generates a stable, order-independent memoization key by sorting a copy of the peer list and joining it. Updates getSortedChunkPostPeers to use this key instead of eligiblePeers.length, and adds tests covering collision-avoidance, order-independence, non-mutation, and empty input.

Peer memoization key fix

Layer / File(s) Summary
chunkPostPeersCacheKey helper and memoizer update
src/arweave/composite-client.ts
Exports chunkPostPeersCacheKey that sorts a copy of the peer array and joins it; updates the getSortedChunkPostPeers normalizer to use this set-based key instead of eligiblePeers.length.
Tests for chunkPostPeersCacheKey
src/arweave/composite-client.test.ts
Adds import and a describe block verifying no same-length collisions, order-independence, no input mutation, and empty-string result for an empty peer array.

Estimated code review effort

🎯 1 (Trivial) | ⏱️ ~5 minutes

Possibly related PRs

  • ar-io/ar-io-node#445: Introduced the memoized peer sorting architecture in composite-client.ts that this PR's memoization key fix directly targets.
  • ar-io/ar-io-node#468: Modifies the preferred-vs-non-preferred peer ordering logic inside the same getSortedChunkPostPeers function updated here.

Suggested reviewers

  • djwhitt
🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly summarizes the main change: switching chunk-post peer memoization from length-based to set-based keying.
Description check ✅ Passed The description accurately matches the changeset and explains the bug, fix, and tests.
Docstring Coverage ✅ Passed Docstring coverage is 100.00% which is sufficient. The required threshold is 80.00%.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch fix/chunk-post-peer-memo-key

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.

@codecov

codecov Bot commented Jun 29, 2026

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 78.76%. Comparing base (96ede32) to head (d43b86b).
⚠️ Report is 17 commits behind head on develop.

Additional details and impacted files
@@             Coverage Diff             @@
##           develop     #804      +/-   ##
===========================================
+ Coverage    78.65%   78.76%   +0.11%     
===========================================
  Files          132      132              
  Lines        49980    50109     +129     
  Branches      3763     3781      +18     
===========================================
+ Hits         39312    39470     +158     
+ Misses       10620    10591      -29     
  Partials        48       48              

☔ View full report in Codecov by Harness.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

@vilenarios

Copy link
Copy Markdown
Contributor Author

Superseded by #812 — consolidated into the feature/chunk-fanout integration branch (F + B1 + B2 + dashboard as one coherent PR). All commits from this branch are included there; closing to review as a unit.

@vilenarios vilenarios closed this Jul 1, 2026
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