Skip to content

feat: support ignoring Redis TTL for diagnostics - #555

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

feat: support ignoring Redis TTL for diagnostics#555
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

Depends on eloqdata/tx_service#546.

Customers diagnosing large Redis keys need to inspect records that remain in RocksDB after their TTL has expired. The diagnostic cluster must expose those records without destroying the stored TTL, so normal expiration can be restored afterward.

Behavior before and after

By default, behavior is unchanged. With --ignore_redis_ttl=true or [store] ignore_redis_ttl=true in a RocksDB-backed deployment, persisted TTL objects remain visible and report no active TTL while the mode is enabled. Disabling the option and restarting restores expiration from the original stored absolute timestamp.

Implementation

  • Initialize a process-wide Redis object TTL interpretation flag from the EloqDSS RocksDB setting.
  • Make all Redis TTL object variants return HasTTL() == false only in diagnostic mode while preserving their embedded TTL and serialized bytes.
  • Add serialization coverage proving the mode does not rewrite TTL metadata.
  • Document the option in eloqkv.ini and the data-model guide.
  • Update data_substrate to the implementation in feat: add diagnostic Redis TTL bypass tx_service#546.

Design decisions and alternatives

The mode changes runtime interpretation instead of clearing the DSS version-ts MSB or editing Redis object blobs. That makes it reversible and avoids an export/import rewrite. The setting is intentionally static after service initialization; changing it requires a restart so readers, checkpoints, scans, and compaction use one consistent policy.

Test plan

  • Unit/TCL tests
  • Integration or manual validation
  • Formatting/build checks
  • Compatibility or performance validation, when relevant

Commands and results:

# Before the submodule 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
syntax-only compile of both changed test files                    # PASS
./eloqkv --helpfull | search ignore_redis_ttl                     # default false confirmed

# After rebase/final diff
syntax-only compile of the resolved data-store callback           # PASS
clang-format --dry-run --Werror <all changed C/C++ files>         # PASS
git diff --check origin/main...HEAD                               # PASS
git merge-base --is-ancestor origin/main HEAD                     # PASS

# Not completed
cmake --build bld-s3 --parallel 16       # environment missing /usr/local protobuf headers
runtime TTL/TCL scenario                 # not run

Risk assessment

The default is false, so existing deployments are unaffected. When enabled, expired records become visible and ordinary writes still persist; this mode must therefore be used only on an isolated diagnostic store. Every EloqKV and DSS process accessing that store must use the same setting. Once disabled, already-expired records disappear again and become eligible for compaction.

The current submodule pointer targets the review commit from eloqdata/tx_service#546 and must be updated to that PR's merged commit before this PR is merged.

Rollback plan

Set ignore_redis_ttl=false everywhere and restart; no data migration is required because serialized TTL metadata is unchanged. The commits can also be reverted.

Reviewer guide

Review RedisEloqObject::SetIgnoreTTL/IgnoreTTL and the TTL subclasses' HasTTL() overrides first, then RedisServiceImpl::Init. The main invariant is that ignoring TTL affects runtime checks only and never changes serialization.

Follow-up work

After eloqdata/tx_service#546 is squash-merged, update this PR's submodule pointer to the merged main commit and rerun the RocksDB Cloud build and runtime diagnostic scenario.

Summary by CodeRabbit

  • New Features

    • Added an optional diagnostic mode to bypass Redis TTL enforcement.
    • Configure it with --ignore_redis_ttl=true or [store] ignore_redis_ttl=true.
    • Expired keys remain accessible, and TTL/PTTL report no active expiry while enabled.
    • Original TTL metadata remains preserved, allowing normal expiration to resume after disabling the option and restarting.
  • Tests

    • Added coverage confirming TTL metadata is preserved when expiration is bypassed.

@coderabbitai

coderabbitai Bot commented Aug 7, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

Walkthrough

The PR adds a diagnostic mode that ignores Redis TTL enforcement at runtime while preserving stored TTL metadata. It updates object behavior, service initialization, configuration documentation, and serialization tests. It also updates the data_substrate submodule reference.

Changes

Redis TTL Ignore Mode

