Skip to content

feat: add diagnostic Redis TTL bypass - #546

Open
thweetkomputer wants to merge 1 commit into
mainfrom
feat/ignore-redis-ttl
Open

feat: add diagnostic Redis TTL bypass#546
thweetkomputer wants to merge 1 commit into
mainfrom
feat/ignore-redis-ttl

Conversation

@thweetkomputer

@thweetkomputer thweetkomputer commented Aug 7, 2026

Copy link
Copy Markdown
Collaborator

Context

Customers diagnosing large Redis keys need to inspect records that are still present in RocksDB even after their Redis TTL has expired. The normal point-read, scan, and compaction paths hide or physically reclaim those records.

Behavior before and after

Before this change, EloqDSS treats expired EloqKV records as deleted during reads and scans, and the RocksDB TTL compaction filter eventually removes them.

With --ignore_redis_ttl=true or [store] ignore_redis_ttl=true, RocksDB-backed EloqDSS variants expose persisted expired records and retain them during compaction. The default remains false. Stored TTL metadata and value bytes are unchanged, so disabling the option and restarting restores normal expiration from the original absolute timestamp.

Implementation

  • Define and load the ignore_redis_ttl flag for EloqDSS RocksDB configurations.
  • Centralize build-specific access through IgnoreRedisTTL(); non-RocksDB builds always return false.
  • Gate point-read, bucket-fetch, and scanner expiration checks on the flag.
  • Make TTLCompactionFilter retain records while diagnostic mode is enabled.
  • Add compaction-filter coverage and document the operational contract.

Design decisions and alternatives

The implementation bypasses TTL interpretation instead of clearing the version-ts MSB or rewriting serialized values. This preserves the original expiration timestamp and makes the mode reversible without a data migration. Every EloqKV and DSS process accessing the diagnostic store must use the same setting.

Test plan

  • Unit/CTest coverage
  • Parent-project integration or manual validation
  • Formatting/build checks
  • Recovery, compatibility, or performance validation, when relevant
  • Documentation updated, when behavior changed

Commands and results:

# Before rebase; passed in the current workspace
make data_substrate/fast -j16            # bld-rocksdb-cloud: PASS
make eloqkv/fast -j16                    # bld-rocksdb-cloud: PASS
make eloqkv/fast -j16                    # bld-eloqstore: PASS

# After rebase onto origin/main
c++ ... -fsyntax-only data_store_service_client_closure.cpp  # PASS
clang-format --dry-run --Werror <changed C/C++ files>         # PASS
git diff --check origin/main...HEAD                           # PASS

# Not completed
cmake --build bld-s3 --parallel 16       # environment missing /usr/local protobuf headers
TTLCompactionFilter-Test runtime         # not run; test source was syntax-checked before rebase

Risk assessment

This intentionally changes read visibility and compaction behavior only when explicitly enabled. Inconsistent settings across processes can produce inconsistent visibility, and ordinary writes remain persistent while diagnostic mode is active. Once disabled, records whose absolute TTL is already in the past become expired again.

Rollback plan

Set ignore_redis_ttl=false on every EloqKV and DSS process and restart. No stored data conversion is required. The code change can also be reverted independently.

Reviewer guide

Start with ignore_redis_ttl.h and rocksdb_config.cpp, then verify the three read/scan gates and the early return in TTLCompactionFilter::Filter. The key invariant is that diagnostic mode never mutates the stored TTL header, MSB, or value bytes.

Follow-up work

Run the new unit test binary and an end-to-end RocksDB Cloud diagnostic-cluster scenario in CI.

Summary by CodeRabbit

  • New Features

    • Added the ignore_redis_ttl diagnostic option for RocksDB-based configurations.
    • When enabled, expired records remain available during reads, scans, bucket operations, and compaction.
    • The option preserves expiration metadata so standard TTL behavior resumes when disabled.
    • Configuration-file support was added, while explicit command-line settings take precedence.
  • Bug Fixes

    • Preserved normal TTL expiration behavior when the diagnostic option is disabled.
  • Tests

    • Added coverage confirming both standard expiration and TTL-ignoring behavior.

@coderabbitai

coderabbitai Bot commented Aug 7, 2026

Copy link
Copy Markdown

Review Change Stack

Walkthrough

Adds the ignore_redis_ttl option for RocksDB-backed builds. The option controls TTL filtering during reads, scans, and compaction while preserving stored expiration metadata. Configuration loading keeps explicit command-line values unchanged.

Changes

Redis TTL bypass

