Repository navigation
feat: add replaceWithVersion (0x09/0x0A) version-based conditional replace - #4
Merged
Merged
Conversation
…place Implements replaceIfUnmodified — replace an entry's value only if its version matches the supplied version (from getWithMetadata). Completes the version-based writes of Step 10; conditionals (putIfAbsent/replace/ containsKey) remain. - Add REPLACE_WITH_VERSION_REQUEST/RESPONSE opcodes (0x09/0x0A). - RemoteCache::replaceWithVersion(key, value, version, lifespan=0, maxIdle=0) returns future<bool>, matching Java boolean replaceWithVersion(...): true for status 0x00/0x03, false for 0x01 (modified) / 0x02 (no such key). - Request = key + expiration byte + [lifespan] + [maxIdle] + version(s8) + value, reusing PUT's expiration encoding and Codec::writeLong for version. - Parser drains *_WITH_PREVIOUS (0x03/0x04) body defensively (FORCE_RETURN_ VALUE not yet wired), consistent with removeWithVersion. Schema bug found: hotrod40.ksy replace_if_unmodified_request packs the expiration time_units nibbles in the opposite order from put_request/ expiration_params (lifespan and maxIdle swapped). Java uses one shared writeExpirationParams for both PUT and replaceWithVersion, so PUT's order (high nibble = lifespan, low = maxIdle) is authoritative and is what this client implements. Documented in STATUS.md; upstream schema fix pending. Tests: 5 unit (ReplaceWithVersionTest, incl. all four expiration nibble combinations) + 5 integration (ReplaceWithVersionIntegrationTest). Full suite: unit 165/165, integration green against Docker Infinispan. Clean under Release + -Werror -Wall -Wextra. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Implements
replaceWithVersion(replaceIfUnmodified, opcodes0x09/0x0A) — replaces an entry's value only if its version matches the supplied version (fromgetWithMetadata). Completes the version-based writes of Step 10; the remaining Step 10 items are the conditionals (putIfAbsent/replace/containsKey).Changes
REPLACE_WITH_VERSION_REQUEST = 0x09,REPLACE_WITH_VERSION_RESPONSE = 0x0A.RemoteCache::replaceWithVersion(key, value, version, lifespan=0, maxIdle=0)→std::future<bool>, matching Java'sboolean replaceWithVersion(...):truefor status0x00/0x03,falsefor0x01(modified) /0x02(no such key), throws otherwise.key+ expiration byte +[lifespan vLong]+[maxIdle vLong]+version (s8)+value, reusing PUT's expiration encoding and the existingCodec::writeLongfor the version.*_WITH_PREVIOUShandling (0x03/0x04) consistent withremoveWithVersion, for whenFORCE_RETURN_VALUEis wired later.hotrod40.ksyreplace_if_unmodified_requestpacks the expirationtime_unitsnibbles in the opposite order fromput_request/expiration_params(lifespan ↔ maxIdle swapped). Java uses one sharedwriteExpirationParamsfor both PUT and replaceWithVersion (TimeUnitParam.encodeTimeUnits = (encodedLifespan << 4) | encodedMaxIdle), so PUT's order — high nibble = lifespan, low = maxIdle — is authoritative and is what this client implements. Noted inSTATUS.md(Kaitai section + deliverable); upstream schema fix pending in hotrod-dissector.This is exactly the tri-leg cross-check the repo prescribes: client vs Java vs schema disagreed → the schema had the bug.
Tests
ReplaceWithVersionTest): all four expiration nibble combinations (default/lifespan-only/maxIdle-only/both), version placement, opcode constants.ReplaceWithVersionIntegrationTest, Docker Infinispan): matching version replaces; stale version doesn't replace and original survives; missing key not created; version advances across chained CAS; post-disconnect throws.-Werror -Wall -Wextra.🤖 Generated with Claude Code