Layer / File(s) Summary
TTL state and object behavior
include/redis_object.h, include/redis_*_object.h
Adds thread-safe runtime TTL controls. Redis object HasTTL() methods now reflect the ignore-TTL state.
TTL configuration and initialization
src/redis_service.cpp, eloqkv.ini, docs/03-data-model.md
Reads ignore_redis_ttl during initialization, applies the setting, logs a warning when enabled, and documents its behavior.
TTL serialization validation
tests/unit/eloq/object_serialize_deserialize_test.cpp
Verifies that ignored TTL state preserves the stored TTL and serialized metadata.

Data Substrate Update

Layer / File(s) Summary
Submodule reference update
data_substrate
Updates the submodule pointer to commit 99604109c00967d33c07cc6adf167df51bd33331.

Estimated code review effort: 2 (Simple) | ~10 minutes

Possibly related PRs

Suggested reviewers: liunyl

Poem

I hop through TTL fields in a row,
Keeping stored timestamps safe below.
Ignore mode wakes with a gentle tune,
Then normal expiry returns at noon.
The rabbit approves this careful boon.

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% 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
Title check ✅ Passed The title clearly and concisely describes the main change: diagnostic support for ignoring Redis TTL expiration.
Description check ✅ Passed The description covers all template sections, explains behavior and risks, documents validation, and clearly lists incomplete tests and the pending submodule update.
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 💡 1
📝 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.

@thweetkomputer
thweetkomputer marked this pull request as ready for review August 7, 2026 02:42
@thweetkomputer
thweetkomputer requested a review from zhangh43 August 7, 2026 02:42

@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: 5

🤖 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 `@data_substrate`:
- Line 1: Update the data_substrate submodule pointer from unreachable commit
99604109c00967d33c07cc6adf167df51bd33331 to a reachable merged commit from
eloqdata/tx_service#546, or refresh it with git submodule update --remote
data_substrate, then commit the updated pointer.

In `@include/redis_hash_object.h`:
- Around line 268-270: Update HasTTL() and GetTTL() in Redis hash, list, set,
string, and zset object classes to report stored TTL metadata rather than the
process-local ignore flag; use the ignore-only flag exclusively in expiry
enforcement and expiry/read/report paths. Apply the corresponding behavior
consistently in include/redis_hash_object.h (268-270),
include/redis_list_object.h (264-266), include/redis_set_object.h (132-134),
include/redis_string_object.h (283-285), and include/redis_zset_object.h (378).
Update eloqkv.ini (101-107), docs/03-data-model.md (88), and
tests/unit/eloq/object_serialize_deserialize_test.cpp (39-47) only as needed to
reflect and verify the preserved TTL metadata semantics.

In `@include/redis_object.h`:
- Around line 66-80: Update the documentation for the public
RedisEloqObject::SetIgnoreTTL() and IgnoreTTL() APIs to state that the
process-wide mode is configured once during initialization and must not change
while commands execute. Also document that the atomic acquire/release operations
provide visibility only; they do not make runtime mode changes semantically
consistent.

In `@src/redis_service.cpp`:
- Around line 244-251: Update RedisServiceImpl::Init() to parse the
store.ignore_redis_ttl configuration and --ignore_redis_ttl command-line option
before calling EloqDS::IgnoreRedisTTL() and RedisEloqObject::SetIgnoreTTL().
Ensure the parsed setting is applied consistently before the existing warning
logic.

In `@tests/unit/eloq/object_serialize_deserialize_test.cpp`:
- Around line 32-51: The test case “ignore Redis TTL preserves serialized
metadata” must restore the process-wide SetIgnoreTTL state even when an
assertion or exception interrupts execution. Capture the prior ignore-TTL value
before modifying it, then use an RAII guard scoped to the test to restore that
value automatically; retain the existing assertions and serialization behavior.
🪄 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: 1f6adfa2-4b85-4264-8ce9-f0c71a3efb21

📥 Commits

Reviewing files that changed from the base of the PR and between dd05387 and 07c38af.

📒 Files selected for processing (11)
  • data_substrate
  • docs/03-data-model.md
  • eloqkv.ini
  • include/redis_hash_object.h
  • include/redis_list_object.h
  • include/redis_object.h
  • include/redis_set_object.h
  • include/redis_string_object.h
  • include/redis_zset_object.h
  • src/redis_service.cpp
  • tests/unit/eloq/object_serialize_deserialize_test.cpp

Comment thread data_substrate
@@ -1 +1 @@
Subproject commit 63db0ecbe3cd04e23282aa61af3961491647bddf
Subproject commit 99604109c00967d33c07cc6adf167df51bd33331

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.

