Skip to content

Streaming Compression support for RDB - #3531

Merged
hpatro merged 2 commits into
valkey-io:unstablefrom
sarthakaggarwal97:streaming-compression-rio-pr
Aug 17, 2026
Merged

hpatro merged 2 commits into
valkey-io:unstablefrom
sarthakaggarwal97:streaming-compression-rio-pr

Conversation

@sarthakaggarwal97

@sarthakaggarwal97 sarthakaggarwal97 commented Apr 17, 2026 •

Copy link
Copy Markdown
Contributor

Related to #3195

Overview

Today, rdbcompression yes applies legacy LZF compression to individual string payloads inside an otherwise plain RDB stream. This PR adds Valkey Compressed Stream (VCS) support for on-disk RDB persistence, with lz4 as the first supported whole-stream codec.

Setting rdbcompression lz4 wraps the complete logical RDB in a small VCS envelope and compresses it as a single LZ4 frame through the existing rio. The default remains yes, preserving the existing plain RDB format and per-string LZF behavior.

During loading, the RDB path probes the input before normal parsing begins. Plain RDB input is replayed unchanged, while a valid VCS envelope attaches an LZ4 stream reader that transparently decodes the logical RDB. Malformed, incompatible, and truncated compressed streams are rejected.
When rdbchecksum yes, LZ4 frame checksums also detect corrupted content. As with legacy plain RDB files, bytes after the logical end of the RDB are ignored.

Architecture

+------------------------+       +------------------------------+       +----------------------+
|    RDB save/load       |       |    rio + stream transform    |       |    file backend      |
|                        |       |                              |       |                      |
| rdbSaveRio             |------>| rioWrite -> streamWriter     |------>| dump.rdb             |
| rdbLoadRio             |<------| rioRead  <- streamReader     |<------| dump.rdb             |
| rdbSaveRawString       |       | VCS envelope + codec state   |       |                      |
| valkey-check-rdb       |       | logical/physical accounting  |       |                      |
+------------------------+       +------------------------------+       +----------------------+

The stream writer or reader is attached directly to the existing rio. Encoded I/O reaches the concrete file backend through raw rio operations, avoiding recursive stream dispatch while keeping normal RDB parsing unchanged.

Key Design Decisions

  1. Whole-stream compression is implemented as an optional transform attached to rio, rather than as a separate RIO wrapper or part of object serialization.
  2. VCS adds a seven-byte envelope before the compressed payload so loaders can classify the stream before normal RDB parsing begins.
  3. lzf remains the default, preserving the existing plain RDB format and compatibility.
  4. Per-string LZF is skipped while whole-stream compression is active, so compression modes are not stacked.
  5. The envelope version, codec, reserved byte, and stream_kind are validated before decoding.
  6. rdbLoad, valkey-check-rdb, and startup loading transparently support both plain and VCS-wrapped RDB files.
  7. Streaming compression applies only to on-disk snapshots in this PR. Replication full synchronization and AOF RDB preambles continue to use the plain RDB format.
  8. Logical RDB bytes and physical stream bytes are accounted for separately so save and load progress retain the correct semantics.

Data Flow: Save Path

rdbSave()
   |
   | if rdbcompression=lz4
   | and this is not a replication RDB
   v
rioInitWithFile(...)
   |
   | attach streamWriter
   | write VCS envelope lazily
   | rioWrite(logical RDB bytes)
   |        |
   |        v
   | streamWriter -> LZ4 frame -> rioWriteRaw
   v
dump.rdb

Important notes:

  • The VCS envelope stores magic, version, codec, a reserved byte, and stream_kind.
  • For compressed frames, rdbchecksum yes enables both LZ4 block and content XXH32 checksums, rdbchecksum no omits them.
  • The logical RDB CRC64 trailer is zero for VCS input. rdbchecksum controls CRC64 generation and validation for plain RDB files, and LZ4 checksum generation and validation for compressed RDB files.
  • The compression frame is finalized before the file is flushed and synchronized.
  • When whole-stream compression is active, the existing per-string LZF path is bypassed.

Data Flow: Load Path

rdbLoad() / valkey-check-rdb
   |
   | initialize file rio
   | attach probing streamReader
   | read VCS_ENVELOPE_SIZE bytes incrementally
   v
[plain RDB] ------------------------> replay probe bytes -> passthrough -> RDB parser
[valid VCS + RDB stream kind] -----> LZ4 decode ----------------> RDB parser
[malformed/incompatible VCS] ------> fail early
   |
   | after normal RDB parsing
   v
validate frame completion, configured checksums, and truncation

The RDB parser continues to consume logical bytes through the same rio. For compressed input, physical source progress is tracked separately from decoded output progress.

This PR is intentionally scoped to on-disk RDB streaming compression and the persistence, loading, and validation paths that need to understand it. It does not add replication compression or diskless full-sync capability negotiation.

Benchmarks

Benchmarked on r7g.2xlarge (Graviton, 8 vCPUs, 61GB RAM, NVMe). All results averaged over 3 repeats.

Datasets

  • Improved Realistic JSON: Synthetic JSON with natural language text and varied field types. This data is more compressible due to natural language. Tested at 100B–10KB value sizes.
final_improved_combined
  • BlockMesh Tweets — 1M/5M unique real tweets from BlockMesh/tweets. Multilingual, avg ~270B, zero cross-key repetition.
final_blockmesh_combined

Notes:

  1. LZ4 streaming beats LZF on every metric at every size. 30-77% faster saves, 24-73% faster loads, 45-73% smaller RDBs.
  2. LZ4 library is currently vendored from https://github.com/lz4/lz4. The decision was taken here [NEW] RDB Compression via LZ4, Batching, and Batch-Level Dictionary #1962 (comment)

@codecov

codecov Bot commented Apr 18, 2026 •

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 93.37884% with 97 lines in your changes missing coverage. Please review.
✅ Project coverage is 78.75%. Comparing base (4669926) to head (9a54fba).

