Skip to content

[TENT] Add bounded receiver-credit control protocol model#2861

Open
catyans wants to merge 24 commits into
kvcache-ai:mainfrom
catyans:feat/receiver-credit-control-model
Open

[TENT] Add bounded receiver-credit control protocol model#2861
catyans wants to merge 24 commits into
kvcache-ai:mainfrom
catyans:feat/receiver-credit-control-model

Conversation

@catyans

@catyans catyans commented Jul 11, 2026

Copy link
Copy Markdown
Collaborator

Summary

Adds the transport-neutral control protocol model for receiver-owned credits proposed in #2849. This is a stacked Draft and depends on #2860; the overlapping ledger commits disappear from this diff after #2860 merges.

This PR adds:

  • Optional/Required capability negotiation with explicit Active/Legacy/Stale/Failed states;
  • bounded, strict network-byte-order codecs for capability offers, activation responses, and cumulative credit updates;
  • activation metadata carrying chosen version, receiver session, restart epoch, and freshness TTL;
  • a bounded (target_id, qos_class) peer-context table with restart fencing and exact cleanup;
  • a nonblocking ingress adapter that validates session/QoS/epoch before bounded enqueue;
  • explicit retryable queue-full behavior;
  • deterministic fault, malformed-wire, concurrency, restart, and mixed-version tests;
  • a manual typed-RPC harness used for cross-host validation.

Scope boundary

This Draft intentionally does not allocate a production ControlService RPC ID or choose receiver-push versus sender-pull. The current CoroRpcAgent handler does not expose caller identity, so receiver-push requires an explicit sender binding in the wire contract; sender-pull has different polling semantics. That choice is requested in #2849.

Also excluded:

  • Admission/dispatch gating;
  • public Request API changes or priority-to-QoS mapping;
  • background threads;
  • default runtime behavior changes.

Key invariants

  • malformed, truncated, oversized, duplicate-field, unknown-resource, wrong-session, wrong-QoS, and wrong-epoch messages fail before enqueue;
  • queue saturation is visible and retryable, never a silent drop;
  • receiver restart replaces the peer context atomically; stale cleanup cannot erase a newer session;
  • concurrent restart/read cannot tear session and epoch snapshots;
  • Optional peers can fall back to Legacy while Required peers fail closed;
  • all state and wire sizes are bounded.

Cluster validation

No local-to-remote file copy was used; cluster nodes fetched the branch directly.

  • lingjun-100 explicit Release: repeated focused suite 1000/1000 PASS;
  • lingjun-102 independent clean clone explicit Release: repeated focused suite 1000/1000 PASS;
  • ASan + LeakSanitizer: PASS;
  • TSan, including 10,000 receiver restarts with 16 concurrent readers: PASS;
  • CUDA-enabled tent_runtime build: PASS;
  • malformed-wire long run: approximately 100M inputs plus 32M concurrent queue events, PASS;
  • cross-host 16-client slow receiver: accepted=16000 queue_full=53754 invalid=0 available=16000, all processes exit 0;
  • cross-host mixed-version negotiation:
    • {2,1} + Required -> Active v1;
    • {2} + Optional -> Legacy;
    • {2} + Required -> Failed;
      all RPC servers report DONE=0 calls=1 invalid=0.

Test plan

cmake --build build --target receiver_credit_control_test receiver_credit_rpc_harness
ctest --test-dir build -R receiver_credit_control_test --output-on-failure

Depends on #2860. Related RFC: #2849.

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

Copy link
Copy Markdown
Contributor

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 introduces a receiver credit flow control mechanism for the mooncake transfer engine, including the SenderCreditLedger for tracking resource grants and reservations, and control-plane components for capability negotiation, session activation, and message serialization. The feedback highlights a critical security issue in CreditPeerContextTable::activate where a session could be hijacked by a different sender peer if the epoch increases without validating the sender's identity. Additionally, it is recommended to use a 64-bit hash mixing constant in LookupKeyHash for consistency and improved hash distribution on 64-bit platforms.