🗄️ Data Integrity & Integration | 🟠 Major | ⚡ Quick win

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
set -euo pipefail

expected='99604109c00967d33c07cc6adf167df51bd33331'

test "$(git -C data_substrate rev-parse HEAD)" = "$expected"
git -C data_substrate cat-file -e "${expected}^{commit}"

pr_json="$(gh api repos/eloqdata/tx_service/pulls/546)"
test "$(jq -r '.state' <<<"$pr_json")" = "closed"
test "$(jq -r '.merged_at' <<<"$pr_json")" != "null"
test "$(jq -r '.merge_commit_sha' <<<"$pr_json")" = "$expected"

Repository: eloqdata/eloqkv

Length of output: 153


🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "CLAUDE.md presence:"
[ -f CLAUDE.md ] && echo "yes" || echo "no"
[ -f CL AUDE.md ] && echo "CL AUDE.md exists" || true

echo
echo "Submodule files:"
git ls-files data_substrate | head -80 || true

echo
echo "Gitlink in index:"
git ls-files -s data_substrate | sed -n '1p' || true

echo
echo "data_substrate submodule status:"
git submodule status data_substrate || true

echo
echo "CLAUDE.md size/head if present:"
[ -f CLAUDE.md ] && wc -l CLAUDE.md && sed -n '1,220p' CLAUDE.md

echo
echo "Relevant files containing data_substrate:"
rg -n "data_substrate|tx_service|ttl" -S --glob '!**/.git/**' 2>/dev/null | sed -n '1,220p'

Repository: eloqdata/eloqkv

Length of output: 6992


🏁 Script executed:

#!/bin/bash
set -u

expected='99604109c00967d33c07cc6adf167df51bd33331'

echo "Submodule tracked path:"
git ls-files --stage data_substrate data_substrate/ 2>/dev/null || true

echo
echo "Check if expected SHA is reachable from tracked commit (submodule worktree may be absent):"
if git -C data_substrate rev-parse --verify "$expected^{commit}" >/dev/null 2>&1; then
  echo "expected_sha: $expected"
  echo "expected_ref: $(git -C data_substrate rev-parse HEAD)"
  git -C data_substrate merge-base --is-ancestor "$expected" HEAD; echo "ancestor_exit=$?"
  git -C data_substrate merge-base --is-ancestor HEAD "$expected"; echo "reverse_ancestor_exit=$?"
else
  echo "expected SHA not found in submodule worktree"
fi

echo
echo "Upstream PR `#546`:"
pr_json="$(gh api repos/eloqdata/tx_service/pulls/546 --silent)"
printf '%s\n' "$pr_json" | jq '{number,state,title,merged,merged_at,merge_commit_sha}' 2>/dev/null || { printf '%s\n' "$pr_json"; exit 1; }

echo
echo "Remote heads/tags for tx_service relevant refs (no checkout/build):"
git ls-remote --heads --tags https://github.com/eloqdata/tx_service.git \
  refs/heads/main refs/heads/master refs/heads/develop "$expected" 2>/dev/null | sed -n '1,200p' || true

echo
echo "Parent submodule URL from .gitmodules/data_substrate:"
git config --file .gitmodules submodule.data_substrate.url || true

Repository: eloqdata/eloqkv

Length of output: 622


🏁 Script executed:

#!/bin/bash
set -u

expected='99604109c00967d33c07cc6adf167df51bd33331'

echo "git ls-remote all matching $expected:"
git ls-remote https://github.com/eloqdata/tx_service.git "$expected" 2>/dev/null || true

echo
echo "Fetch lightweight tag object if exists:"
tmpdir="$(mktemp -d)"
export GIT_DIR="$tmpdir/empty.git"
git -C "$tmpdir" init --bare >/dev/null
git ls-remote --tags https://github.com/eloqdata/tx_service.git "$expected" 2>/dev/null || true

echo
echo "Resolve SHA by direct GitHub API ref lookup (tags and heads):"
for ref in refs/tags "$expected" refs/heads/main refs/heads/master refs/heads/develop; do
  echo "--- $ref"
  gh api "repos/eloqdata/tx_service/git/ref/$ref" --silent 2>/dev/null | jq '{ref,object:{sha,type}}' || true
done