Files with missing lines Patch % Lines
src/unit/test_compression.cpp 96.78% 27 Missing ⚠ïļ
src/valkey-check-rdb.c 74.02% 20 Missing ⚠ïļ
src/rdb.c 83.92% 18 Missing ⚠ïļ
src/compression.c 78.18% 12 Missing ⚠ïļ
src/compression_stream.c 95.25% 11 Missing ⚠ïļ
src/rio.c 86.79% 7 Missing ⚠ïļ
src/compression_lz4.c 97.22% 2 Missing ⚠ïļ
Additional details and impacted files
@@             Coverage Diff              @@
##           unstable    #3531      +/-   ##
============================================
+ Coverage     78.51%   78.75%   +0.23%     
============================================
  Files           166      170       +4     
  Lines         88381    89782    +1401     
============================================
+ Hits          69390    70705    +1315     
- Misses        18991    19077      +86     
Files with missing lines Coverage Δ
src/config.c 79.90% <Ãļ> (Ãļ)
src/rdb.h 100.00% <Ãļ> (Ãļ)
src/rio.h 97.95% <100.00%> (-2.05%) ⮇ïļ
src/server.h 100.00% <Ãļ> (Ãļ)
src/compression_lz4.c 97.22% <97.22%> (Ãļ)
src/rio.c 85.76% <86.79%> (+1.50%) ⮆ïļ
src/compression_stream.c 95.25% <95.25%> (Ãļ)
src/compression.c 78.18% <78.18%> (Ãļ)
src/rdb.c 77.24% <83.92%> (-0.02%) ⮇ïļ
src/valkey-check-rdb.c 72.85% <74.02%> (+1.32%) ⮆ïļ
... and 1 more

... and 14 files with indirect coverage changes

🚀 New features to boost your workflow:
  • ❄ïļ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • ðŸ“Ķ JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

@sarthakaggarwal97 sarthakaggarwal97 changed the title Compression: Add Streaming RIO-based RDB compression Add Streaming Compression support for RDB Apr 20, 2026
@sarthakaggarwal97 sarthakaggarwal97 changed the title Add Streaming Compression support for RDB Streaming Compression support for RDB Apr 20, 2026
@sarthakaggarwal97
sarthakaggarwal97 marked this pull request as ready for review April 21, 2026 16:13
@sarthakaggarwal97
sarthakaggarwal97 force-pushed the streaming-compression-rio-pr branch 3 times, most recently from a241fd7 to 6af049a Compare April 27, 2026 15:47
@github-actions

Copy link
Copy Markdown

❌ Provenance Check Alert

Potential code similarities detected with upstream repository.

  • 2026-04-27 15:48:12 [INFO] - matches redis/redis PR #14433 (similarity: 0.992, method: file_simhash+deep)
  • 2026-04-27 15:48:12 [INFO] - matches redis/redis PR #14609 (similarity: 0.992, method: file_simhash+deep)
  • 2026-04-27 15:48:12 [INFO] - matches redis/redis PR #14435 (similarity: 0.992, method: file_simhash+deep)

This check was performed automatically by the Provenance Guard Action.

@xdk-amz xdk-amz left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Overall looks good but recommend separating RDB checksum concerns from compression checksum concerns and letting operators decide what combination they want instead of mixing the handling between the two modules. I would like to see some exploration on the lz4 configs I commented on as well as some defensive fixes to potentially unsafe code + other nits.

Comment thread src/aof.c Resolved
Comment thread src/aof.c Resolved
Comment thread src/rio.c Resolved
Comment thread src/rdb.c Resolved
Comment thread src/compression_rio.c Resolved
Comment thread src/compression_lz4.c Resolved
Comment thread src/compression_stream.c Resolved
Comment thread src/compression_lz4.c Resolved
Comment thread src/compression_lz4.c Resolved
Comment thread src/compression_stream.c Resolved
@sarthakaggarwal97

sarthakaggarwal97 commented May 5, 2026 •

Copy link
Copy Markdown
Contributor Author

Benchmarks with using RDB checksum as is over logical RDB Stream:

LZ4@0 Save (ms): CRC over logical stream vs LZ4 Block Checksum only over 1M Keys:

Value Size LZ4 Block Checksum CRC + Block Checksum Overhead
100B 489 628 +28%
256B 890 1062 +19%
512B 1464 1773 +21%
1024B 2228 2798 +26%
10KB 13778 17705 +28%

LZ4@0 Load (ms):

Size LZ4 Block Checksum CRC + Block Checksum Overhead
100B 641 764 +19%
256B 840 1050 +25%
512B 1260 1582 +26%
1024B 1910 2447 +28%
10KB 13061 15852 +21%

@sarthakaggarwal97

Copy link
Copy Markdown
Contributor Author
image image image image

@coderabbitai

coderabbitai Bot commented May 12, 2026 •

Copy link
Copy Markdown
Contributor

Review Change Stack

Note

Reviews paused

It looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the reviews.auto_review.auto_pause_after_reviewed_commits setting.

Use the following commands to manage reviews:

  • @coderabbitai resume to resume automatic reviews.
  • @coderabbitai review to trigger a single review.

Use the checkboxes below for quick actions:

  • â–ķïļ Resume reviews
  • 🔍 Trigger review
📝 Walkthrough

Walkthrough

Adds streaming LZ4 compression for RDB files, including vendored codec sources, VCS framing, RIO integration, save/load and checker support, configuration changes, build wiring, and unit/integration tests for normal and corrupted streams.

Changes

Streaming LZ4 RDB support