Important

The consumer version of Gemini Code Assist on GitHub is being sunset. Starting June 18, 2026, new organization installations will be blocked, and all code review activity will officially cease on July 17, 2026.
For more details on the timeline and next steps, please review the Help Documentation.

Comment thread mooncake-transfer-engine/tent/src/runtime/receiver_credit_control.cpp Outdated
@catyans

catyans commented Jul 11, 2026

Copy link
Copy Markdown
Collaborator Author

Final consolidated results: data, charts, and conclusion

This comment supersedes the two earlier validation comments on this PR. It is the single source of truth for the current experimental result at head f13431a.

Executive conclusion

The receiver-credit control model passed the tested correctness, boundedness, restart, mixed-version, concurrency, and memory-safety gates. Under deliberately severe receiver slowdown, both loopback and cross-host runs eventually accepted 100% of 16,000 offered updates, produced zero invalid accepts, and ended with a credit-amplification ratio of exactly 1.0000. Queue saturation was observable and retryable rather than silent.

This is sufficient evidence for reviewing the transport-neutral control model in this Draft. It is not evidence that production dispatch gating or TTFT is complete; production receiver-push versus sender-pull remains a design decision in #2849.

1. Validation scale

Validation Measured volume Result
Release repetitions, lingjun-100 1,000 1,000/1,000 PASS
Release repetitions, lingjun-102 clean clone 1,000 1,000/1,000 PASS
Malformed wire inputs ~100,000,000 PASS
Concurrent bounded-queue events 32,000,000 PASS
Receiver restarts 10,000 zero torn snapshots
Concurrent snapshot readers 16 TSan PASS
ASan + LeakSanitizer focused suite PASS, no report
CUDA-enabled tent_runtime build PASS
clang-format 20.1.8 changed C/C++ files 0 violations
xychart-beta
    title "Validation event volume"
    x-axis ["Release runs (K)", "Restarts (K)", "Queue events (M)", "Malformed inputs (M)"]
    y-axis "Count in stated unit" 0 --> 100
    bar [2, 10, 32, 100]
Loading

2. Saturation results

Workload: 16 concurrent clients, 1,000 logical cumulative updates per client, bounded inbox capacity 64, drain batch 31, and 1 ms delay after each receiver drain.

Metric Loopback Cross-host 102 -> 100 Conclusion
Offered logical updates 16,000 16,000 same workload
Accepted 16,000 16,000 100% accepted
Queue-full responses 66,178 53,754 retry path exercised
Queue-full / RPC attempts 80.5301% 77.0622% explicit backpressure
Applied new maxima 1,008 (6.3000%) 1,003 (6.2687%) cumulative semantics
Duplicate/old 14,984 (93.6500%) 14,990 (93.6875%) minted no credit
Sequence gaps 8 (0.0500%) 7 (0.0438%) visible, not hidden
Invalid 0 0 no invalid acceptance
Final available 16,000 16,000 amplification = 1.0000
Exit status all 0 clients 0, server 0 complete runs
xychart-beta
    title "Retryable backpressure versus accepted updates"
    x-axis ["Loopback", "Cross-host"]
    y-axis "Events" 0 --> 70000
    bar [66178, 53754]
    line [16000, 16000]
Loading

Bars are retryable queue-full responses; the line is accepted logical updates. Even with 3.36-4.14 queue-full responses per accepted update, no logical update was lost.

Raw receiver outputs:

loopback:  accepted=16000 applied=1008 duplicate=14984 gaps=8 queue_full=66178 invalid=0 epoch=31 available=16000
cross-host: accepted=16000 applied=1003 duplicate=14990 gaps=7 queue_full=53754 invalid=0 epoch=32 available=16000

3. Conservation invariants

