Skip to content

fix(cache): preserve empty nested JSON objects (DAT-2310) - #125

Merged
abnegate merged 1 commit into
mainfrom
fix/cache-empty-object-fidelity
Aug 12, 2026
Merged

fix(cache): preserve empty nested JSON objects (DAT-2310)#125
abnegate merged 1 commit into
mainfrom
fix/cache-empty-object-fidelity

Conversation

@abnegate

Copy link
Copy Markdown
Member

What changed

  • preserve empty JSON objects as stdClass while retaining associative arrays for non-empty objects
  • use the fidelity-preserving decoder in Redis, Redis Cluster, Hazelcast, and Redis multiplexing envelope reads and touches
  • cover root, nested, and list empty objects separately from empty arrays

Seen red

On current main, the new Redis envelope regression returned empty arrays in place of every empty object:

  • expected: {"empty":{},"nested":{"empty":{}},"list":[{},...],"emptyArray":[]}
  • actual: {"empty":[],"nested":{"empty":[]},"list":[[],...],"emptyArray":[]}

Verification

  • cache unit suite: 102 tests, 217 assertions, 4 existing capability skips
  • JSON fidelity E2E: Redis, Sharding, Hazelcast: 3 tests, 12 assertions
  • Redis Cluster fidelity E2E on a native arm64 six-node Redis 7 cluster: 1 test, 4 assertions
  • Redis multiplexing fidelity E2E: 1 test, 4 assertions
  • non-cluster, non-multiplexing E2E: 61 tests, 181 assertions
  • bin/monorepo check cache
  • bin/monorepo validate

The repository Redis Cluster image is amd64-only and its healthcheck segfaults under local arm64 emulation, so the exact fidelity case was also run against a native six-node Redis 7 cluster. The complete local multiplexing E2E process still hits an unrelated existing Swoole segmentation fault; the new multiplexing regression itself passes independently.

Release chain

This is the cache layer of DAT-2310. A stable cache 4.0.x release is required before database, server-ce, and Cloud lock updates; no temporary VCS pin is introduced.

Related: utopia-php/mongo#48, #123.

@greptile-apps

greptile-apps Bot commented Aug 12, 2026

Copy link
Copy Markdown
Contributor

Greptile Summary

The PR preserves empty JSON objects as stdClass while continuing to decode non-empty objects as associative arrays.

  • Adds a shared fidelity-preserving JSON decoder.
  • Integrates it into Redis envelopes, Redis Cluster, and Hazelcast load/touch paths.
  • Adds unit and E2E coverage for root, nested, and list-contained empty objects while distinguishing empty arrays.

Confidence Score: 5/5

The PR appears safe to merge, with no actionable correctness or security failures identified.

The new decoder preserves only the intended empty-object distinction, continues converting valid envelopes and non-empty JSON objects to associative arrays, forwards decoding flags, and retains existing malformed-envelope behavior across each integrated adapter.

Important Files Changed

Filename Overview
packages/cache/src/Cache/Adapter/Json.php Adds recursive JSON conversion that retains empty objects while preserving the adapters’ existing associative-array representation for non-empty objects.
packages/cache/src/Cache/Adapter/Redis/Envelope.php Routes Redis envelope reads and touches through the fidelity-preserving decoder without changing validation, expiration, or malformed-input behavior.
packages/cache/src/Cache/Adapter/RedisCluster.php Applies fidelity-preserving decoding to Redis Cluster load and touch operations while retaining existing envelope checks.
packages/cache/src/Cache/Adapter/Hazelcast.php Applies the shared decoder to Hazelcast load and touch paths so nested empty objects survive round trips.
packages/cache/tests/Cache/Scope/EmptyObjectFidelity.php Provides reusable E2E coverage for empty objects at multiple nesting positions, empty arrays, and touch behavior.
packages/cache/tests/Cache/Unit/RedisEnvelopeTest.php Adds focused regression coverage confirming empty-object fidelity across Redis envelope decode and touch operations.

Reviews (1): Last reviewed commit: "(fix): preserve empty objects in JSON-ba..." | Re-trigger Greptile

@abnegate
abnegate merged commit 1e4d496 into main Aug 12, 2026
6 checks passed
@abnegate
abnegate deleted the fix/cache-empty-object-fidelity branch August 12, 2026 07:49
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