Layer / File(s) Summary
Vendored LZ4 codec
deps/lz4/*
Adds LZ4 block, HC, frame, xxHash implementations, public headers, licensing, and local build rules.
Build integration
cmake/..., deps/CMakeLists.txt, deps/Makefile, src/CMakeLists.txt, src/Makefile, src/unit/*
Builds and links LZ4 and compiles the new compression sources.
Streaming compression pipeline
src/compression*
Adds LZ4 streaming lifecycle, VCS envelopes, writer/reader buffering, passthrough handling, checksum options, and strict frame-end validation.
RIO and RDB integration
src/rio*, src/rdb*, src/config.c, src/server.h, src/aof.c, src/replication.c
Adds partial reads, stream decorators, compression modes, compressed RDB save/load handling, progress/checksum behavior, and AOF format decisions.
Compressed RDB checker
src/valkey-check-rdb.c
Routes RDB validation through streaming readers and validates compressed stream completion and errors.
Validation and documentation
src/unit/test_compression.cpp, tests/integration/*, valkey.conf
Adds unit and integration coverage for round trips, corruption, checksums, replication, configuration, and compatibility behavior.

Estimated code review effort: 5 (Critical) | ~120 minutes

Sequence Diagram(s)

sequenceDiagram
  participant RDBSave
  participant rio
  participant streamWriter
  participant LZ4
  participant streamReader
  participant RDBLoad
  RDBSave->>rio: write RDB bytes
  rio->>streamWriter: transform payload
  streamWriter->>LZ4: emit framed LZ4 data
  streamReader->>LZ4: decode framed data
  streamReader->>rio: provide decoded bytes
  rio->>RDBLoad: load RDB data
Loading
ðŸšĨ Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠ïļ Warning Docstring coverage is 29.83% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
Title check ✅ Passed The title clearly summarizes the primary change: adding streaming compression support for RDB files.
Description check ✅ Passed The description directly explains the VCS and LZ4 RDB streaming compression changes, architecture, behavior, tests, and benchmarks.

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

âĪïļ Share

Comment @coderabbitai help to get the list of available commands.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠ïļ Outside diff range comments (2)
src/aof.c (1)

1009-1054: ⚠ïļ Potential issue | 🟠 Major | ⚡ Quick win

Please request @core-team architectural review for this aof.c behavior change.

This changes AOF/RDB sync-restart behavior (including fallback policy), which should get explicit core-team architectural sign-off before merge.

As per coding guidelines, "Request @core-team architectural review for changes to cluster*.c, replication.c, rdb.c, or aof.c".

ðŸĪ– Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/aof.c` around lines 1009 - 1054, The change in aof.c modifies AOF/RDB
sync-restart behavior (in functions restartAOFWithSyncRdb and
rdbFileUsesStreamingCompression) and the fallback policy when a
streamed-compressed RDB is detected; request an explicit architectural review
from `@core-team` before merging by adding a review request or TODO in the PR and
code comments referencing restartAOFWithSyncRdb and
rdbFileUsesStreamingCompression so core-team can approve the behavioral change,
and ensure the PR description summarizes the new fallback logic (fall back to
BGREWRITEAOF when streaming compression is detected) for their sign-off.
src/rdb.c (1)

3689-3695: ⚠ïļ Potential issue | ðŸŸĄ Minor | ⚡ Quick win

Differentiate VKCS loads from checksum-disabled RDBs in this notice.

RIO_FLAG_SKIP_RDB_CHECKSUM now also covers the streaming-compressed path, so this branch will log that checksums were disabled even when integrity is coming from the codec layer. That makes load diagnostics misleading.

Suggested fix
-            if (rdb->flags & RIO_FLAG_SKIP_RDB_CHECKSUM) {
-                serverLog(LL_NOTICE, "RDB file was saved with checksum disabled: skipped checksum for this transfer");
+            if ((rdb->flags & RIO_FLAG_STREAMING_COMPRESSION) &&
+                (rdb->flags & RIO_FLAG_SKIP_RDB_CHECKSUM)) {
+                serverLog(LL_NOTICE,
+                          "Skipping logical RDB checksum for streaming-compressed input");
+            } else if (rdb->flags & RIO_FLAG_SKIP_RDB_CHECKSUM) {
+                serverLog(LL_NOTICE,
+                          "RDB file was saved with checksum disabled: "
+                          "skipped checksum for this transfer");
             } else if (cksum == 0) {
ðŸĪ– Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/rdb.c` around lines 3689 - 3695, The notice incorrectly attributes
checksum skipping to RIO_FLAG_SKIP_RDB_CHECKSUM even for streaming-compressed
(VKCS) loads; update the branch in rdb.c (where server.rdb_checksum,
server.skip_checksum_validation, memrev64ifbe, rdb->flags and
RIO_FLAG_SKIP_RDB_CHECKSUM are handled) to detect when the input is coming from
a streaming-compressed/codec-backed path (e.g., check the RIO or codec metadata
on rdb to see if a VKCS/streaming codec provided integrity) and emit a distinct
serverLog message for that case versus a true checksum-disabled RDB; keep the
existing behavior for cksum==0 and cksum!=expected, but split the
RIO_FLAG_SKIP_RDB_CHECKSUM branch into two paths (codec-backed integrity vs.
checksum-disabled file) with appropriate, different log text.
ðŸ§đ Nitpick comments (3)
src/compression_lz4.h (1)

12-28: ⚡ Quick win

Add API contract comments for exported LZ4 entry points.

These declarations are public-facing but currently undocumented at function level (ownership, error model, buffer/input-consumed guarantees). Please add concise contract comments to prevent misuse.

As per coding guidelines "Document why code exists, not just what it does; document all functions in C code".

ðŸĪ– Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/compression_lz4.h` around lines 12 - 28, Add concise API contract
comments above each exported LZ4 function declaration
(compressionLz4CompressorInit, compressionLz4CompressorDestroy,
compressionLz4DecompressorInit, compressionLz4DecompressorDestroy,
compressionLz4OutputBound, compressionLz4CompressFeed,
compressionLz4DecompressFeed) that describe ownership semantics (who
allocates/frees streamCompressor/streamDecompressor and buffer pointers), the
error model and possible return values (success codes vs negative error codes),
guarantees about how much output will be produced or bounded (for
compressionLz4OutputBound and CompressFeed), and for decompression functions
explicitly state how input_consumed is set and when callers must retry vs drop
input; keep each comment short, consistent, and focused on why the function
contract exists (caller responsibilities, lifetime, and failure behavior).
deps/lz4/Makefile (1)

26-28: ⚡ Quick win

Declare clean as phony.

If a file named clean appears in this directory, make clean can silently no-op. Add .PHONY: clean for reliable cleanup.

ðŸĪ– Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@deps/lz4/Makefile` around lines 26 - 28, The Makefile target "clean" should
be declared phony to avoid being skipped if a file named "clean" exists; update
the Makefile by adding a .PHONY declaration for the clean target (e.g., add
".PHONY: clean") so that the clean rule (which removes *.o and *.a) always runs.
src/rdb.c (1)

3150-3197: ⚡ Quick win

Make the new rdbInputStream* helpers file-local.

These helpers are only referenced inside src/rdb.c, so exporting them widens the symbol surface for no gain.

Suggested fix
-void rdbInputStreamInit(rdbInputStream *input, rio *raw_rio) {
+static void rdbInputStreamInit(rdbInputStream *input, rio *raw_rio) {
@@
-decompressRioInitResult rdbInputStreamPrepare(rdbInputStream *input) {
+static decompressRioInitResult rdbInputStreamPrepare(rdbInputStream *input) {
@@
-void rdbInputStreamDestroy(rdbInputStream *input) {
+static void rdbInputStreamDestroy(rdbInputStream *input) {
@@
-int rdbInputStreamValidateEnd(rdbInputStream *input) {
+static int rdbInputStreamValidateEnd(rdbInputStream *input) {
@@
-bool rdbRioHasCorruptCompressedInput(const rio *rdb) {
+static bool rdbRioHasCorruptCompressedInput(const rio *rdb) {

As per coding guidelines, "Use static keyword for file-local functions in C code"

ðŸĪ– Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/rdb.c` around lines 3150 - 3197, Mark the helper functions as file-local
by adding the static storage specifier to their definitions: rdbInputStreamInit,
rdbInputStreamPrepare, rdbInputStreamDestroy, rdbInputStreamValidateEnd, and
rdbRioHasCorruptCompressedInput. Leave the rdbInputStream type and any external
declarations untouched; only change the function declarations/definitions to
static so these helpers are not exported from the object file.
ðŸĪ– Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@deps/lz4/lz4frame.c`:
- Around line 1619-1621: LZ4F_decompress performs pointer arithmetic on
srcBuffer without checking for NULL; add a guard at the start of LZ4F_decompress
to handle srcBuffer == NULL (or *srcSizePtr == 0) before computing
srcStart/srcEnd/srcPtr so you never do NULL + offset arithmetic; if srcBuffer is
NULL or *srcSizePtr == 0, initialize srcStart/srcEnd/srcPtr to a safe
non-dereferenced value (or skip computing srcEnd) and ensure subsequent logic
(e.g., the frame parsing path exercised by LZ4F_getFrameInfo calling
LZ4F_decompress with NULL/0) treats this as an empty input rather than
performing pointer arithmetic or dereferencing.

In `@src/compression_rio.c`:
- Around line 89-100: compressRioFlush and compressRioFinish currently mark the
stream writer errored but do not set the rio-level write error flag, so update
both functions (compressRioFlush and compressRioFinish) to set
RIO_FLAG_WRITE_ERROR on the rio when any flush/finalize failure occurs;
specifically, when streamWriterIsErrored(cr->writer) is detected, when
streamWriterFlush(cr->writer) != 0, and when
cr->inner->flush/cr->inner->finalize returns 0, set the rio flag (e.g., r->flags
|= RIO_FLAG_WRITE_ERROR or call the existing helper to mark rio write error) in
addition to calling streamWriterSetError(cr->writer) so callers relying on the
rio flag see the error.

---

Outside diff comments:
In `@src/aof.c`:
- Around line 1009-1054: The change in aof.c modifies AOF/RDB sync-restart
behavior (in functions restartAOFWithSyncRdb and
rdbFileUsesStreamingCompression) and the fallback policy when a
streamed-compressed RDB is detected; request an explicit architectural review
from `@core-team` before merging by adding a review request or TODO in the PR and
code comments referencing restartAOFWithSyncRdb and
rdbFileUsesStreamingCompression so core-team can approve the behavioral change,
and ensure the PR description summarizes the new fallback logic (fall back to
BGREWRITEAOF when streaming compression is detected) for their sign-off.

In `@src/rdb.c`:
- Around line 3689-3695: The notice incorrectly attributes checksum skipping to
RIO_FLAG_SKIP_RDB_CHECKSUM even for streaming-compressed (VKCS) loads; update
the branch in rdb.c (where server.rdb_checksum, server.skip_checksum_validation,
memrev64ifbe, rdb->flags and RIO_FLAG_SKIP_RDB_CHECKSUM are handled) to detect
when the input is coming from a streaming-compressed/codec-backed path (e.g.,
check the RIO or codec metadata on rdb to see if a VKCS/streaming codec provided
integrity) and emit a distinct serverLog message for that case versus a true
checksum-disabled RDB; keep the existing behavior for cksum==0 and
cksum!=expected, but split the RIO_FLAG_SKIP_RDB_CHECKSUM branch into two paths
(codec-backed integrity vs. checksum-disabled file) with appropriate, different
log text.

---

Nitpick comments:
In `@deps/lz4/Makefile`:
- Around line 26-28: The Makefile target "clean" should be declared phony to
avoid being skipped if a file named "clean" exists; update the Makefile by
adding a .PHONY declaration for the clean target (e.g., add ".PHONY: clean") so
that the clean rule (which removes *.o and *.a) always runs.

In `@src/compression_lz4.h`:
- Around line 12-28: Add concise API contract comments above each exported LZ4
function declaration (compressionLz4CompressorInit,
compressionLz4CompressorDestroy, compressionLz4DecompressorInit,
compressionLz4DecompressorDestroy, compressionLz4OutputBound,
compressionLz4CompressFeed, compressionLz4DecompressFeed) that describe
ownership semantics (who allocates/frees streamCompressor/streamDecompressor and
buffer pointers), the error model and possible return values (success codes vs
negative error codes), guarantees about how much output will be produced or
bounded (for compressionLz4OutputBound and CompressFeed), and for decompression
functions explicitly state how input_consumed is set and when callers must retry
vs drop input; keep each comment short, consistent, and focused on why the
function contract exists (caller responsibilities, lifetime, and failure
behavior).

In `@src/rdb.c`:
- Around line 3150-3197: Mark the helper functions as file-local by adding the
static storage specifier to their definitions: rdbInputStreamInit,
rdbInputStreamPrepare, rdbInputStreamDestroy, rdbInputStreamValidateEnd, and
rdbRioHasCorruptCompressedInput. Leave the rdbInputStream type and any external
declarations untouched; only change the function declarations/definitions to
static so these helpers are not exported from the object file.
🊄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

â„đïļ Review info
⚙ïļ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: a47a8b43-59a8-4016-a872-af1fde59642c

ðŸ“Ĩ Commits

Reviewing files that changed from the base of the PR and between 6c9d7fc and ae21623.

📒 Files selected for processing (40)
  • cmake/Modules/SourceFiles.cmake
  • cmake/Modules/ValkeySetup.cmake
  • deps/CMakeLists.txt
  • deps/Makefile
  • deps/lz4/CMakeLists.txt
  • deps/lz4/LICENSE
  • deps/lz4/Makefile
  • deps/lz4/lz4.c
  • deps/lz4/lz4.h
  • deps/lz4/lz4frame.c
  • deps/lz4/lz4frame.h
  • deps/lz4/lz4hc.c
  • deps/lz4/lz4hc.h
  • deps/lz4/xxhash.c
  • deps/lz4/xxhash.h
  • src/CMakeLists.txt
  • src/Makefile
  • src/aof.c
  • src/compression.c
  • src/compression.h
  • src/compression_lz4.c
  • src/compression_lz4.h
  • src/compression_rio.c
  • src/compression_rio.h
  • src/compression_stream.c
  • src/compression_stream.h
  • src/config.c
  • src/rdb.c
  • src/rdb.h
  • src/rio.c
  • src/rio.h
  • src/server.h
  • src/unit/CMakeLists.txt
  • src/unit/Makefile
  • src/unit/test_compression.cpp
  • src/valkey-check-rdb.c
  • tests/integration/rdb-compression.tcl
  • tests/integration/replication-aof-sync.tcl
  • tests/integration/valkey-check-rdb.tcl
  • valkey.conf

Comment thread deps/lz4/lz4frame.c Resolved
Comment thread src/compression_rio.c Resolved
Comment thread valkey.conf Resolved
@sarthakaggarwal97
sarthakaggarwal97 force-pushed the streaming-compression-rio-pr branch 2 times, most recently from 2d6bfae to b494e19 Compare May 12, 2026 23:59

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

ðŸĪ– Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@deps/lz4/Makefile`:
- Around line 26-28: The Makefile's clean target (target name "clean") should be
declared phony to avoid being skipped if a file named "clean" exists; add a
.PHONY declaration for the clean target (e.g., add a line declaring .PHONY:
clean) near the top or before the clean target so make always runs the clean
recipe (rm -f *.o and rm -f *.a).
🊄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

â„đïļ Review info
⚙ïļ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro Plus

Run ID: ebf9c0e3-08ee-4c87-a906-6a8e31eb4a87

ðŸ“Ĩ Commits

Reviewing files that changed from the base of the PR and between ae21623 and b494e19.

📒 Files selected for processing (40)
  • cmake/Modules/SourceFiles.cmake
  • cmake/Modules/ValkeySetup.cmake
  • deps/CMakeLists.txt
  • deps/Makefile
  • deps/lz4/CMakeLists.txt
  • deps/lz4/LICENSE
  • deps/lz4/Makefile
  • deps/lz4/lz4.c
  • deps/lz4/lz4.h
  • deps/lz4/lz4frame.c
  • deps/lz4/lz4frame.h
  • deps/lz4/lz4hc.c
  • deps/lz4/lz4hc.h
  • deps/lz4/xxhash.c
  • deps/lz4/xxhash.h
  • src/CMakeLists.txt
  • src/Makefile
  • src/aof.c
  • src/compression.c
  • src/compression.h
  • src/compression_lz4.c
  • src/compression_lz4.h
  • src/compression_rio.c
  • src/compression_rio.h
  • src/compression_stream.c
  • src/compression_stream.h
  • src/config.c
  • src/rdb.c
  • src/rdb.h
  • src/rio.c
  • src/rio.h
  • src/server.h
  • src/unit/CMakeLists.txt
  • src/unit/Makefile
  • src/unit/test_compression.cpp
  • src/valkey-check-rdb.c
  • tests/integration/rdb-compression.tcl
  • tests/integration/replication-aof-sync.tcl
  • tests/integration/valkey-check-rdb.tcl
  • valkey.conf
✅ Files skipped from review due to trivial changes (2)
  • cmake/Modules/ValkeySetup.cmake
  • deps/lz4/LICENSE
🚧 Files skipped from review as they are similar to previous changes (33)
  • src/CMakeLists.txt
  • deps/CMakeLists.txt
  • src/unit/CMakeLists.txt
  • tests/integration/valkey-check-rdb.tcl
  • valkey.conf
  • cmake/Modules/SourceFiles.cmake
  • src/config.c
  • src/compression_rio.h
  • src/rio.h
  • tests/integration/replication-aof-sync.tcl
  • deps/lz4/CMakeLists.txt
  • src/aof.c
  • src/server.h
  • src/rdb.h
  • deps/Makefile
  • src/compression_lz4.c
  • src/Makefile
  • src/compression_lz4.h
  • src/compression.h
  • src/unit/Makefile
  • src/compression_rio.c
  • src/compression_stream.h
  • deps/lz4/xxhash.c
  • deps/lz4/xxhash.h
  • tests/integration/rdb-compression.tcl
  • src/rdb.c
  • src/valkey-check-rdb.c
  • deps/lz4/lz4frame.h
  • src/compression.c
  • src/compression_stream.c
  • deps/lz4/lz4hc.c
  • deps/lz4/lz4.h
  • deps/lz4/lz4hc.h

Comment thread deps/lz4/Makefile Resolved

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ðŸ§đ Nitpick comments (2)
src/compression.h (1)

47-58: ⚡ Quick win

Document public function contracts consistently.

The public declarations here are missing per-function API docs (ownership, nullability, error behavior). Please add short contract comments for each declaration to keep this interface self-describing and safe to use.

Proposed doc-style pattern
+/* Returns non-zero if the algorithm has streaming codec support. */
 bool compressionAlgoSupportsStreaming(compressionAlgo algo);