Layer / File(s) Summary
TTL bypass configuration
store_handler/eloq_data_store_service/ignore_redis_ttl.h, store_handler/eloq_data_store_service/rocksdb_config.cpp, docs/09-store-handler.md
Defines the diagnostic flag, loads it from [store] when appropriate, and documents its behavior.
Read and scan filtering
store_handler/data_store_service_client_closure.cpp, store_handler/data_store_service_scanner.cpp
Read and scan paths apply expiration filtering only when IgnoreRedisTTL() is disabled.
Compaction preservation and validation
store_handler/eloq_data_store_service/rocksdb_data_store_common.cpp, tx_service/tests/TTLCompactionFilter-Test.cpp
Compaction preserves expired records when enabled. Tests cover normal filtering and diagnostic-mode retention.

Estimated code review effort: 3 (Moderate) | ~20 minutes

Sequence Diagram(s)

sequenceDiagram
  participant Client
  participant FetchRecordCallback
  participant DataStoreServiceScanner
  participant TTLCompactionFilter
  participant IgnoreRedisTTL
  Client->>FetchRecordCallback: Fetch record
  FetchRecordCallback->>IgnoreRedisTTL: Check bypass flag
  IgnoreRedisTTL-->>FetchRecordCallback: Return flag state
  FetchRecordCallback-->>Client: Filter or return expired record
  Client->>DataStoreServiceScanner: Scan records
  DataStoreServiceScanner->>IgnoreRedisTTL: Check bypass flag
  IgnoreRedisTTL-->>DataStoreServiceScanner: Return flag state
  DataStoreServiceScanner-->>Client: Filter or return expired records
  TTLCompactionFilter->>IgnoreRedisTTL: Check bypass flag
  IgnoreRedisTTL-->>TTLCompactionFilter: Return flag state
  TTLCompactionFilter-->>TTLCompactionFilter: Delete or preserve expired records
Loading

Possibly related PRs

Suggested reviewers: liunyl, liangjchen, zhangh43

Poem

A rabbit found old keys in the store,
With TTL marks still set as before.
“Ignore,” said the flag,
“Keep each dusty tag.”
Compaction now leaves them at the door.

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly and concisely describes the addition of a diagnostic Redis TTL bypass.
Description check ✅ Passed The description covers context, behavior, implementation, design, testing, risks, rollback, review guidance, and follow-up work.
Docstring Coverage ✅ Passed Docstring coverage is 100.00% which is sufficient. The required threshold is 80.00%.
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.
✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch feat/ignore-redis-ttl

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

Choose a reason for hiding this comment

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

Actionable comments posted: 2

🤖 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 `@docs/09-store-handler.md`:
- Line 127: Update the “Diagnostic TTL bypass (EloqDSS RocksDB variants)”
documentation to state that an explicitly supplied --ignore_redis_ttl
command-line value takes precedence over [store] ignore_redis_ttl, including
that --ignore_redis_ttl=false overrides an INI value of true. Briefly explain
the operational constraint that all participating processes must use the same
effective setting.

In `@tx_service/tests/TTLCompactionFilter-Test.cpp`:
- Around line 59-70: Update both TTL-related sections in the test around
ShouldFilter to restore FLAGS_ignore_redis_ttl via an RAII scoped guard that
captures its prior value and restores it on scope exit, including assertion
failures. Remove the manual reset and preserve each section’s intended flag
setting.
🪄 Autofix

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: Organization UI

Review profile: CHILL

Plan: Pro Plus

Run ID: 3388fd85-906a-4f4c-a5e9-8aa853ad14ff

📥 Commits

Reviewing files that changed from the base of the PR and between 6ccdb32 and 9960410.

📒 Files selected for processing (7)
  • docs/09-store-handler.md
  • store_handler/data_store_service_client_closure.cpp
  • store_handler/data_store_service_scanner.cpp
  • store_handler/eloq_data_store_service/ignore_redis_ttl.h
  • store_handler/eloq_data_store_service/rocksdb_config.cpp
  • store_handler/eloq_data_store_service/rocksdb_data_store_common.cpp
  • tx_service/tests/TTLCompactionFilter-Test.cpp

Comment thread docs/09-store-handler.md
## 6. TTL and Purge Mechanisms

- **Record TTL (data plane).** `BatchWriteRecords` items carry a `ttl` (ms epoch). On read, `FetchRecordCallback` treats an expired EloqKV record as `RecordStatus::Deleted` even if the store still has it. Physical reclamation is compaction-driven: `TTLCompactionFilter` (both `rocksdb_handler.h` and DSS `rocksdb_data_store_common.h`) drops expired entries during RocksDB compaction; the DSS variant flags TTL presence in the version-ts MSB (`MSB`/`MSB_MASK`).
- **Diagnostic TTL bypass (EloqDSS RocksDB variants).** `--ignore_redis_ttl=true` (or `[store] ignore_redis_ttl=true`) bypasses the EloqKV point-read, bucket, and scanner expiry checks and makes `TTLCompactionFilter` retain expired records. EloqKV separately makes its TTL object variants report no TTL while the mode is active. Neither the version-ts MSB, the outer expiration timestamp, nor the Redis object's embedded TTL is rewritten, so restarting every EloqKV and DSS process with the option disabled restores normal expiration from the stored absolute timestamp. All participating processes must use the same setting; the option is intended for isolated diagnostic stores, and it does not make ordinary writes read-only.

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

