[Bugfix] Preserve empty values in Mooncake Store REST GET#2587
Conversation
There was a problem hiding this comment.
Code Review
This pull request updates the handle_get method in mooncake_store_service.py to check if the retrieved value is explicitly None instead of evaluating its truthiness. This allows empty values, such as empty bytes, to be successfully returned with a 200 OK status rather than incorrectly triggering a 404 Not Found error. The mock Response class and the test case test_handle_get_empty_bytes in the test suite have been updated to support and verify this new behavior. There are no review comments to address, and I have no feedback to provide.
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.
|
Codecov Report✅ All modified and coverable lines are covered by tests. 📢 Thoughts on this report? Let us know! |
| value = self.store.get(key) | ||
|
|
||
| if not value: | ||
| if value is None: |
There was a problem hiding this comment.
The fix assumes self.store.get(key) returns None for a missing key, but the real MooncakeDistributedStore.get() binding returns zero-length bytes when get_buffer(key) is null. With the new if value is None check, a real missing key falls through and returns 200 with an empty body instead of 404.
The updated unit test passes because the fake store models missing keys as None, which does not match the real binding behavior. Please either change the binding contract so missing keys return None, or make handle_get() distinguish existence separately, for example by checking is_exist(key) before returning b"" as a valid stored value.
There was a problem hiding this comment.
Thanks for catching this. I updated the REST GET path to use the binding's existence contract instead of using the value truthiness/None result to decide whether to return 404.
handle_get() now checks self.store.is_exist(key) first, returns 404 when it returns 0, returns 500 on a negative existence-check result, and only then calls get(). Empty bytes are preserved as a valid 200 response for existing keys. I also added a second existence check when get() returns b"" so the REST handler does not turn a missing/null buffer into a false 200 response.
The unit tests now model the real binding behavior: the missing-key case uses is_exist == 0 while get() may still be b"". I also added coverage for existence-check failure, unexpected None from get(), and the empty-byte ambiguity after get().
Validation:
Ran 7 focused GET handler tests in 0.017s
OK
git diff --check also passes locally, with only Windows LF/CRLF warnings.
Lin-z-w
left a comment
There was a problem hiding this comment.
Thanks for the fix. LGTM.
handle_exist used bool(is_exist(key)) to build the response body.
is_exist() returns 0 (not found), a positive integer (found), or a
negative integer (store error). bool(-1) is True, so a store error was
silently surfaced as HTTP 200 {"exists": true} instead of HTTP 500.
Fix: check exists < 0 and return 500 "Exist check failed", mirroring
the pattern introduced for handle_get in kvcache-ai#2587. Also replace bool(exists)
with exists > 0 for clarity.
Adds test_handle_exist_store_error to cover the previously untested
negative-return path.
Signed-off-by: Yufeng He <40085740+he-yufeng@users.noreply.github.com>
…#2587) Co-authored-by: VectorPeak <VectorPeak@users.noreply.github.com>
Description
This PR fixes a value-preservation bug in the Mooncake Store REST API
GET /api/get/{key}path. The handler previously treated an empty byte payload as a missing key, so a value that could be stored through the REST API could not be read back reliably.The original REST read path used the value returned by
self.store.get(key)to decide whether the key existed:That check conflates two different states: an existing empty byte payload (
b"") and an absent object. Reviewer feedback also pointed out that the realMooncakeDistributedStore.get()binding may return zero-length bytes when the underlyingget_buffer(key)result is null, soget()alone is not a reliable existence signal.The updated handler now uses the store's explicit existence API before reading the value:
For empty byte values, the handler re-checks existence after
get()returnsb"". This keeps valid stored empty payloads readable while avoiding a false200response when the binding surfaces a missing/null buffer as zero-length bytes.Changes Made
Nonechecks toself.store.is_exist(key).b""as a valid200response body for existing keys.500whenis_exist()reports a negative error or whenget()unexpectedly returnsNoneafter a successful existence check.is_exist(key) == 0whileget(key)may still beb"".Nonefromget(), and the empty-byte ambiguity afterget().Evidence
The original bug can be reproduced with an isolated handler-style case where the store returns an existing empty byte payload:
Before this fix, the handler evaluated
b""as false and returned the missing-key branch:After this fix, the key existence check distinguishes an existing empty payload from a missing key:
A real missing key is represented by
is_exist(key) == 0and still returns404 Key not foundeven ifget(key)would produceb"".Possible Call Chain / Impact
The affected path is the Mooncake Store REST API read flow:
This PR only changes the REST GET response decision for values returned through the REST shim. It does not change writes, deletion, mounting, store setup, or the underlying Mooncake distributed store APIs.
Module
mooncake-transfer-engine)mooncake-store)mooncake-ep)mooncake-pg)mooncake-integration)mooncake-p2p-store)mooncake-wheel)mooncake-common)mooncake-rl)Type of Change
How Has This Been Tested?
Test commands:
Test results:
Targeted GET handler tests passed:
git diff --checkpassed with no patch errors. It emitted Windows line-ending warnings only.I also ran the full
mooncake-wheel.tests.test_mooncake_store_service_apifile locally before this update. It had unrelated existing failures aroundhandle_put_missing_valueand unmount call expectations, so I did not include that as a passing validation claim.Checklist
./scripts/code_format.shpre-commit run --all-filesand all hooks passAI Assistance Disclosure
AI assistance was used to identify the edge case, make the handler/test updates, respond to review feedback, and draft this PR description. The submitter is responsible for reviewing and validating the final changes.