Skip to content

fix(universaldb): preserve plain set values#4952

Merged
NathanFlurry merged 1 commit intomainfrom
udb-versionstamp/plain-set-byte-preserving
May 5, 2026
Merged

fix(universaldb): preserve plain set values#4952
NathanFlurry merged 1 commit intomainfrom
udb-versionstamp/plain-set-byte-preserving

Conversation

@NathanFlurry
Copy link
Copy Markdown
Member

Description

Please include a summary of the changes and the related issue. Please also include relevant motivation and context.

Type of change

  • Bug fix (non-breaking change which fixes an issue)
  • New feature (non-breaking change which adds functionality)
  • Breaking change (fix or feature that would cause existing functionality to not work as expected)
  • This change requires a documentation update

How Has This Been Tested?

Please describe the tests that you ran to verify your changes.

Checklist:

  • My code follows the style guidelines of this project
  • I have performed a self-review of my code
  • I have commented my code, particularly in hard-to-understand areas
  • I have made corresponding changes to the documentation
  • My changes generate no new warnings
  • I have added tests that prove my fix is effective or that my feature works
  • New and existing unit tests pass locally with my changes

Copy link
Copy Markdown
Member Author

NathanFlurry commented May 4, 2026

This stack of pull requests is managed by Graphite. Learn more about stacking.

@claude
Copy link
Copy Markdown
Contributor

claude Bot commented May 4, 2026

PR Review: fix(universaldb): preserve plain set values

Overview

This PR fixes a data-corruption bug in universaldb where the plain Set operation would silently corrupt arbitrary binary values that happened to resemble FDB-style incomplete versionstamp markers. It removes the heuristic substitute_versionstamp_if_incomplete function from both the Postgres and RocksDB drivers, renames Operation::Set to Operation::SetValue for clarity, and adds a regression test.


What the bug was

The deleted substitute_versionstamp_if_incomplete function used a fragile heuristic:

  1. Read the last 4 bytes of the value as a little-endian offset.
  2. Look for the byte 0x33 (an FDB tuple-layer escape byte) near that offset.
  3. If found, silently overwrite 10 bytes with a generated versionstamp.

Any arbitrary binary value matching this pattern would be silently corrupted. The comments in both drivers acknowledged this with TODO: versionstamps need to be calculated on the sql side.

The fix is correct: a plain set should always store verbatim bytes. Versionstamp substitution must only happen on an explicit set_versionstamped_value path.


Code quality

  • Rename is correct and complete. All five match sites for Operation::Set across tx_ops.rs, postgres/transaction_task.rs, and rocksdb/transaction_task.rs were updated. No stale references remain. The compiler would catch any miss.
  • Dead code fully removed. substitute_versionstamp_if_incomplete and its imports are gone from both drivers.
  • No enum fall-through. Each driver match arm enumerates variants explicitly. No silent _ => catchall was introduced.

Issues / suggestions

Minor: test comment should clarify WHY this specific byte pattern matters

The test name test_plain_set_preserves_versionstamp_like_binary is good, but a one-line comment inside the function explaining that 0x33 is an FDB tuple escape byte and that the trailing zeroes mimic an incomplete-versionstamp offset would help future readers understand what failure this guards against. Per CLAUDE.md convention, comments should be lowercase complete sentences.

Minor: test comment capitalisation

The inline comment // Test that plain Set stores arbitrary binary values verbatim. should be lowercase per CLAUDE.md.

Observation: versionstamped set path is not covered by this diff

This PR correctly fixes the plain set path. The separate versionstamp set flow is not touched. Appropriate scope for this fix, but worth noting the removed TODO comments implied that path is still not implemented for Postgres/RocksDB.


Test coverage

The new integration test is well-targeted: it stores a value that would have been corrupted by the old heuristic, reads it back, and asserts byte-for-byte equality. It runs as part of run_all_tests for both driver backends and the namespace is cleared after, consistent with the rest of the test suite.


Summary

Straightforward and correct bug fix. The two minor comment style issues are the only non-blocking suggestions. No correctness, performance, or security concerns.

@NathanFlurry NathanFlurry force-pushed the udb-versionstamp/plain-set-byte-preserving branch from 4f8735e to ee08c9b Compare May 4, 2026 15:36
@github-actions
Copy link
Copy Markdown
Contributor

github-actions Bot commented May 4, 2026

Preview packages published to npm

Install with:

npm install rivetkit@pr-4952

All packages published as 0.0.0-pr.4952.43f6721 with tag pr-4952.

Engine binary is shipped via @rivetkit/engine-cli on linux-x64-musl, linux-arm64-musl, darwin-x64, and darwin-arm64. Windows users should use the release installer or set RIVET_ENGINE_BINARY.

Docker images:

docker pull rivetdev/engine:slim-43f6721
docker pull rivetdev/engine:full-43f6721
Individual packages
npm install rivetkit@pr-4952
npm install @rivetkit/react@pr-4952
npm install @rivetkit/rivetkit-napi@pr-4952
npm install @rivetkit/workflow-engine@pr-4952

@NathanFlurry NathanFlurry marked this pull request as ready for review May 5, 2026 11:24
Base automatically changed from udb-versionstamp/fix-operand-encoding to main May 5, 2026 14:58
@NathanFlurry NathanFlurry merged commit ee08c9b into main May 5, 2026
20 of 23 checks passed
@NathanFlurry NathanFlurry deleted the udb-versionstamp/plain-set-byte-preserving branch May 5, 2026 14:58
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.

1 participant