📐 Maintainability & Code Quality | 🟡 Minor | ⚡ Quick win

Document command-line precedence.

An explicit --ignore_redis_ttl value overrides [store] ignore_redis_ttl. State this rule, including that --ignore_redis_ttl=false overrides an INI value of true.

As per coding guidelines, document non-obvious operational constraints and explain why.

🤖 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 `@docs/09-store-handler.md` at line 127, Update the “Diagnostic TTL bypass
(EloqDSS RocksDB variants)” documentation to state that an explicitly supplied
--ignore_redis_ttl command-line value takes precedence over [store]
ignore_redis_ttl, including that --ignore_redis_ttl=false overrides an INI value
of true. Briefly explain the operational constraint that all participating
processes must use the same effective setting.

Source: Coding guidelines

Comment on lines +59 to +70
FLAGS_ignore_redis_ttl = false;
const std::string value = MakeValue(EloqDS::MSB | 42, 1);
REQUIRE(ShouldFilter(value, kCompactionTimestamp));
}

SECTION("expired TTL value is retained in diagnostic mode")
{
FLAGS_ignore_redis_ttl = true;
const std::string value = MakeValue(EloqDS::MSB | 42, 1);
REQUIRE_FALSE(ShouldFilter(value, kCompactionTimestamp));
FLAGS_ignore_redis_ttl = false;
}

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win

Restore FLAGS_ignore_redis_ttl with RAII.

If REQUIRE_FALSE fails on Line 68, Catch2 exits the section before Line 69. Later tests then run with TTL bypass enabled. Preserve and restore the prior flag value with a scoped guard in each section.

Proposed test isolation fix
+class ScopedIgnoreRedisTTLFlag
+{
+ public:
+    explicit ScopedIgnoreRedisTTLFlag(bool value)
+        : previous_value_(FLAGS_ignore_redis_ttl)
+    {
+        FLAGS_ignore_redis_ttl = value;
+    }
+
+    ~ScopedIgnoreRedisTTLFlag()
+    {
+        FLAGS_ignore_redis_ttl = previous_value_;
+    }
+
+ private:
+    bool previous_value_;
+};
+
-        FLAGS_ignore_redis_ttl = false;
+        ScopedIgnoreRedisTTLFlag ttl_flag(false);
         const std::string value = MakeValue(EloqDS::MSB | 42, 1);
         REQUIRE(ShouldFilter(value, kCompactionTimestamp));
 
-        FLAGS_ignore_redis_ttl = true;
+        ScopedIgnoreRedisTTLFlag ttl_flag(true);
         const std::string value = MakeValue(EloqDS::MSB | 42, 1);
         REQUIRE_FALSE(ShouldFilter(value, kCompactionTimestamp));
-        FLAGS_ignore_redis_ttl = false;
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
FLAGS_ignore_redis_ttl = false;
const std::string value = MakeValue(EloqDS::MSB | 42, 1);
REQUIRE(ShouldFilter(value, kCompactionTimestamp));
}
SECTION("expired TTL value is retained in diagnostic mode")
{
FLAGS_ignore_redis_ttl = true;
const std::string value = MakeValue(EloqDS::MSB | 42, 1);
REQUIRE_FALSE(ShouldFilter(value, kCompactionTimestamp));
FLAGS_ignore_redis_ttl = false;
}
class ScopedIgnoreRedisTTLFlag
{
public:
explicit ScopedIgnoreRedisTTLFlag(bool value)
: previous_value_(FLAGS_ignore_redis_ttl)
{
FLAGS_ignore_redis_ttl = value;
}
~ScopedIgnoreRedisTTLFlag()
{
FLAGS_ignore_redis_ttl = previous_value_;
}
private:
bool previous_value_;
};
ScopedIgnoreRedisTTLFlag ttl_flag(false);
const std::string value = MakeValue(EloqDS::MSB | 42, 1);
REQUIRE(ShouldFilter(value, kCompactionTimestamp));
}
SECTION("expired TTL value is retained in diagnostic mode")
{
ScopedIgnoreRedisTTLFlag ttl_flag(true);
const std::string value = MakeValue(EloqDS::MSB | 42, 1);
REQUIRE_FALSE(ShouldFilter(value, kCompactionTimestamp));
}
🤖 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 `@tx_service/tests/TTLCompactionFilter-Test.cpp` around lines 59 - 70, Update
both TTL-related sections in the test around ShouldFilter to restore
FLAGS_ignore_redis_ttl via an RAII scoped guard that captures its prior value
and restores it on scope exit, including assertion failures. Remove the manual
reset and preserve each section’s intended flag setting.

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