mirror of
https://github.com/kvcache-ai/Mooncake.git
synced 2026-11-05 01:17:55 +00:00
[GH-ISSUE #3245] [Store][Test] PutStartExpiringTest can race with asynchronous eviction under coverage #831
Labels
No labels
ascend
auto-closed
bug
bug
CI/Build
Common
documentation
enhancement
feature request
good first issue
help wanted
high priority
MetaX
nightly-failure
pull-request
PyTorch Backend
question
RFC
Roadmap
stale
Store
Tests
Transfer Engine
No milestone
No project
No assignees
1 participant
Notifications
Due date
No due date set.
Dependencies
No dependencies set.
Reference
kvcache-ai/Mooncake#831
Loading…
Add table
Add a link
Reference in a new issue
No description provided.
Delete branch "%!s()"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Originally created by @Icedcoco on GitHub (Aug 3, 2026).
Original GitHub issue: https://github.com/kvcache-ai/Mooncake/issues/3245
Bug Report
Summary
MasterServiceTest.PutStartExpiringTestfailed in PR #3201 because the test retriesPutStart()after a fixed 50 ms sleep, while the memory eviction that releases expired/discarded replicas runs asynchronously.In the failed CI run, the eviction cycle took approximately 59 ms. The retry therefore happened before eviction completed and before capacity became available.
This appears to be a pre-existing timing-sensitive test rather than a functional regression introduced by PR #3201.
Observed failure
Related PR: https://github.com/kvcache-ai/Mooncake/pull/3201
Failed CI job:
https://github.com/kvcache-ai/Mooncake/actions/runs/30544794003/job/90903216242
Environment:
--coveragemaster_service_testfailedFailure:
The
Bad expected accessexception is secondary. The test uses a non-fatalEXPECT_TRUE()and then immediately calls.value()on the failed result.Test scenario
PutStartExpiringTestconfigures:put_start_discard_timeout_sec = 3put_start_release_timeout_sec = 5After the replicas of
key_2become eligible for discard/release, the test:PutStart(key_2)and expectsNO_AVAILABLE_HANDLE.PutStart(key_2)again and expects success.Relevant test code is around:
mooncake-store/tests/master_service_test.cpp:5460-5473CI timing evidence
The failed job contains the following sequence:
The eviction cycle took approximately 59.3 ms from trigger to completion.
This already exceeds the test's fixed 50 ms wait.
The assertion failed before the
EVICT-RESULTandEVICT-DONEmessages wereemitted, which is consistent with the second
PutStart()running beforediscarded replicas had been released.
The test does not print the error returned by the second
PutStart().NO_AVAILABLE_HANDLEis the most likely result based on the allocation path,but this should be confirmed by improving the assertion diagnostics.
Relevant implementation path
When allocation cannot find enough memory replicas,
AllocateAndInsertMetadata():need_mem_eviction_ = true.ErrorCode::NO_AVAILABLE_HANDLE.The background eviction thread checks this flag asynchronously. It sleeps for
up to 10 ms between checks and then calls
BatchEvict().BatchEvict()scans all 1024 metadata shards, using up to 16 worker threads,joins those workers, and only later calls
ReleaseExpiredDiscardedReplicas(now).There is no synchronization between the test and completion of this eviction
cycle. The test therefore assumes that thread wake-up, shard scanning, and
discarded-replica release will all finish within 50 ms.
Coverage instrumentation and CI load make that assumption unreliable.
The
evicted_count=0log line does not show whether discarded replicas werereleased. That count is separate from the discarded-replica release count, so
it should not be interpreted as evidence that no memory was released.
Relationship to PR #3201
PR #3201 changes only the oplog batch storage, codec, and snapshot tests:
oplog_batch_storage.h/.cppoplog_batch_types.hoplog_batch_codec.cppsnapshot_child_process_test.cppIt does not modify:
master_service.cppmaster_service.hmaster_service_test.cppOther relevant tests, including
master_service_ha_testand all modifiedoplog batch tests, passed in the same CI job.
Therefore, the available evidence indicates that PR #3201 exposed an existing
timing-sensitive test rather than introducing the failure directly.
Local result
The test passed five consecutive iterations in a local non-coverage build:
Local eviction cycles completed in approximately 6-14 ms, so the fixed 50 ms
sleep happened to be sufficient. This difference further supports a
load-sensitive race rather than a deterministic functional failure.
Suggested fix
Replace the fixed 50 ms sleep with a bounded condition-based retry:
MasterServiceTest::WaitUntil()helper.PutStart()until it succeeds or the timeout expires.NO_AVAILABLE_HANDLEas the expected transient result.PutStart()again.ASSERT_TRUE()before accessing.value().Increasing the sleep to another fixed value would only reduce the probability
of failure and would keep the test timing-dependent.
A production change to reorder work inside
BatchEvict()may be worthevaluating separately, but it is not required to make this test deterministic.
Acceptance criteria
PutStartExpiringTestwaits for observable eviction completion instead of afixed delay.
.value()after a non-fatal failed assertion.Before submitting...
@github-actions[bot] commented on GitHub (Aug 3, 2026):
Thanks for opening this issue, @Icedcoco!
102317026A maintainer will triage this when possible. To help us respond faster, please include:
Useful links: Documentation · Contributing guide