Skip to content

Merge upstream main (7faef38b) into our_main - #17

Merged
Juhyun-Kim-Memphis merged 346 commits into
our_mainfrom
inf-522/sync-7faef38b
Sep 21, 2026
Merged

Juhyun-Kim-Memphis merged 346 commits into
our_mainfrom
inf-522/sync-7faef38b

Conversation

@Juhyun-Kim-Memphis

@Juhyun-Kim-Memphis Juhyun-Kim-Memphis commented Sep 21, 2026 •

Copy link
Copy Markdown
Collaborator

요약

업스트림 kvcache-ai/Mooncake main을 7faef38b(2026-09-21, kvcache-ai#4195)까지 our_main에 병합했습니다. 기준 커밋은 INF-522에서 고정한 값이며, 그보다 새로운 upstream 커밋은 넣지 않았습니다.

충돌 해소

충돌 파일은 14개였습니다. 두 파일을 빼고는 충돌 hunk만 upstream 쪽을 택했습니다(파일 전체를 upstream으로 덮지 않았으므로, 충돌하지 않은 우리 hunk는 그대로 남습니다).

파일 해소 이유
CMakeLists.txt upstream fork #7의 전역 STORE_USE_JEMALLOC define을 #4208의 target별 define이 대체
docs/.../http-service.md, docs/.../mooncake-store-deployment-guide.md upstream kvcache-ai#3316 최종본과 kvcache-ai#3743 문구
include/client_service.h, include/master_client.h, src/real_client.cpp upstream fork #1이 upstream #3316과 #3871로 흡수됨
include/master_service.h, src/master_service.cpp upstream fork #1·#3의 옛 sweep 코드, #13의 kvcache-ai#3533 백포트에 붙인 주석 → upstream 최종본
tests/master_service_ssd_test.cpp, tests/rpc_timeout_test.cpp upstream fork #1 테스트의 옛 형태 → upstream의 DSL 이전(kvcache-ai#3847)·kvcache-ai#3871 테스트
mooncake-wheel/mooncake/mooncake_store_service.py upstream kvcache-ai#3316 최종본. 우리 preStop payload {"grace_period_seconds": 20}은 upstream의 body 검증을 통과함
mooncake-wheel/pyproject.toml upstream(0.3.13) 트렁크 버전은 별도 PR(0.3.15.dev0)에서 옮깁니다
src/shm_helper.cpp 양쪽 upstream #3587이 utils.h를 삭제함. fork #14(병렬 populate)는 utils.h의 어떤 심볼도 쓰지 않으므로, <algorithm>·<thread>·<vector> include를 upstream의 common/client_buffer_allocation.h 옆에 둠
tests/file_storage_test.cpp 우리 쪽 일부 fork #15의 deferred-key 테스트 5개는 유지. 같은 hunk에 있던 env 설정 테스트 5개는 upstream #3525가 file_storage_config_test.cpp로 옮겼으므로 뺌

충돌 없이 자동 병합됐지만 손으로 고친 곳이 하나 있습니다.

  • include/master_service.h: 자동 병합이 fork #1의 옛 predicate CleanupStaleHandles 오버로드와 HasMountedLocalDiskSegment 선언 사본을 upstream 선언 옆에 하나씩 더 남겼습니다. 두 사본을 지웠습니다(중복 선언이라 그대로 두면 컴파일이 실패함).

유지한 캐리 패치

fork PR 상태
#8·#10 master resident-memory watermark(MaybeTrimHeap)와 glibc 2.28 mallinfo 대체 유지. 충돌 없이 자동 병합. #8이 넣은 master_config.h·master.cpp·master_service.{h,cpp} 줄이 병합 전과 같음
#14 병렬 shm populate 유지. include만 위처럼 옮김
#15 upstream kvcache-ai#3009 백포트(offload key 유실 수정) 유지. upstream #3009는 아직 OPEN이라 이것이 유일한 형태. file_storage.*·storage_backend.* 코드는 자동 병합, 테스트는 위처럼 해소
#13의 [Bench] master_bench 커밋 3개 유지. 자동 병합
#1·#3 흡수됨(upstream kvcache-ai#3316). 잔재 0
#13의 kvcache-ai#3533 부분 흡수됨(upstream c5635ff3). breaker는 #16에서 이미 제거됨
#7 CMake 줄만 남아 있었고, #4208로 대체됨

잔여 delta (git diff 7faef38b c7f42241 --stat)

 mooncake-store/benchmarks/master_bench.cpp | 503 ++++++++++++++++++++++++++++-   (bench)
 mooncake-store/include/file_storage.h      |  67 ++++                              (#15)
 mooncake-store/include/master_config.h     |  14 +                                 (#8)
 mooncake-store/include/master_service.h    |  39 +++                               (#8)
 mooncake-store/include/storage_backend.h   |  22 +-                                (#15)
 mooncake-store/src/file_storage.cpp        | 108 ++++++-                           (#15)
 mooncake-store/src/master.cpp              |  27 ++                                (#8)
 mooncake-store/src/master_service.cpp      | 217 +++++++++++++                       (#8, #10)
 mooncake-store/src/shm_helper.cpp          | 102 +++++-                            (#14)
 mooncake-store/src/storage_backend.cpp     |  23 +-                                (#15)
 mooncake-store/tests/file_storage_test.cpp | 296 ++++++++++++++++-                   (#15)
 11 files changed, 1389 insertions(+), 29 deletions(-)

확인한 것:

검증

  • 확장 unit gate: PASS

  • fork ci.yml 수동 실행(이 브랜치): https://github.com/vessl-ai/Mooncake/actions/runs/35579535308

    • CTest unit tests (Python 3.12) success(upstream CI의 전체 unit test), build-flags·Sphinx docs·typos success.
    • Check code format failure: workflow_dispatch에는 비교할 base가 없어 스크립트가 Base branch '' not found로 끝남. 코드 판정이 아니라 수동 실행의 한계입니다.
    • Check Python with Ruff failure: 지적된 8개 파일은 모두 upstream 파일이고 7faef38b와 바이트 단위로 같습니다(잔여 delta에 Python 파일 없음).
    • wheel 빌드 job은 needs: clang-format 때문에 skip됨 → 아래 probe로 대신 확인.
  • wheel 빌드 probe: 이 병합 커밋 위에 ci.yml의 needs에서 clang-format만 뺀 커밋 하나를 얹은 브랜치 inf-522/ci-wheel-probe(병합하지 않음)로 ci.yml을 수동 실행: https://github.com/vessl-ai/Mooncake/actions/runs/35579803960

    • success: build-wheel(3.10, 3.12), build-wheel-cu13, build-wheel-efa(non-cuda 3.10, cuda 3.12, cuda13 3.12), build-wheel-rocm, test-wheel-ubuntu, tent-ci, CTest unit tests. YLT FetchContent, 번들 libssl 등 새 빌드 의존성이 GitHub runner의 wheel 경로에서 문제없음을 확인했습니다. (magma의 manylinux carrier 레시피와 zeromq-devel 설치는 이미지 빌드 단계에서 따로 확인해야 합니다.)
    • 실패는 위와 같은 dispatch 한계인 Check code format(와 그에 따른 CI Gate)뿐.
  • fork nightly.yml 수동 실행(skip_publish=true): https://github.com/vessl-ai/Mooncake/actions/runs/35579531264

    • nightly-coverage: 전체 ctest 100% tests passed, 0 tests failed out of 217. 그 뒤 새 단계 run_store_go_integration.sh에서 Failed to start HTTP metadata server on 0.0.0.0:8080로 실패. 이 단계는 upstream이 이번 구간에서 nightly에 넣은 것이고(our_main의 nightly에는 없음), upstream 자신의 nightly(kvcache-ai run 35521913959, 2026-09-20)에서도 같은 메시지로 실패합니다. 기존 upstream 문제로 판정합니다.
    • build-musa: success.
    • Build Docker Image: "hosted runner lost communication" 로 runner가 끊김(코드 판정 없음). 재실행 결과: success(job 106286468195, 09:45:58Z → 10:09:30Z, 23분 32초. our_main 정기 nightly의 같은 job은 약 22분)
    • 나머지 job은 github.repository == 'kvcache-ai/Mooncake' 게이트로 fork에서 skip(our_main의 정기 nightly와 같음).

이 PR 밖에서 볼 것

  • TCP connection pool: upstream #3569가 기본값을 on으로 바꿨습니다. 이 PR에는 upstream 그대로 들어오며, 기본값을 다시 끄는 carry-only PR을 바로 뒤에 올립니다.
  • liveness TTL: #2991부터 --client_ttl은 --client_active_ttl_sec의 deprecated alias입니다. --client_ttl=60이면 SUSPECTED 60초, OFFLINE 약 120초가 됩니다. 롤아웃 때 TTL을 명시하는 것은 롤아웃 이슈의 몫입니다.
  • STORE_USE_JEMALLOC: [Store] Export process and allocator memory metrics, and complete the jemalloc build option kvcache-ai/Mooncake#4208 이후 이 define은 mooncake_master/mooncake_client 실행 파일에만 붙고, MaybeTrimHeap이 있는 master_service.cpp는 object library로 컴파일됩니다. 기본값(OFF)에서는 영향이 없지만, jemalloc을 켜면 #8은 glibc 분기를 탑니다.
  • tier 간 wire 호환성(master와 store를 따로 롤할 때)은 검증하지 않았습니다.

Refs: INF-522

판정

gate PASS, upstream CI의 전체 unit test와 nightly의 전체 ctest(217개) PASS, wheel 빌드(cu13·EFA 포함) PASS입니다. 실패한 항목은 수동 실행의 한계(format/ruff base 없음)와 upstream에도 있는 기존 실패(Go integration의 8080 포트 충돌)뿐이라, merge commit으로 병합합니다.

Colors-111 and others added 30 commits September 1, 2026 11:07
…che-ai#3790)

* Map MOONCAKE_LOCAL_HOSTNAME to TENT rpc_server_hostname

* code format

---------

Co-authored-by: ruanzhao <ruanzhao@kingsoft.com>
…vcache-ai#3777)

* [TENT] Prefer the LAG-effective port speed from ibv_query_port_speed

* [TENT] Let tests inject verbs into RdmaContext and cover the effective-speed path

* [TENT] Hold the last effective speed over transient query failures and count them

---------

Co-authored-by: maxlisongsong <maxlisongsong@didiglobal.com>
* [Store] Add batch OpLog snapshot coordinator

* [Bugfix][Store] Fix batch snapshot coordinator races

---------

Co-authored-by: Yuchen Kou <kouyuchen@approaching.ai>
* perf(store): remove redundant per-file deletion delay

* test(store): make concurrent remove test deterministic
…on (kvcache-ai#3782)

Signed-off-by: Wang Zupeng <zupenwang@gmail.com>
The ghfast fallback used raw git fetch, which skipped checkout's
pull_request_target fork check and ran untrusted PR heads on the
privileged self-hosted job. Rewrite github.com via insteadOf and retry
the same action so network failures still use the mirror.

Signed-off-by: staryxchen <staryxchen@tencent.com>
Co-authored-by: Cursor <cursoragent@cursor.com>
…ner (kvcache-ai#3718)

* [Bugfix] Refactor RDMA slice dispatch and endpoint reclaim

* Improve impl based on comments

* [TransferEngine] Avoid RDMA lifecycle gate during active handshake

* Reformat
…cache-ai#3468)

* feat: Add strict_local_numa to hard-exclude cross-NUMA RDMA rails

* Fix code address comment by @alogfans

Conflicts:
	mooncake-transfer-engine/tent/include/tent/transport/rdma/quota.h
	mooncake-transfer-engine/tent/src/transport/rdma/quota.cpp

* Fix code address comment by @staryxchen

* fix ci

---------

Co-authored-by: shawnding <shawnding@tencent.com>
…i#3582)

* [TENT] Preserve ownership after failed memory free

* fix(tent): warn when local memory free fails

---------

Co-authored-by: codex <codex@local.invalid>
Co-authored-by: Yuchen Kou <kouyuchen@approaching.ai>
… PORT_ACTIVE was lost (kvcache-ai#3799)

* [Bugfix][TENT] Recover paused RDMA contexts when PORT_ACTIVE is lost

A TENT RDMA context paused by IBV_EVENT_PORT_ERR only leaves DEVICE_PAUSED
from the IBV_EVENT_PORT_ACTIVE branch of applyContextEvent(). The async fd is
registered edge-triggered (EPOLLIN|EPOLLET) but handleContextEvents() consumed
exactly one ibv_async_event per epoll wakeup, so an event queued behind another
(e.g. IBV_EVENT_COMM_EST bursts) is stranded until an unrelated later event
releases it. A stranded PORT_ACTIVE leaves the context paused forever, silently
failing every transfer on that NIC (issue kvcache-ai#3523 defect C).

- handleContextEvents() now drains the whole queue (loop until EAGAIN/EWOULDBLOCK,
  retry on EINTR, propagate a real read error) instead of one event per wakeup.
- Workers::resumePausedContexts(): 1 Hz safety net on the existing monitorThread
  heartbeat. For DEVICE_PAUSED contexts it reads the port state and, when the
  hardware reports IBV_PORT_ACTIVE, runs the same recovery the event path runs.
- Recovery actions factored into Workers::activateContext() so the event and poll
  paths cannot drift apart.
- New RdmaContext::queryPortState() reads port state without touching the cached
  link speed/width (refreshLinkSpeed() diffs against them).

Tests:
- tent/tests/rdma_async_event_drain_test.cpp (wraps ibv_get_async_event, no device
  needed): all 5 cases fail on the pre-fix code.
- tent/tests/rdma_transport_test.cpp: RecoveryPollLeavesInertContextsAlone,
  QueryOnInertContextIsRejected, PollActivatesPausedContextWithLivePort.

* [Bugfix][TENT] Reduce noise from high-frequency async events

* [Bugfix][TENT] Fix formatting after upstream sync

Restore the closing brace lost while resolving the queryPortState upstream
sync, and apply the repository clang-format-20 and cmake-format rules to the
PR files. All pre-commit hooks pass on the affected files.

---------

Co-authored-by: TTThanos <yaozhong.lyz@alibaba-inc.com>
…che-ai#3763)

* [Store] Structure DistributedStorageConfig environment settings

Signed-off-by: Schatten <czhengt@qq.com>

* [Store] Separate DistributedStorageConfig from backend

Signed-off-by: Schatten <czhengt@qq.com>

---------

Signed-off-by: Schatten <czhengt@qq.com>
…#3773)

* [Store] Structure ClientMetricConfig environment settings

Signed-off-by: Schatten <czhengt@qq.com>

* [Store] Use chrono duration for client metric interval

Signed-off-by: Schatten <czhengt@qq.com>

---------

Signed-off-by: Schatten <czhengt@qq.com>
Co-authored-by: Aoi <aione.moe.dev@gmail.com>
…i#3781)

Signed-off-by: Schatten <czhengt@qq.com>
Co-authored-by: Aoi <aione.moe.dev@gmail.com>
…vcache-ai#3804)

Signed-off-by: Schatten <czhengt@qq.com>
Co-authored-by: Aoi <aione.moe.dev@gmail.com>
…vcache-ai#3820)

High-concurrency PD created 256 independent notify recv MRs per RDMA
endpoint, exhausting MR capacity while QP tables were still sparse.
Match the send path: one contiguous 256x64KiB buffer and one ibv_reg_mr,
then slice by slot.

Signed-off-by: staryxchen <staryxchen@tencent.com>
Co-authored-by: Cursor <cursoragent@cursor.com>
…che-ai#3768)

tebench called exit() from worker threads when a transfer FAILED, so a
SIGKILL'd RDMA target made concurrent workers abort with unordered_map::at.
Return failure to main so threads can join, rank unknown statuses without
throwing, and wait on stop or pending==0 under the mutex like classic TE.

Signed-off-by: staryxchen <staryxchen@tencent.com>
Co-authored-by: Cursor <cursoragent@cursor.com>
…ache-ai#3789)

* [Store] Support 512MB hugepage size for client buffer allocation

512MiB is the PMD hugepage size on arm64 kernels running with 64K base
pages, where 2MB pages give poor TLB coverage and 1GB pages are
unavailable.

- MC_STORE_HUGEPAGE_SIZE now accepts 512MB in addition to 2MB/1GB
  (get_hugepage_size_from_env, allocate_buffer_numa_segments).
- Provide MAP_HUGE_512M / MFD_HUGE_512M fallbacks for older
  glibc/kernel headers that do not define them.
- MmapArena honors the configured hugepage size: align the pool to it,
  pass the size-specific MAP_HUGE_* flag to mmap(), and strip the size
  bits on the no-hugepage retry.
- Document 512MB in the store deployment guide.

* [Store] Use standard UAPI names MAP_HUGE_512MB/MFD_HUGE_512MB

The Linux UAPI spells these constants with a trailing 'B'
(MAP_HUGE_512MB in asm-generic/mman-common.h, MFD_HUGE_512MB in
linux/memfd.h). Guard and define the standard names so the fallbacks
only kick in on headers that genuinely lack them.
…cache-ai#3784)

* fix multi NICs spanning different NUMA nodes in TENT

* code format

* validating the caller-supplied location before overriding the probe in registerLocalMemory

* code format

* fix doubled /metadata path in config override test

* retriger ci

---------

Co-authored-by: ruanzhao <ruanzhao@kingsoft.com>
…vcache-ai#3689)

* TENT: add high-performance TCP worker scaffold

* TENT: implement high performance TCP v1

* TENT: add HP TCP configuration and integration guards

* TENT: format high-performance TCP sources

* feat(tent): complete correctness-first high-performance TCP v1

* test(tent): make HP TCP sanitizer synchronization explicit

* refactor(tent): expose high-performance TCP as hp_tcp

* docs(tent): document hp_tcp design

* fix(tent): close HP TCP correctness gaps

* refactor: trim hp_tcp to reviewable v1 core

* refactor(tent): trim hp tcp worker surface

* fix(tent): preserve hp tcp worker affinity

* refactor(tent): simplify hp_tcp v1 ownership

* Revert "refactor(tent): simplify hp_tcp v1 ownership"

This reverts commit b883c4a.

* fix(tent): harden HP TCP failure lifecycle

* perf(tent): keep HP TCP health checks lock-free

* fix(tent): close HP TCP failure and notification gaps

Preserve at-most-once writes across ambiguous failures, enforce bounded frame progress without expiring idle pooled connections, harden registration/task lifetimes, and route notifications without unsafe retries.

* refactor(tent): trim HP TCP v1 scope

* refactor(tent): tighten hp tcp v1 surface

* refactor(tent): separate hp_tcp transport sources

---------

Co-authored-by: 林李谦 <linliqian@192.168.1.5>
…eue (kvcache-ai#3726)

Co-authored-by: zhaoye <yzhao04@iquestlab.com>
Co-authored-by: Claude <noreply@anthropic.com>
Co-authored-by: XFDG <xfdg@users.noreply.github.com>
…vcache-ai#3814)

* fix: drain RDMA CQ during active handshake

* Fix comments

* polling for initial step
* [TENT] Fix DeviceSelector inflight quota accounting

* Update mooncake-transfer-engine/tent/tests/quota_accounting_test.cpp

Co-authored-by: Stary <staryxchen@tencent.com>

---------

Co-authored-by: jipengtian <jipengtian@xiaohongshu.com>
Co-authored-by: Stary <staryxchen@tencent.com>
…ache-ai#3835)

Embedded/standalone TEs stamp buffer device_id with the logical NPU id
but publish a single endpoint at index 0, which spammed fallback
warnings. Multi-endpoint dest routing is unchanged.

Co-authored-by: youyx <youxiao@huawei.com>
Co-authored-by: Cursor <cursoragent@cursor.com>
…vcache-ai#3832)

Segment metadata is copy-on-write, so buffer/CUDA-graph register
publishes a new Topology* even when the rail map is unchanged. Treat
same NIC/memory layout as a pin refresh instead of loadDefault(), and
log the config banner only on first load so PD/e2e is not flooded.

Signed-off-by: staryxchen <staryxchen@tencent.com>
Co-authored-by: Cursor <cursoragent@cursor.com>
XinyuYe-Intel and others added 11 commits September 20, 2026 11:50
…ngine (kvcache-ai#4157)

Builds on the XpuPlatform from kvcache-ai#4030 to make Intel GPU (XPU) memory a
first-class participant in transfers.

Transport and routing:
- Add TransportType::XPU (wire value 14) with name/parse, the TRANSPORT_XPU
  C-API macro and the pybind binding + static_assert.
- Add XpuTransport, a thin local staging transport that advertises
  gpu_to_dram/dram_to_gpu (not gpu_to_gpu, so cross-node hops stage through
  host DRAM). It binds the active XpuPlatform (mirroring NVLinkTransport /
  CudaPlatform) and classifies interior device pointers via
  getMemoryType()==MTYPE_XPU. Registered under USE_XPU
  (transports/xpu/enable) and included in default registration, so
  registerLocalMemory() on XPU VRAM without an explicit transport list
  produces a buffer a transport can serve.
- Teach the routing predicates about MTYPE_XPU: isGpuMemoryType() is the
  single device predicate shared by isGpuType() and the selector, and
  matchesMemoryPattern() knows the "xpu" pattern.
- Make staging reachable without a direct route. When either side of a
  non-local request is MTYPE_XPU, resolve the staging policy up front and
  select the host transport (RDMA/TCP/HP_TCP) using the post-staging
  dram_to_dram pattern; carry staging_params on the route through prepare,
  queued dispatch and retry. An unstaged host buffer on either side must
  itself carry the network transport; every device side is staged, and a
  device side without a host DRAM stage location fails closed with a
  warning. XPU is gated on local_segment (not same_machine) in both the
  selector and legacy paths, since XpuTransport only serves
  LOCAL_SEGMENT_ID. Non-XPU routing is unchanged.

Platform (XpuSyclBackend):
- Classify externally allocated USM as XPU device memory. Keep the
  [base, base+size) registry for interior-pointer resolution of own
  allocations and fall back to sycl::get_pointer_type/get_pointer_device
  against the platform default context, which is where PyTorch's XPU
  allocator draws from, so a PyTorch tensor handed to
  registerLocalMemory("xpu:N") is recognised and copyable. Queues are
  created on that same default context. Only usm::alloc::device counts as
  device memory. The backend singleton is intentionally leaked so SYCL
  queues/contexts are not destroyed during static teardown.

Tests:
- tent_xpu_transport_test: interior-offset D2H/H2D staging, fail-loud
  misclassification cases.
- tent_transport_selector_test: XPU wire value, predicate agreement,
  staging direction, XPU not routable across machines, "xpu" pattern,
  unstaged host source must carry the host transport.
- tent_xpu_engine_test (new): two in-process engines over real TCP/HP-TCP
  loopback with real B60 copies (4 MiB + 4096 B payloads, read/write,
  one/two device sides, legacy/selector, direct/queued, injected
  stage-failure retry), routed through resolveTransport like
  submitTransfer.
- tent_xpu_platform_test: ForeignUsmClassifiesAsXpuAndCopies; the
  post-free MTYPE_CPU assertion is dropped (Level Zero caches freed USM).

Validated on Intel Arc Pro B60 (icpx, USE_TENT+USE_XPU): TENT CTest
suites pass, xpu_engine_test 44 pass / 4 skip, xpu_platform_test 8/8.
CPU-only GCC build (USE_XPU=OFF) passes. Engine selection is unchanged:
XPU deployments opt in with MC_USE_TENT=1 like every other build.
Part of RFC kvcache-ai#4031.
* refactor quick-start.md

* refactor quick-start.md
…i#4198)

* [Doc] Consolidate Mooncake Store API references into one section

Co-authored-by: Cursor <cursoragent@cursor.com>

* [Doc] Move Master Service APIs into the Store API section

Co-authored-by: Cursor <cursoragent@cursor.com>

---------

Co-authored-by: Cursor <cursoragent@cursor.com>
…i#4196)

Co-authored-by: Ke Yang <yangke@approaching.ai>
Co-authored-by: Feng Ren <alogfans@users.noreply.github.com>
…el is unavailable (kvcache-ai#4068)

Three failures in RdmaTransport::sendNotification() mean nothing left
the host - no endpoint could be brought up for the peer, the endpoint has
no connected notify QP (the peer has none, or it was disabled after a
fault by kvcache-ai#3475), or the post was refused - and all three surfaced as an
InternalError that TransferEngineImpl::sendNotification() dropped. Report
them as DeviceNotFound / RdmaError and let the engine try the next
notification transport and, when none is left, the control-plane RPC the
peer answers bootstrap on (the path TcpTransport::sendNotification()
already uses), the way the classic engine's rdma_notify_oob_fallback
does. Any other error is still returned untouched, and a transport that
advertises notifications without implementing them (SunriseLink) is
skipped on both the send chain and the receive drain.

One case is deliberately excluded: when the endpoint could not be brought
up because the bootstrap RPC itself failed, the peer's control plane is
not answering, so RdmaTransport reports RpcServiceError and the engine
returns it as is instead of stacking a second RPC timeout on the polling
thread. Every other reason (no context, allocation, QP setup, a stale
segment) still falls back.

receiveNotification() only drained the first transport that supports
notifications, so a notification that arrived over RPC and was queued by
the TCP transport was never handed out; drain every transport plus the
in-process queue. Nothing registered a notify callback with
ControlService unless a TCP transport was loaded, so RPC-delivered
notifications were dropped on arrival; register an in-process one before
the transports install (the TCP transports still take over the slot).

notification/rpc_fallback (default true) turns the fallback off. What
this does and does not change:

- Cost: the fallback is a synchronous RPC at the same call sites the TCP
  notification path already uses today, including the poll that fires a
  transfer-bound notification. With the peer process alive and only its
  channel broken it is a millisecond affair (p50 ~67 us over loopback);
  with the control plane unreachable the exclusion above keeps it at the
  one bootstrap timeout the caller paid before.
- Mixed versions: delivery over the fallback needs the receiver to run
  this change or to have a TCP transport loaded. An older RDMA-only
  receiver drops the RPC notification in onNotify() and still answers
  the RPC, so the result is what it is today (lost), only no longer
  reported as an error.
- A payload larger than the notify slot (64 KB) now reaches the peer
  over RPC instead of failing.
- Ordering holds within one path only: in one poll, notifications that
  came over RPC are handed out after the ones the notify QP carried.

Only failures where nothing was posted are covered: a notification lost
in flight after a successful post is not resent, since that needs
receiver-side deduplication first.

Co-authored-by: xiaodouzi666 <xiaodouzi6661@gmail.com>
…ache-ai#4164)

* [Bugfix][Conductor] Clamp query match to the queried token count

Signed-off-by: pjdurden <prajjwalchittori1@gmail.com>

* [Bugfix][Conductor] Bound sglang_bigram matches by logical position count

The bigram chains hash token pairs: SglangHashChain builds block_count_ over
token_ids.size() - 1, and each block hashes up to that logical length. So a
query of n raw tokens covers n - 1 reusable KV positions, not n.

Clamping those matches at the raw token count therefore still reports one
position past what any indexed block holds. Select the bound once in Query()
instead, so the bigram strategy caps at n - 1 while the block count keeps
bounding it from the other side.

Adds two regression tests: a full 40-token bigram match over a 16-token block
size now reports 39 rather than 40 or the 48 a whole-block count would give,
and a run that stops at the last whole block still reports 32, confirming the
clamp does not pull whole-block matches down.

Signed-off-by: pjdurden <prajjwalchittori1@gmail.com>
Signed-off-by: pjdurden <adobearakap@gmail.com>

---------

Signed-off-by: pjdurden <prajjwalchittori1@gmail.com>
Signed-off-by: pjdurden <adobearakap@gmail.com>
Co-authored-by: pjdurden <adobearakap@gmail.com>
…es (kvcache-ai#3801)

* [Store] Add ProbeKey/BatchProbeKey RPCs for lease-free existence probes

Implements Option A of RFC kvcache-ai#3769: add ProbeKey and BatchProbeKey as
twins of ExistKey/BatchExistKey that share the same lookup path but
grant no read lease, so speculative scans cannot pin the working set
against eviction.

The RPC crosses WrappedMasterService (coro_rpc), MasterClient,
Client, RealClient/DummyClient (PyClient), and the Python binding
(probe_key / batch_probe_key), plus Python API docs. store_c.h and
the generated Rust bindings are intentionally untouched.

Point-in-time semantics: a true result means the object existed at
the time of the call; it may be evicted before a subsequent Get, so
callers must treat a following miss as normal. Reads remain
protected by GetReplicaList's own lease grant.

Refs: kvcache-ai#3769
…rder (kvcache-ai#3662)

* [Bugfix][Store] Use SelectBestReplica in batch_get_session_start to support SSD offloading (kvcache-ai#3658)

When SSD offloading is enabled, some data resides on SSD instead of in-memory.
batch_get_session_start was using SelectCompleteMemoryReplica which only
selects memory replicas, causing INVALID_REPLICA (702) errors for keys
whose replicas exist only on SSD.

Fix: replace SelectCompleteMemoryReplica with SelectBestReplica, which
handles all replica types (memory, SSD, disk, DFS) and picks the best
available one, matching the behavior of batch_get_into and other get methods.

Co-Authored-By: Claude <noreply@anthropic.com>

* fix: address fcczzz+bitborne reviews on batch_get_session_start

Two bugs in PR kvcache-ai#3662:

1. SelectBestReplica priority: scan all replicas before returning so
   local MEMORY always beats local NOF regardless of list order.
   Previously the first local replica (memory or NOF) caused an early
   return, so [local NOF, local MEMORY] would incorrectly select NOF.

2. batch_get_into_multi_buffer_ranges replica_limit: NOF replicas also
   support range reads via RDMA. Use the NOF buffer size for overflow
   detection instead of 0, which caused INVALID_PARAMS for any NOF
   replica selected by batch_get_session_start.

Co-Authored-By: Claude <noreply@anthropic.com>

* [Bugfix][Store] Add regression test for local MEMORY vs NOF ordering (issue kvcache-ai#3658)

Covers both permutations (local NOF before local MEMORY, and vice versa)
to lock in the order-independent priority fix in SelectBestReplica.

* [Bugfix][Store] Restrict batch_get_session_start to MEMORY replicas (kvcache-ai#3658)

The session range-read path is memory-only: Client::BatchTransferReadRanges
rejects every non-MEMORY replica (client_service.cpp), so a session started
against a NOF_SSD replica passes the size/overflow check and then fails the
actual transfer with INVALID_PARAMS, and a LOCAL_DISK/DFS/DISK selection fails
even earlier with a zero replica_limit.

The previous revision switched batch_get_session_start to SelectBestReplica,
which can return NOF_SSD (and lower tiers). Restore a MEMORY-only selector for
the session path: move SelectCompleteMemoryReplica into replica_selection.h
(next to SelectBestReplica) so it is unit-testable, and use it in
batch_get_session_start. The single-object get path keeps SelectBestReplica,
which correctly routes NOF/DISK/DFS through Client::Get.

The kvcache-ai#3658 fix (local MEMORY preferred over local NOF regardless of master
return order) is preserved: SelectCompleteMemoryReplica scans all replicas and
prefers a local MEMORY replica.

Adds SessionPathRejectsNoFOnlyObject: a NOF-only object is selected by
SelectBestReplica (single-object path) but declined by
SelectCompleteMemoryReplica (session path), and a local MEMORY replica still
wins when both MEMORY and NOF are present.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>

* ci: re-run CI after kvcache-ai#3870 fixes test_concurrent_stress flake

* fix: narrow replica selection ordering scope

---------

Co-authored-by: zhaoye <yzhao04@iquestlab.com>
Co-authored-by: Claude <noreply@anthropic.com>
Co-authored-by: XFDG <xfdg@users.noreply.github.com>
…he-ai#4195)

* [Store] Add etcd capacity soak and NOSPACE recovery operations

* [Doc] Condense batch OpLog capacity operations guidance

---------

Co-authored-by: Yuchen Kou <kouyuchen@approaching.ai>
Resolution: every conflicting hunk takes upstream's side except two.
Upstream now carries what those hunks held on our side: kvcache-ai#3316 (fork #1 and
#3) with its review follow-ups, kvcache-ai#3533 (the part of fork #13 that remained
after #16 removed the breaker), kvcache-ai#3871's RPC timeout overrides, and kvcache-ai#4208's
per-target STORE_USE_JEMALLOC define, which replaces fork #7's CMake line.
pyproject.toml takes upstream's 0.3.13; the trunk version moves in its own PR.

- shm_helper.cpp: kvcache-ai#3587 deleted utils.h. The parallel populate (fork #14)
  uses nothing from it, so it keeps its <algorithm>/<thread>/<vector>
  includes next to upstream's common/client_buffer_allocation.h.
- file_storage_test.cpp: keeps fork #15's deferred-key tests. The env config
  tests on our side of that hunk were moved by kvcache-ai#3525 to
  file_storage_config_test.cpp, so they are dropped here.

master_service.h auto-merged a stale copy of fork #1's predicate
CleanupStaleHandles overload and a second HasMountedLocalDiskSegment
declaration next to upstream's own; both copies are removed.

The remaining delta against 7faef38 is the carried set only: #8/#10 (heap
trim and its glibc 2.28 mallinfo fallback), #14 (parallel shm populate), #15
(backport of upstream kvcache-ai#3009), and the three [Bench] master_bench commits.
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.