+
+/* Returns a stable, human-readable algorithm name for logs/config output. */
 const char *compressionAlgoName(compressionAlgo algo);

+/* Initializes compressor state for the selected algorithm and level.
+ * Returns 0 on success, -1 on failure. */
 int streamCompressorInit(streamCompressor *sc, compressionAlgo algo, int level);
+/* Releases compressor resources. Safe to call after failed init. */
 void streamCompressorDestroy(streamCompressor *sc);

+/* Initializes decompressor state for the selected algorithm.
+ * Returns 0 on success, -1 on failure. */
 int streamDecompressorInit(streamDecompressor *sd, compressionAlgo algo);
+/* Releases decompressor resources. */
 void streamDecompressorDestroy(streamDecompressor *sd);

As per coding guidelines, "Document why code exists, not just what it does; document all functions in C code."

ðŸĪ– Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/compression.h` around lines 47 - 58, Add short per-function API contract
comments above each public declaration (compressionAlgoSupportsStreaming,
compressionAlgoName, streamCompressorInit, streamCompressorDestroy,
streamDecompressorInit, streamDecompressorDestroy, streamDecompressorFrameDone,
streamDecompressorInputHint) describing purpose, ownership/ownership transfer
(who allocates/frees streamCompressor/streamDecompressor), nullability of
pointer parameters and return values, error semantics and return codes (e.g. 0
on success, negative on error), thread-safety expectations, and any lifetime
guarantees (when the returned const char * from compressionAlgoName is valid).
Use the existing project doc-style pattern for C comments so each function is
self-describing and follows the codebase guideline of “why” and “contract”
information.
src/compression_lz4.h (1)

12-30: ⚡ Quick win

Add function-level docs for the LZ4 public API surface.

This header exposes public entry points but none are documented. Add concise contract comments for init/destroy/feed/output-bound so callers know expected invariants and error semantics.

Suggested documentation skeleton
+/* Initializes LZ4 compressor state in `sc`. Returns 0 on success, -1 on error. */
 int compressionLz4CompressorInit(streamCompressor *sc);
+/* Releases LZ4 compressor resources. */
 void compressionLz4CompressorDestroy(streamCompressor *sc);
+/* Initializes LZ4 decompressor state in `sd`. Returns 0 on success, -1 on error. */
 int compressionLz4DecompressorInit(streamDecompressor *sd);
+/* Releases LZ4 decompressor resources. */
 void compressionLz4DecompressorDestroy(streamDecompressor *sd);
+/* Conservative upper bound for compressed output size for `input_len`. */
 size_t compressionLz4OutputBound(size_t input_len);

As per coding guidelines, "Document why code exists, not just what it does; document all functions in C code."

ðŸĪ– Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/compression_lz4.h` around lines 12 - 30, Add concise function-level
comments above each public symbol in src/compression_lz4.h
(compressionLz4CompressorInit, compressionLz4CompressorDestroy,
compressionLz4DecompressorInit, compressionLz4DecompressorDestroy,
compressionLz4OutputBound, compressionLz4CompressFeed,
compressionLz4DecompressFeed) describing the contract: purpose,
ownership/lifetime expectations (who allocates/frees
streamCompressor/streamDecompressor), required preconditions (valid pointers,
output_capacity >= needed, input may be NULL for flush), thread-safety, what
each parameter means (including compressFlushMode and input_consumed), precise
return/error semantics (success values, what negative return codes mean, when 0
is returned), how partial consumption is reported for feed functions and when
callers must call Destroy, and that compressionLz4OutputBound returns an upper
bound for worst-case expansion; keep each comment short and actionable so
callers know invariants and error handling.
ðŸĪ– Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Nitpick comments:
In `@src/compression_lz4.h`:
- Around line 12-30: Add concise function-level comments above each public
symbol in src/compression_lz4.h (compressionLz4CompressorInit,
compressionLz4CompressorDestroy, compressionLz4DecompressorInit,
compressionLz4DecompressorDestroy, compressionLz4OutputBound,
compressionLz4CompressFeed, compressionLz4DecompressFeed) describing the
contract: purpose, ownership/lifetime expectations (who allocates/frees
streamCompressor/streamDecompressor), required preconditions (valid pointers,
output_capacity >= needed, input may be NULL for flush), thread-safety, what
each parameter means (including compressFlushMode and input_consumed), precise
return/error semantics (success values, what negative return codes mean, when 0
is returned), how partial consumption is reported for feed functions and when
callers must call Destroy, and that compressionLz4OutputBound returns an upper
bound for worst-case expansion; keep each comment short and actionable so
callers know invariants and error handling.

