Skip to content

feat(core): metaserver flush barrier + embeddable P2P transfer service#381

Merged
xiaguan merged 5 commits into
masterfrom
feat/metaserver-flush-barrier
Jul 3, 2026
Merged

feat(core): metaserver flush barrier + embeddable P2P transfer service#381
xiaguan merged 5 commits into
masterfrom
feat/metaserver-flush-barrier

Conversation

@xiaguan

@xiaguan xiaguan commented Jul 2, 2026

Copy link
Copy Markdown
Collaborator

What

Three additions that let an in-process Rust embedder (e.g. openinfer) serve cross-node RDMA fetches without running the full pegaflow-server binary:

  1. MetaServerClient::flush() — a barrier over the fire-and-forget registration queue. Resolves once every insert/remove enqueued before the call has been delivered to the MetaServer or dropped after a failed attempt. Exposed as PegaEngine::flush_saves_and_registrations() (write-pipeline drain first, so block-seal registrations are enqueued before the barrier runs). This is the P/D handoff barrier: a prefill node flushes before signalling KV-ready, so a decode node's MetaServer query observes every registration that made it through; dropped registrations degrade to decode-side recompute.

  2. P2pTransferService — the minimal Engine gRPC surface a serving peer must expose (RdmaHandshake / QueryBlocksForTransfer / ReleaseTransferLock + Health), with every CUDA-IPC registration RPC answered unimplemented. pegaflow-server keeps its full service; this is for embedders that drive PegaEngine in-process. Includes serve_with_incoming so embedders can bind first and fail loud on a taken port.

  3. logging::init uses try_applyRcBackend::new calls init_logging on first use; when pegaflow-core is embedded as a library the host process has already installed its own logger, and logforth's apply() panicked, taking down the host's engine loader thread. The host's logger receives our records; its existence is not an error.

Also bumps the cudarc floor to 0.19.7 and adapts to its regenerated sys bindings (CUmemAllocationHandleType is now a newtype over c_uint; the multicast handleTypes bitmask reads .0 instead of an enum cast, and cuda_sys.rs re-binds the handle-type constants as consts since associated constants cannot be pub used).

Tests

  • 3 new fake-metaserver tests for the flush barrier: delivered-before-ack, ack-on-drop (permanent insert failure), no-hang after shutdown. cargo test -p pegaflow-core --features rdma --lib internode: 7/7 pass.
  • End-to-end validated by the openinfer P/D disaggregation M2 run on a jiuzhang H200 node: 1 prefill + 1 decode openinfer instance, each embedding PegaEngine with this branch; decode discovered the prefill node's KV via the MetaServer and pulled 33/33 blocks (74.2 MiB) over RDMA READ; greedy output token-identical to the single-instance baseline across block-boundary prompt lengths; killing the MetaServer or the prefill node degrades to local prefill with no crash or hang.

🤖 Generated with Claude Code

xiaguan and others added 4 commits July 3, 2026 03:53
Two additions for in-process Rust embedders (e.g. openinfer) that serve
cross-node RDMA fetches without running the full pegaflow-server binary:

- MetaServerClient::flush(): a barrier over the fire-and-forget
  registration queue. Resolves once every insert/remove enqueued before
  the call has been delivered to the MetaServer or dropped after a
  failed attempt. Exposed as PegaEngine::flush_saves_and_registrations()
  (write pipeline drain first, so block-seal registrations are enqueued
  before the barrier). This is the P/D handoff barrier: a prefill node
  flushes before signalling KV-ready, so a decode node's MetaServer
  query is guaranteed to observe the registrations.

- P2pTransferService: the minimal Engine gRPC surface a serving peer
  must expose (RdmaHandshake / QueryBlocksForTransfer /
  ReleaseTransferLock + Health), with every IPC-registration RPC
  answered unimplemented. pegaflow-server keeps its full service; this
  is for embedders that drive PegaEngine in-process.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…s, serve_with_incoming

- Bump cudarc floor to 0.19.7 and adapt to its regenerated sys bindings:
  CUmemAllocationHandleType is now a newtype over c_uint, so the
  multicast handleTypes bitmask reads .0 instead of an enum cast, and
  cuda_sys.rs re-binds the handle-type constants as consts (associated
  constants cannot be `pub use`d). Lets embedders on cudarc 0.19.5+
  keep per-symbol lazy loading instead of downgrading to 0.19.3.
- P2pTransferService::serve_with_incoming: caller-bound listener
  variant so embedders can fail loud on a taken port before reporting
  ready.
- flush_saves_and_registrations docs: the barrier bounds *when*
  delivery is attempted, never *whether* it succeeds — dropped
  registrations degrade to peer-side recompute, not an error.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
RcBackend::new (the rdma transport bring-up) calls init_logging on
first use. When pegaflow-core is embedded as a library the host
process has long since installed its own logger, and logforth's
apply() panics — taking down the host's engine loader thread. Use
try_apply and log the skip to stderr: the host's logger receives our
records; its existence is not an error.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
The router rewrites max_tokens=1 for the P node, but chat clients send the
modern max_completion_tokens field (OpenAI deprecated max_tokens for chat).
Engines prefer max_completion_tokens when both are present, so P ran the
full decode: every turn paid prefill + complete generation on P before D
even started, inflating multi-turn P/D TTFT from ~110ms to ~1.5s per turn
(Qwen3-8B 1P+1D, 10-way concurrency, 4k prompt + 1k/turn).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@xiaguan xiaguan merged commit d46fd16 into master Jul 3, 2026
12 checks passed
@xiaguan xiaguan deleted the feat/metaserver-flush-barrier branch July 3, 2026 06:21
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.

2 participants