Add Zstd support for EVCache#197
Open
janewang1680 wants to merge 15 commits into
Open
Conversation
Contributor
|
@shy-1234 can you also review the PR please |
shy-1234
reviewed
Jun 27, 2026
shy-1234
reviewed
Jun 27, 2026
shy-1234
reviewed
Jun 27, 2026
shy-1234
reviewed
Jun 27, 2026
2 tasks
joegoogle123
pushed a commit
that referenced
this pull request
Jun 30, 2026
…nscoderProperties
Today EVCacheImpl reads the binary-serialization FastProperty inline:
```java
final boolean useBinarySerialization = propertyRepository.get(_appName + ".envelope.binary.serialization.enabled", Boolean.class)
.orElseGet("evcache.envelope.binary.serialization.enabled").orElse(false).get();
this.evcacheValueTranscoder = new EVCacheTranscoder(maxValueSize, ENVELOPE_COMPRESSION_DISABLED, useBinarySerialization);
```
This change introduces an EVCacheTranscoderProperties bundle that owns the
read and exposes the result behind a typed accessor. Each property follows a
uniform three-level resolution chain:
1. <appName>.<appSuffix> (per-app override)
2. <globalKey> (fleet-wide global)
3. compiled-in static default
Today the bundle holds exactly one property — USE_BINARY_SERIALIZATION,
appSuffix `binary.serialization.enabled`, globalKey
`default.evcache.binary.serialization.enabled`. The Key enum is the
extension point: new transcoder properties land here and inherit the same
chain without touching the call sites.
EVCacheTranscoder gains a (int, int, EVCacheTranscoderProperties) ctor that
stores the bundle and consults `properties.isBinarySerializationEnabled()`
inside `serialize()`. The old (int, int, boolean) ctor is gone; the 2-arg
(int, int) ctor constructs a properties object with appName=null so the
no-app callers naturally fall through to the global key.
EVCacheImpl drops the inline read and the ENVELOPE_COMPRESSION_DISABLED
constant, building the bundle once per app.
NOTE on property key naming: the global key changed from
`evcache.envelope.binary.serialization.enabled` to
`default.evcache.binary.serialization.enabled`, matching the
`default.evcache.…` convention used by the other transcoder properties.
The per-app suffix is `binary.serialization.enabled` (no `envelope.`
prefix). Any caller who set the old global key will need to migrate.
Future fields that need runtime-dynamic reads can call the bundle's
`getProperty(Key, Class, default)` method instead of caching at
construction. PR #197's setCompressionAlgorithmProperty /
setCompressionLevelProperty setters on EVCacheSerializingTranscoder are
orthogonal and untouched here.
Tests: 5 new tests in EVCacheTranscoderPropertiesTest cover per-app
override, global fallback, static default, per-app-beats-global precedence,
and null-appName routing to the global key.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
joegoogle123
pushed a commit
that referenced
this pull request
Jun 30, 2026
…nscoderProperties
Today EVCacheImpl reads the binary-serialization FastProperty inline:
```java
final boolean useBinarySerialization = propertyRepository.get(_appName + ".envelope.binary.serialization.enabled", Boolean.class)
.orElseGet("evcache.envelope.binary.serialization.enabled").orElse(false).get();
this.evcacheValueTranscoder = new EVCacheTranscoder(maxValueSize, ENVELOPE_COMPRESSION_DISABLED, useBinarySerialization);
```
This change introduces an EVCacheTranscoderProperties bundle that owns the
read and exposes the result behind a typed accessor. Each property follows a
uniform three-level resolution chain:
1. <appName>.<appSuffix> (per-app override)
2. <globalKey> (fleet-wide global)
3. compiled-in static default
Today the bundle holds exactly one property — USE_BINARY_SERIALIZATION,
appSuffix `binary.serialization.enabled`, globalKey
`default.evcache.binary.serialization.enabled`. The Key enum is the
extension point: new transcoder properties land here and inherit the same
chain without touching the call sites.
EVCacheTranscoder gains a (int, int, EVCacheTranscoderProperties) ctor that
stores the bundle and consults `properties.isBinarySerializationEnabled()`
inside `serialize()`. The old (int, int, boolean) ctor is gone; the 2-arg
(int, int) ctor constructs a properties object with appName=null so the
no-app callers naturally fall through to the global key.
EVCacheImpl drops the inline read and the ENVELOPE_COMPRESSION_DISABLED
constant, building the bundle once per app.
NOTE on property key naming: the global key changed from
`evcache.envelope.binary.serialization.enabled` to
`default.evcache.binary.serialization.enabled`, matching the
`default.evcache.…` convention used by the other transcoder properties.
The per-app suffix is `binary.serialization.enabled` (no `envelope.`
prefix). Any caller who set the old global key will need to migrate.
Future fields that need runtime-dynamic reads can call the bundle's
`getProperty(Key, Class, default)` method instead of caching at
construction. PR #197's setCompressionAlgorithmProperty /
setCompressionLevelProperty setters on EVCacheSerializingTranscoder are
orthogonal and untouched here.
Tests: 5 new tests in EVCacheTranscoderPropertiesTest cover per-app
override, global fallback, static default, per-app-beats-global precedence,
and null-appName routing to the global key.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
joegoogle123
pushed a commit
that referenced
this pull request
Jun 30, 2026
…nscoderProperties
Today EVCacheImpl reads the binary-serialization FastProperty inline:
```java
final boolean useBinarySerialization = propertyRepository.get(_appName + ".envelope.binary.serialization.enabled", Boolean.class)
.orElseGet("evcache.envelope.binary.serialization.enabled").orElse(false).get();
this.evcacheValueTranscoder = new EVCacheTranscoder(maxValueSize, ENVELOPE_COMPRESSION_DISABLED, useBinarySerialization);
```
This change introduces an EVCacheTranscoderProperties bundle that owns the
read and exposes the result behind a typed accessor. Each property follows a
uniform three-level resolution chain:
1. <appName>.<appSuffix> (per-app override)
2. <globalKey> (fleet-wide global)
3. compiled-in static default
Today the bundle holds exactly one property — USE_BINARY_SERIALIZATION,
appSuffix `binary.serialization.enabled`, globalKey
`default.evcache.binary.serialization.enabled`. The Key enum is the
extension point: new transcoder properties land here and inherit the same
chain without touching the call sites.
EVCacheTranscoder gains a (int, int, EVCacheTranscoderProperties) ctor that
stores the bundle and consults `properties.isBinarySerializationEnabled()`
inside `serialize()`. The old (int, int, boolean) ctor is gone; the 2-arg
(int, int) ctor constructs a properties object with appName=null so the
no-app callers naturally fall through to the global key.
EVCacheImpl drops the inline read and the ENVELOPE_COMPRESSION_DISABLED
constant, building the bundle once per app.
NOTE on property key naming: the global key changed from
`evcache.envelope.binary.serialization.enabled` to
`default.evcache.binary.serialization.enabled`, matching the
`default.evcache.…` convention used by the other transcoder properties.
The per-app suffix is `binary.serialization.enabled` (no `envelope.`
prefix). Any caller who set the old global key will need to migrate.
Future fields that need runtime-dynamic reads can call the bundle's
`getProperty(Key, Class, default)` method instead of caching at
construction. PR #197's setCompressionAlgorithmProperty /
setCompressionLevelProperty setters on EVCacheSerializingTranscoder are
orthogonal and untouched here.
Tests: 5 new tests in EVCacheTranscoderPropertiesTest cover per-app
override, global fallback, static default, per-app-beats-global precedence,
and null-appName routing to the global key.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
joegoogle123
pushed a commit
that referenced
this pull request
Jul 1, 2026
…nscoderProperties
Today EVCacheImpl reads the binary-serialization FastProperty inline:
```java
final boolean useBinarySerialization = propertyRepository.get(_appName + ".envelope.binary.serialization.enabled", Boolean.class)
.orElseGet("evcache.envelope.binary.serialization.enabled").orElse(false).get();
this.evcacheValueTranscoder = new EVCacheTranscoder(maxValueSize, ENVELOPE_COMPRESSION_DISABLED, useBinarySerialization);
```
This change introduces an EVCacheTranscoderProperties bundle that owns the
read and exposes the result behind a typed accessor. Each property follows a
uniform three-level resolution chain:
1. <appName>.<appSuffix> (per-app override)
2. <globalKey> (fleet-wide global)
3. compiled-in static default
Today the bundle holds exactly one property — USE_BINARY_SERIALIZATION,
appSuffix `binary.serialization.enabled`, globalKey
`default.evcache.binary.serialization.enabled`. The Key enum is the
extension point: new transcoder properties land here and inherit the same
chain without touching the call sites.
EVCacheTranscoder gains a (int, int, EVCacheTranscoderProperties) ctor that
stores the bundle and consults `properties.isBinarySerializationEnabled()`
inside `serialize()`. The old (int, int, boolean) ctor is gone; the 2-arg
(int, int) ctor constructs a properties object with appName=null so the
no-app callers naturally fall through to the global key.
EVCacheImpl drops the inline read and the ENVELOPE_COMPRESSION_DISABLED
constant, building the bundle once per app.
NOTE on property key naming: the global key changed from
`evcache.envelope.binary.serialization.enabled` to
`default.evcache.binary.serialization.enabled`, matching the
`default.evcache.…` convention used by the other transcoder properties.
The per-app suffix is `binary.serialization.enabled` (no `envelope.`
prefix). Any caller who set the old global key will need to migrate.
Future fields that need runtime-dynamic reads can call the bundle's
`getProperty(Key, Class, default)` method instead of caching at
construction. PR #197's setCompressionAlgorithmProperty /
setCompressionLevelProperty setters on EVCacheSerializingTranscoder are
orthogonal and untouched here.
Tests: 5 new tests in EVCacheTranscoderPropertiesTest cover per-app
override, global fallback, static default, per-app-beats-global precedence,
and null-appName routing to the global key.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Move compression algorithm/level resolution into EVCacheTranscoderProperties so the transcoder holds live Property handles resolved through the standard per-app -> global -> static-default chain (keys: compression.algorithm, compression.zstd.level). Simplifies EVCacheSerializingTranscoder/EVCacheTranscoder plumbing and removes the ad-hoc getProperty overloads and setters. Harden algorithm parsing: an unrecognized FP value (e.g. a typo) previously resolved to null and NPE'd the compression switch at encode time. It now warn-logs and falls back to DEFAULT_COMPRESSION_ALGORITHM (GZIP), so a bad fast-property degrades instead of taking down writes. Tests: rewrite EVCacheSerializingTranscoderTest and EVCacheTranscoderPropertiesTest against the new property-bundle API; add coverage for three-level resolution of the two new keys, case-insensitivity, live FP updates, the compression-grew-data branch, and the unrecognized-algorithm fallback. Remove redundant duplicate tests. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
joegoogle123
approved these changes
Jul 3, 2026
Contributor
|
LGTM |
srrangarajan
approved these changes
Jul 6, 2026
shy-1234
approved these changes
Jul 6, 2026
shy-1234
left a comment
Contributor
There was a problem hiding this comment.
LGTM. Please also get a +1 from @joegoogle123 and I think we are good to go.
3 tasks
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
Add pluggable compression algorithm support (gzip, zstd) via a new CompressionAlgorithm enum on EVCacheSerializingTranscoder, with magic-byte auto-detection on decode so existing gzip-compressed cache entries
continue to decode correctly. Algorithm and zstd level are configurable via two new fast properties:
default.evcache.compression.algorithm (default GZIP)
default.evcache.compression.zstd.level (default 3)
Fix a pre-existing bug in the compression ratio metric where compressed.length / b.length always evaluated to 1.0 because b was reassigned to compressed before the ratio calculation. The metric now uses the
captured originalLength, producing accurate ratios.
Test plan
./gradlew :evcache-core:test --tests "com.netflix.evcache.EVCacheSerializingTranscoderTest" — 17 tests covering enum values, default constructor, gzip/zstd round-trip, cross-decode (gzip-written read by zstd
transcoder and vice versa), and FP wiring.
Verify backward compatibility: data written with gzip in production decodes correctly after deploy.
Verify compression ratio metric (COMPRESSION_RATIO timer) reports realistic ratios (not always ~100%) in a canary.
Verify it works in our internal services