In `@src/compression.h`:
- Around line 47-58: Add short per-function API contract comments above each
public declaration (compressionAlgoSupportsStreaming, compressionAlgoName,
streamCompressorInit, streamCompressorDestroy, streamDecompressorInit,
streamDecompressorDestroy, streamDecompressorFrameDone,
streamDecompressorInputHint) describing purpose, ownership/ownership transfer
(who allocates/frees streamCompressor/streamDecompressor), nullability of
pointer parameters and return values, error semantics and return codes (e.g. 0
on success, negative on error), thread-safety expectations, and any lifetime
guarantees (when the returned const char * from compressionAlgoName is valid).
Use the existing project doc-style pattern for C comments so each function is
self-describing and follows the codebase guideline of “why” and “contract”
information.

â„đïļ Review info
⚙ïļ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro Plus

Run ID: f9cc2d76-d6f8-4849-8ca9-1346437aa8c3

ðŸ“Ĩ Commits

Reviewing files that changed from the base of the PR and between 7ceb358 and b7e58c8.

📒 Files selected for processing (9)
  • src/compression.c
  • src/compression.h
  • src/compression_lz4.c
  • src/compression_lz4.h
  • src/compression_rio.c
  • src/compression_rio.h
  • src/compression_stream.c
  • src/compression_stream.h
  • src/rdb.c
🚧 Files skipped from review as they are similar to previous changes (7)
  • src/compression_rio.h
  • src/compression_rio.c
  • src/compression_stream.h
  • src/compression_lz4.c
  • src/compression.c
  • src/compression_stream.c
  • src/rdb.c

@sarthakaggarwal97
sarthakaggarwal97 force-pushed the streaming-compression-rio-pr branch from dbf155f to 21ee8c4 Compare May 14, 2026 21:28

@roshkhatri roshkhatri left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looked a little deeper for optimization. Let me know what you think

Comment thread src/compression.c Resolved
Comment thread src/compression.c Resolved
Comment thread src/compression.c Resolved
Comment thread src/compression.c Resolved
Comment thread src/compression_lz4.c Resolved
Comment thread src/compression.h Resolved
Comment thread src/compression_stream.h Resolved
Comment thread src/rio.c Resolved
Comment thread src/compression_stream.c Resolved
Comment thread src/compression_stream.c Resolved

@nmvk nmvk left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks mostly good to me. I haven’t reviewed the RIO part yet. Two design questions on CRC validation over decoded content and moving VKCS after the RDB magic/version.

Comment thread src/rdb.c Resolved
Comment thread src/compression.h Resolved
Comment thread src/compression_lz4.c Resolved
Comment thread src/compression.c Resolved
Comment thread src/compression.c Resolved
Comment thread src/compression.c Resolved
Comment thread src/compression_lz4.c Resolved
Comment thread src/compression_stream.c Resolved
Comment thread src/compression_stream.c Resolved
Comment thread src/compression_stream.c Resolved
@sarthakaggarwal97

sarthakaggarwal97 commented May 19, 2026 •

Copy link
Copy Markdown
Contributor Author

Thanks for the review folks.

There are mostly two design discussions that we need to have consensus:

  1. Checksum
    We rely on CRC checksum to verify the integrity of RDB in the existing model. Now, we would rely on LZ4's or any other streaming algorithms checksum which provides content and block level checksum guarantees. This checksum gives the same guarantees as the CRC checksum. It will still be governed by the rdbchecksum setting. Adding another layer of CRC over the streaming compression adds about 20-30% overhead.

  2. RDB File Format
    With VKCS streaming compression, we essentially have changed the way RDB file looks when it is stored on the disk, although we are not changing the "logical" representation of the RDB itself. It would have made sense to bump the version of RDB itself if there was a change in logical representation, but in the current implementation, even the RDB headers get compressed. I had some discussions with @nmvk @xdk-amz @JimB123 @roshkhatri offline.
    There seems to be two options for us:
    a. Since this is an opt in feature in a major version release, we still save the file as .rdb, without the change in RDB version number and document the change in file format.
    b. Introduce a new .crdb file format. This would support all the VKCS algorithms in the future. We need to be careful with handling dbfilename setting and maybe provide a utility to "decompress" .crdb into .rdb.

Also note, the current implementation is smart enough to differentiate between VKCS and Existing RDB and it's able to load in both case irrespective of configuration. We could also just provide a utility to decompress VKCS RDB to existing RDB.

@valkey-io/core-team please share if you have any thoughts on this.

@hpatro hpatro added the run-extra-tests Run extra tests on this PR (Runs all tests from daily except valgrind and RESP) label Aug 14, 2026
@hpatro

hpatro commented Aug 14, 2026

Copy link
Copy Markdown
Contributor

Good call Hari, but this config is called rdbcompression so I don't think it should apply to quicklist nodes. We have list-compress-depth for that. (We could add another list-compress-algo or something.)

Yeah, we won't be able to depend on this. Would we be able to just change the algorithm for internal compression of data without users consent? or else to be transparent we have to introduce on the lines you suggested (maybe inmemory-compress-algo). I believe there is a separate effort ongoing for it.

@zuiderkwast

Copy link
Copy Markdown
Contributor

Would we be able to just change the algorithm for internal compression of data without users consent?

The contract we've talked about for downgrade is to allow it as long as no new features of the new version have been actively used. Even if there's an RDB bump, the old version should be able to read it with the relaxed RDB version check enabled. Opting it by changing a config is an active choice, but a changed default is not.

I think we could soften this contract if we have some overlap of e.g. two major versions (so let's say 10.0 can read this format but doesn't produce it) and/or if there's a way to downgrade by changing the config before saving. Another possibility is to introduce a way to save RDB files in old versions (#3032) – that would need to include decoding lz4 values to either uncompressed or re-compress as lzf.

Either way, it would be good to be able to change the defaults without being limited by downgrades forever.

@hpatro

hpatro commented Aug 14, 2026

Copy link
Copy Markdown
Contributor

Would we be able to just change the algorithm for internal compression of data without users consent?

The contract we've talked about for downgrade is to allow it as long as no new features of the new version have been actively used. Even if there's an RDB bump, the old version should be able to read it with the relaxed RDB version check enabled. Opting it by changing a config is an active choice, but a changed default is not.

in-memory storage (compressed / not) could be decoupled from disk storage. The user would need to pay the cost of decompress and serialise to disk if the algo for list compression / rdb compression. So, I feel we could change the in-memory compression algorithm without user consent.

I think we could soften this contract if we have some overlap of e.g. two major versions (so let's say 10.0 can read this format but doesn't produce it) and/or if there's a way to downgrade by changing the config before saving. Another possibility is to introduce a way to save RDB files in old versions (#3032) – that would need to include decoding lz4 values to either uncompressed or re-compress as lzf.

Either way, it would be good to be able to change the defaults without being limited by downgrades forever.

Yeah, the tradeoff is between maintaining lot of these config forever vs user choice. btw, thanks for filing #3032, I've some thoughts about it. will share over there.

@zuiderkwast zuiderkwast mentioned this pull request Aug 14, 2026
5 of 9 tasks
@zuiderkwast

Copy link
Copy Markdown
Contributor

in-memory storage (compressed / not) could be decoupled from disk storage

You mean we should decompress in-memory quicklist nodes when we write them to RDB, and they get re-compressed at the RDB stream level instead? Makes sense to me.

How is that working in legacy with lzf-compressed quicklist nodes?

@sarthakaggarwal97
sarthakaggarwal97 force-pushed the streaming-compression-rio-pr branch 2 times, most recently from ab5a94a to e45f2d6 Compare August 14, 2026 13:23
@sarthakaggarwal97

Copy link
Copy Markdown
Contributor Author

The failing tests are not due to this PR.

@sarthakaggarwal97

Copy link
Copy Markdown
Contributor Author

How is that working in legacy with lzf-compressed quicklist nodes?

Currently the nodes are stored as is, there is no explicit logic to decompress individual nodes during RDB serialisation

@hpatro

hpatro commented Aug 15, 2026 •

Copy link
Copy Markdown
Contributor

How is that working in legacy with lzf-compressed quicklist nodes?

Currently the nodes are stored as is, there is no explicit logic to decompress individual nodes during RDB serialisation

Does that mean even with rdbcompression set to no, the nodes are stored as compressed?

@sarthakaggarwal97

Copy link
Copy Markdown
Contributor Author

Does that mean even with rdbcompression set to no, the nodes are stored as compressed?

Yep. rdbcompression only dictates per string compression today.

@hpatro

hpatro commented Aug 15, 2026

Copy link
Copy Markdown
Contributor

Does that mean even with rdbcompression set to no, the nodes are stored as compressed?

Yep. rdbcompression only dictates per string compression today.

We can look into this independently what happens with recompression of data with lz4 stream approach over list nodes compressed with lzf.

@sarthakaggarwal97
sarthakaggarwal97 force-pushed the streaming-compression-rio-pr branch from 226a2d1 to 24e4244 Compare August 15, 2026 20:28
@zuiderkwast

Copy link
Copy Markdown
Contributor

The separation in two commits is clean. We should not squash these commits, right? Let's include the PR number in parentheses in each commit message title. (We don't get a chance to edit the commit messages when we click Rebase-merge.)

Vendor lz4, lz4hc, lz4frame and xxhash from https://github.com/lz4/lz4
(v1.10.0) under deps/lz4 with build wiring for make and cmake.

Signed-off-by: Sarthak Aggarwal <sarthagg@amazon.com>
Add Valkey Compressed Stream (VCS) support for RDB persistence with LZ4
as the first whole-stream codec. The RDB is wrapped in a VCS envelope
and compressed as a single stream at the rio layer. On load, the RDB
path probes for the envelope and transparently decompresses when
present, falling back to the plain RDB path otherwise.

Signed-off-by: Sarthak Aggarwal <sarthagg@amazon.com>
@sarthakaggarwal97
sarthakaggarwal97 force-pushed the streaming-compression-rio-pr branch from 24e4244 to 9a54fba Compare August 16, 2026 20:47
@sarthakaggarwal97

sarthakaggarwal97 commented Aug 16, 2026 •

Copy link
Copy Markdown
Contributor Author

Yes, the plan is to merge two commits as is. I added the PR number in parentheses.

@madolson madolson left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Since I did review it, just putting my approval on it. I never ended up reviewing the final details all that closely, but all the high level decisions I'm aligned with.

@roshkhatri roshkhatri left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM, for multiple algorithms we will need changes when we add ZSTD. Good to go

@hpatro
hpatro merged commit 5d3fd68 into valkey-io:unstable Aug 17, 2026
123 of 124 checks passed
hpatro pushed a commit that referenced this pull request Aug 17, 2026
Vendor lz4, lz4hc, lz4frame and xxhash from https://github.com/lz4/lz4
(v1.10.0) under deps/lz4 with build wiring for make and cmake.

Signed-off-by: Sarthak Aggarwal <sarthagg@amazon.com>
@hpatro

hpatro commented Aug 17, 2026

Copy link
Copy Markdown
Contributor

Thanks for your hard work @sarthakaggarwal97!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

run-extra-tests Run extra tests on this PR (Runs all tests from daily except valgrind and RESP)

Projects

Status: Merged

Development

Successfully merging this pull request may close these issues.

7 participants