echo
echo "Compare current PR branch heads:"
for name in main master develop; do
  sha="$(git ls-remote https://github.com/eloqdata/tx_service.git "refs/heads/$name" 2>/dev/null | awk '{print $1}')"
  echo "$name: $sha"
done
echo "expected: $expected"

Repository: eloqdata/eloqkv

Length of output: 1169


Fix the data_substrate submodule pointer.

99604109c00967d33c07cc6adf167df51bd33331 does not exist in eloqdata/tx_service, so this will break git submodule update --init --recursive. Use a reachable merged commit from eloqdata/tx_service#546 or re-run git submodule update --remote data_substrate and commit that pointer.

🤖 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 `@data_substrate` at line 1, Update the data_substrate submodule pointer from
unreachable commit 99604109c00967d33c07cc6adf167df51bd33331 to a reachable
merged commit from eloqdata/tx_service#546, or refresh it with git submodule
update --remote data_substrate, then commit the updated pointer.

Comment on lines 268 to +270
bool HasTTL() const override
{
return true;
return !IgnoreTTL();

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.

🗄️ Data Integrity & Integration | 🟠 Major | ⚡ Quick win

🧩 Analysis chain

🏁 Script executed:

#!/usr/bin/env bash
set -euo pipefail

echo "data_substrate revision:"
git -C data_substrate rev-parse HEAD

echo "data_substrate TTL-ignore and storage paths:"
git -C data_substrate grep -n -C 8 -E \
  'IgnoreRedisTTL|ignore_redis_ttl|TTLCompactionFilter|BatchWriteRecords|HasTTL|GetTTL' \
  -- . || true

echo "Redis HasTTL() consumers:"
git grep -n -C 5 -E 'HasTTL\(\)|GetTTL\(\)' \
  -- include src tests || true

Repository: eloqdata/eloqkv

Length of output: 21507


🏁 Script executed:

#!/usr/bin/env bash
set -euo pipefail

echo "Object method declarations and implementations:"
for f in include/redis_hash_object.h include/redis_list_object.h include/redis_set_object.h include/redis_string_object.h include/redis_zset_object.h src/redis_eloq_object.cpp; do
  if [ -f "$f" ]; then
    echo "== $f =="
    rg -n -C 4 'class Redis(Hash|List|Set|String|Zset)(TTL)?Object|AddTTL|RemoveTTL|Serialize(.*const|\(\))\s*\{|void SetTTL|bool HasTTL|uint64_t GetTTL|ttl_' "$f" || true
  else
    echo "missing $f"
  fi
done

echo "Redis TTL command and service relevant snippets:"
sed -n '1360,1420p' src/redis_command.cpp
sed -n '7600,7790p' src/redis_command.cpp
sed -n '7800,8280p' src/redis_command.cpp
sed -n '8085,8135p' src/redis_command.cpp
sed -n '5005,5035p' src/redis_service.cpp

echo "Repository-wide IgnoreTTL usages:"
rg -n -C 4 'SetIgnoreTTL|IgnoreTTL|ignore_redis_ttl' . --glob '!data_substrate' || true

Repository: eloqdata/eloqkv

Length of output: 47193


Preserve TTL semantics while bypassing expiry enforcement.

HasTTL() now reads a process-local flag, but EXPIRE/PERSIST/TTL commands and checkpoint/TTL-compaction paths use HasTTL() as a metadata presence check. Keep HasTTL()/GetTTL() reflecting the stored TTL, and use the ignore-only flag where expiry enforcement/read/report behavior should be bypassed.

📍 Affects 8 files
  • include/redis_hash_object.h#L268-L270 (this comment)
  • include/redis_list_object.h#L264-L266
  • include/redis_set_object.h#L132-L134
  • include/redis_string_object.h#L283-L285
  • include/redis_zset_object.h#L378-L378
  • eloqkv.ini#L101-L107
  • docs/03-data-model.md#L88-L88
  • tests/unit/eloq/object_serialize_deserialize_test.cpp#L39-L47
🤖 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 `@include/redis_hash_object.h` around lines 268 - 270, Update HasTTL() and
GetTTL() in Redis hash, list, set, string, and zset object classes to report
stored TTL metadata rather than the process-local ignore flag; use the
ignore-only flag exclusively in expiry enforcement and expiry/read/report paths.
Apply the corresponding behavior consistently in include/redis_hash_object.h
(268-270), include/redis_list_object.h (264-266), include/redis_set_object.h
(132-134), include/redis_string_object.h (283-285), and
include/redis_zset_object.h (378). Update eloqkv.ini (101-107),
docs/03-data-model.md (88), and
tests/unit/eloq/object_serialize_deserialize_test.cpp (39-47) only as needed to
reflect and verify the preserved TTL metadata semantics.

Comment thread include/redis_object.h
Comment on lines +66 to +80
/**
* Controls the diagnostic mode that exposes persisted Redis objects even
* after their expiration timestamp. The mode changes only runtime TTL
* interpretation; serialized TTL metadata remains intact so disabling the
* mode on a later restart restores normal expiration.
*/
static void SetIgnoreTTL(bool ignore_ttl)
{
ignore_ttl_.store(ignore_ttl, std::memory_order_release);
}

static bool IgnoreTTL()
{
return ignore_ttl_.load(std::memory_order_acquire);
}

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.

📐 Maintainability & Code Quality | 🟠 Major | ⚡ Quick win

Document the startup-only and atomic-state contract.

RedisEloqObject::IgnoreTTL() is a new public API without a documentation comment. Document that SetIgnoreTTL() sets one process-wide mode during initialization and must not change while commands run. Atomic visibility does not make live mode changes semantically consistent.

As per coding guidelines, **/*.{h,hpp} requires documentation comments for new public APIs, and **/*.{c,cc,cpp,h,hpp} requires non-obvious concurrency and memory-ordering assumptions to be documented.

Proposed documentation
     /**
-     * Controls the diagnostic mode that exposes persisted Redis objects even
-     * after their expiration timestamp. The mode changes only runtime TTL
-     * interpretation; serialized TTL metadata remains intact so disabling the
-     * mode on a later restart restores normal expiration.
+     * Sets the process-wide diagnostic mode. Call this during initialization
+     * before command workers access Redis objects. Do not change the mode
+     * during normal operation.
      */
     static void SetIgnoreTTL(bool ignore_ttl)

+    /**
+     * Returns whether diagnostic TTL-ignore mode is enabled.
+     * Atomic access publishes the setting across worker threads but does not
+     * make runtime mode changes semantically consistent.
+     */
     static bool IgnoreTTL()
📝 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
/**
* Controls the diagnostic mode that exposes persisted Redis objects even
* after their expiration timestamp. The mode changes only runtime TTL
* interpretation; serialized TTL metadata remains intact so disabling the
* mode on a later restart restores normal expiration.
*/
static void SetIgnoreTTL(bool ignore_ttl)
{
ignore_ttl_.store(ignore_ttl, std::memory_order_release);
}
static bool IgnoreTTL()
{
return ignore_ttl_.load(std::memory_order_acquire);
}
/**
* Sets the process-wide diagnostic mode. Call this during initialization
* before command workers access Redis objects. Do not change the mode
* during normal operation.
*/
static void SetIgnoreTTL(bool ignore_ttl)
{
ignore_ttl_.store(ignore_ttl, std::memory_order_release);
}
/**
* Returns whether diagnostic TTL-ignore mode is enabled.
* Atomic access publishes the setting across worker threads but does not
* make runtime mode changes semantically consistent.
*/
static bool IgnoreTTL()
{
return ignore_ttl_.load(std::memory_order_acquire);
}
🤖 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 `@include/redis_object.h` around lines 66 - 80, Update the documentation for
the public RedisEloqObject::SetIgnoreTTL() and IgnoreTTL() APIs to state that
the process-wide mode is configured once during initialization and must not
change while commands execute. Also document that the atomic acquire/release
operations provide visibility only; they do not make runtime mode changes
semantically consistent.

Source: Coding guidelines

Comment thread src/redis_service.cpp
Comment on lines +244 to +251
const bool ignore_redis_ttl = EloqDS::IgnoreRedisTTL();
RedisEloqObject::SetIgnoreTTL(ignore_redis_ttl);
if (ignore_redis_ttl)
{
LOG(WARNING) << "ignore_redis_ttl is enabled: persisted expiration "
"timestamps will be retained but not enforced";
}

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.

🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win

🧩 Analysis chain

🏁 Script executed:

#!/usr/bin/env bash
set -euo pipefail

git -C data_substrate grep -n -C 8 -E \
  'IgnoreRedisTTL|ignore_redis_ttl|Initialize' -- . || true

git grep -n -C 8 -E \
  'RedisServiceImpl::Init|DataSubstrate::Instance|config_file_|ignore_redis_ttl' \
  -- src include eloqkv.ini || true

Repository: eloqdata/eloqkv

Length of output: 24657


🏁 Script executed:

#!/usr/bin/env bash
set -euo pipefail

echo "== locate ignore_redis_ttl =="
rg -n -C 6 'ignore_redis_ttl|IgnoreRedisTTL|SetIgnoreRedisTTL|GetIgnoreRedisTTL' -- . || true

echo "== locate data_substrate init references =="
rg -n -C 5 'DataSubstrate.*Init|Init\(.*config|config.*ignore_redis_ttl|ParseError|CommandLineOption' src include --glob '*.{cpp,cc,c,hpp,h,hxx,cc}' || true

echo "== outline ignore_redis_ttl header/source =="
fd -a 'ignore_redis_ttl\.h|ignore_redis_ttl\.cpp' . || true
for f in $(fd 'ignore_redis_ttl\.(h|cpp)$' .); do echo "--- $f"; ast-grep outline "$f" || true; sed -n '1,240p' "$f"; done

echo "== redis_server startup =="
sed -n '1,120p' src/redis_server.cpp
sed -n '420,475p' src/redis_server.cpp

echo "== redis_service init section =="
sed -n '226,255p' src/redis_service.cpp

Repository: eloqdata/eloqkv

Length of output: 36885


🏁 Script executed:

#!/usr/bin/env bash
set -euo pipefail

echo "== data_substrate header/source candidates =="
git ls-files | rg '(^|/)(data_substrate\.(h|cpp|hpp|cc)$|data_substrate/.*)|(eloq_data_store_service/ignore_redis_ttl\.(h|cpp)$)' || true

echo "== exact matches in git tracked files =="
git ls-files | xargs -r grep -n -H -S -C 4 'IgnoreRedisTTL|ignore_redis_ttl|SetIgnoreRedisTTL|GetIgnoreRedisTTL' || true

echo "== precise function/header definitions =="
rg -n -C 8 'bool\s+IgnoreRedisTTL|void\s+SetIgnoreRedisTTL|SET_IGNORE|IGNORE_REDIS|ignore_redis_ttl' . || true

echo "== startup flag parsing candidates =="
rg -n -C 4 'DEFINE_bool.*ignore|GetCommandLineOption|ignore_redis_ttl|ParseCommandLineFlags|SetCommandLineOption' src include --glob '*.{cpp,cc,h,hpp,cc}' || true

Repository: eloqdata/eloqkv

Length of output: 29601


Parse ignore_redis_ttl before applying it.

RedisServiceImpl::Init() applies EloqDS::IgnoreRedisTTL() without reading store.ignore_redis_ttl from config_. If this setting is advertised as configurable, map store.ignore_redis_ttl and --ignore_redis_ttl through RedisServiceImpl::Init() before RedisEloqObject::SetIgnoreTTL().

🤖 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/redis_service.cpp` around lines 244 - 251, Update
RedisServiceImpl::Init() to parse the store.ignore_redis_ttl configuration and
--ignore_redis_ttl command-line option before calling EloqDS::IgnoreRedisTTL()
and RedisEloqObject::SetIgnoreTTL(). Ensure the parsed setting is applied
consistently before the existing warning logic.

Comment on lines +32 to +51
TEST_CASE("ignore Redis TTL preserves serialized metadata")
{
EloqKV::RedisStringTTLObject object;
object.SetTTL(12345);

EloqKV::RedisEloqObject::SetIgnoreTTL(false);
REQUIRE(object.HasTTL());
std::string before;
object.Serialize(before);

EloqKV::RedisEloqObject::SetIgnoreTTL(true);
REQUIRE_FALSE(object.HasTTL());
REQUIRE(object.GetTTL() == 12345);
std::string ignored;
object.Serialize(ignored);
REQUIRE(ignored == before);

EloqKV::RedisEloqObject::SetIgnoreTTL(false);
REQUIRE(object.HasTTL());
}

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.

🩺 Stability & Availability | 🟡 Minor | ⚡ Quick win

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
set -euo pipefail

# Locate the test file and relevant implementation symbols.
printf '--- files ---\n'
git ls-files | rg '(^|/)object_serialize_deserialize_test\.cpp$|RedisEloqObject|RedisStringTTLObject|IgnoreTTL|SetIgnoreTTL' || true

printf '\n--- test file excerpt ---\n'
sd='tests/unit/eloq/object_serialize_deserialize_test.cpp'
if [ -f "$sd" ]; then
  nl -ba "$sd" | sed -n '1,120p'
fi

printf '\n--- symbol search ---\n'
rg -n "SetIgnoreTTL|IgnoreTTL|class RedisEloqObject|RedisStringTTLObject" . --glob '!build/**' --glob '!dist/**' | head -200

Repository: eloqdata/eloqkv

Length of output: 244


🏁 Script executed:

#!/bin/bash
set -euo pipefail

# Locate the test file and relevant implementation symbols.
echo '--- files ---'
git ls-files | rg '(^|/)object_serialize_deserialize_test\.cpp$|RedisEloqObject|RedisStringTTLObject|IgnoreTTL|SetIgnoreTTL' || true

echo
echo '--- test file excerpt ---'
sd='tests/unit/eloq/object_serialize_deserialize_test.cpp'
if [ -f "$sd" ]; then
  nl -ba "$sd" | sed -n '1,120p'
fi

echo
echo '--- symbol search ---'
rg -n "SetIgnoreTTL|IgnoreTTL|class RedisEloqObject|RedisStringTTLObject" . --glob '!build/**' --glob '!dist/**' | head -200

Repository: eloqdata/eloqkv

Length of output: 289


🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo '--- test file excerpt ---'
sed -n '1,120p' tests/unit/eloq/object_serialize_deserialize_test.cpp | \
  nl -ba

echo
echo '--- symbol search ---'
rg -n "SetIgnoreTTL|IgnoreTTL|class RedisEloqObject|RedisStringTTLObject" . --glob '!build/**' --glob '!dist/**' | head -200

echo
echo '--- definitions/usages ---'
rg -n "SetIgnoreTTL|Ignor(e|Ing)TTL|RedisStringTTLObject::|SetTTL|HasTTL|GetTTL|Serialize\\(" . --glob '!build/**' --glob '!dist/**' | head -300

Repository: eloqdata/eloqkv

Length of output: 219


🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo '--- test file excerpt ---'
awk '{printf "%6d\t%s\n", NR, $0}' tests/unit/eloq/object_serialize_deserialize_test.cpp | sed -n '1,160p'

echo
echo '--- symbol search ---'
rg -n "SetIgnoreTTL|IgnoreTTL|class RedisEloqObject|RedisStringTTLObject" . --glob '!build/**' --glob '!dist/**' | head -200

echo
echo '--- TTL serialization definitions/usages ---'
rg -n "SetIgnoreTTL|Ignor(e|Ing)TTL|RedisStringTTLObject::|RedisEloqObject::|SetTTL|HasTTL|GetTTL|Serialize\\(" . --glob '!build/**' --glob '!dist/**' | head -400

Repository: eloqdata/eloqkv

Length of output: 42758


🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo '--- redis_object.h relevant section ---'
sed -n '1,130p' include/redis_object.h

echo
echo '--- redis_service.cpp ignore_redis_ttl setup ---'
sed -n '220,255p' src/redis_service.cpp

echo
echo '--- search for SetIgnoreTTL calls ---'
rg -n "SetIgnoreTTL\\(" . --glob '!build/**' --glob '!dist/**'

Repository: eloqdata/eloqkv

Length of output: 5390


Restore RedisEloqObject::SetIgnoreTTL after this test.

This test writes a process-wide atomic flag after the Catch2 @section setup. A fatal assertion or exception before the final reset can leave later tests with ignored Redis TTLs; save the previous value and restore it from an RAII guard.

🤖 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 `@tests/unit/eloq/object_serialize_deserialize_test.cpp` around lines 32 - 51,
The test case “ignore Redis TTL preserves serialized metadata” must restore the
process-wide SetIgnoreTTL state even when an assertion or exception interrupts
execution. Capture the prior ignore-TTL value before modifying it, then use an
RAII guard scoped to the test to restore that value automatically; retain the
existing assertions and serialization behavior.

@thweetkomputer
thweetkomputer deleted the feat/ignore-redis-ttl branch September 3, 2026 02:20
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