Check Loopback Cross-host Result
applied + duplicate + gaps 1008 + 14984 + 8 = 16000 1003 + 14990 + 7 = 16000 PASS
accepted / offered 1.0000 1.0000 no loss
available / max cumulative grant 1.0000 1.0000 no amplification
invalid accepts 0 0 PASS

4. Mixed-version behavior

flowchart LR
    A[Capability offer] --> B{Peer supports v1?}
    B -- yes: 2,1 --> C[Required -> Active v1]
    B -- no: 2 only --> D{Rollout mode}
    D -- Optional --> E[Legacy fallback]
    D -- Required --> F[Failed / NotImplemented]
Loading
Receiver versions Sender mode Observed result Server result
{2,1} Required Active, version 1 DONE=0 calls=1 invalid=0
{2} Optional Legacy, version 0 DONE=0 calls=1 invalid=0
{2} Required Failed / NotImplemented DONE=0 calls=1 invalid=0

5. Fault and restart coverage

Deterministic coverage includes loss, duplicate, reorder, sequence gaps, disconnect/reconnect, same-epoch activation replay, new-session restart, stale cleanup, capacity recovery, zero/full inbox, multi-producer drain, every truncation length, bad magic/schema/reserved fields, oversized messages, duplicate/unknown resources, wrong session/QoS/epoch, decreasing grants, and malformed fuzz.

The peer-context stress ran 10,000 receiver restarts against 16 concurrent readers. Every snapshot preserved a matching (receiver_session, epoch, sender_peer, qos_class) tuple; TSan reported no race.

6. Final assessment

flowchart TD
    P[PASS: PR2 control-model evidence] --> P1[Bounded wire and state]
    P --> P2[Explicit retryable backpressure]
    P --> P3[No logical loss]
    P --> P4[No credit amplification]
    P --> P5[Restart and mixed-version fencing]
    R[Remaining production work] --> R1[Choose receiver-push or sender-pull]
    R --> R2[Formal ControlService RPC]
    R --> R3[Dispatch reserve and rollback]
    R --> R4[Data-plane throughput, P99, TTFT]
Loading

Decision: keep #2861 as a stacked Draft for protocol review, dependent on #2860. Do not mark it Ready until #2860 merges, the diff shrinks, the upstream CI matrix is green, and the ControlService direction in #2849 is aligned. Data-plane performance claims remain in #2859/#2849, not this control-model PR.

@codecov-commenter

Copy link
Copy Markdown

⚠️ Please install the 'codecov app svg image' to ensure uploads and comments are reliably processed by Codecov.

Codecov Report

✅ All modified and coverable lines are covered by tests.

📢 Thoughts on this report? Let us know!

@catyans
catyans force-pushed the feat/receiver-credit-control-model branch from 7227fd7 to d2a3333 Compare July 12, 2026 04:30
@catyans
catyans marked this pull request as ready for review July 12, 2026 06:11
彦纾 added 3 commits July 13, 2026 17:20
# Conflicts:
#	mooncake-transfer-engine/tent/tests/CMakeLists.txt
# Conflicts:
#	mooncake-transfer-engine/tent/tests/CMakeLists.txt
# Conflicts:
#	mooncake-transfer-engine/tent/tests/CMakeLists.txt
…t-control-model

# Conflicts:
#	mooncake-transfer-engine/tent/src/runtime/receiver_credit.cpp
#	mooncake-transfer-engine/tent/tests/CMakeLists.txt
#	mooncake-transfer-engine/tent/tests/receiver_credit_test.cpp
@catyans

catyans commented Jul 15, 2026

Copy link
Copy Markdown
Collaborator Author

Merged current upstream/main into this branch and resolved the receiver-credit file/test-list conflicts after #2860 landed.

Resolution summary:

Cluster validation on lingjun-100 / codex_mooncake_pr_eval, commit 105a8a4b:

  • receiver_credit_test: 14/14 passed
  • receiver_credit_control_test: 24/24 passed
  • bw_arbitration_test: 7/7 passed

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants