Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions docs/03-data-model.md
Original file line number Diff line number Diff line change
Expand Up @@ -85,6 +85,7 @@ Key predicates as EloqKV implements them:
- **Lazy enforcement (engine side)**: during ApplyCc the `ObjectCcMap` reads the payload's TTL; if expired, read-only commands return `RecordStatus::Deleted` immediately, and mutating commands set `ttl_expired_` so the engine first applies `RetireExpiredTTLObjectCommand()` (= `DelCommand`) and then runs the new command on a fresh object (`data_substrate/tx_service/include/cc/object_cc_map.h:657-673`, `:928`). Reads from the KV store likewise treat expired records as deleted, and physical reclamation is compaction-driven (`TTLCompactionFilter`) — `data_substrate/docs/09-store-handler.md` §"Record TTL". In-memory pages track `smallest_ttl_` so page cleaning can drop expired entries wholesale (`cc/cc_page_clean_guard.h:78-123`).
- **WAL correctness for TTL-only writes**: EXPIRE/PERSIST/GETEX mutate only the TTL, are *not* overwrites, yet replay must not depend on fetching the old value from the KV store. So when they will actually reset a TTL, `ExecuteOn` serializes the **whole current object** into an attached `RecoverObjectCommand` (`recover_ttl_obj_cmd_`, `src/redis_command.cpp:7923-7927`, `:7741-7742`); the engine logs that command's image instead (`RecoverTTLObjectCommand()` hook, `object_cc_map.h:1085`). `RecoverObjectCommand` is itself an overwrite whose `CommitOn` rebuilds the TTL object from the embedded blob (`src/redis_command.cpp:7601-7677`). For a key owned by a **remote** node group the coordinator (not the owner) writes the WAL, so the owner returns these facts in `ApplyResponse` (engine fields 10-13, eloqdata/eloqkv#509): `ttl_reset` + `recover_cmd_image` (the owner-serialized snapshot, logged as an overwrite record), the **post-command** object `ttl` (validity horizon, else the remote path logged `UINT64_MAX` and recovery could resurrect an expired object), and `ttl_expired` (the coordinator prepends the retire `DelCommand` record for the expired-then-recreated key). The owner always reports the post-command ttl — an expired-recreation write reports `UINT64_MAX`, not the stale expired value, which also fixed a pre-existing *local* recovery loss (acknowledged expired-key recreations were discarded at replay). Old owners whose response omits fields 10-13 degrade to the previous behavior.
- The checkpointer hands each record's TTL to the store handler (`BatchWriteRecords` items carry a ttl), keyed off `HasTTL()/GetTTL()` — `object_cc_map.h:640-652`, engine doc 09.
- **Diagnostic TTL bypass**: RocksDB-backed EloqDSS builds accept `--ignore_redis_ttl=true` (or `[store] ignore_redis_ttl=true`). The flag makes Redis TTL objects report no TTL at runtime, bypasses the EloqDSS point-read/scan expiry filters, and disables physical TTL removal by the RocksDB compaction filter. It does **not** rewrite either the outer DSS TTL header or the TTL embedded in the Redis object blob; after all EloqKV and DSS processes restart with the flag disabled, normal expiration resumes from the original absolute timestamp. The mode is intended for isolated diagnostic clusters; ordinary writes still have their normal persistent effects.

## 7. The Catalog Factory (`include/eloqkv_catalog_factory.h`, `src/eloqkv_catalog_factory.cpp`)

Expand Down
7 changes: 7 additions & 0 deletions eloqkv.ini
Original file line number Diff line number Diff line change
Expand Up @@ -98,6 +98,13 @@ node_group_replica_num = 1
# auto_redirect = false

[store]
# Diagnostic mode for RocksDB/RocksDB Cloud only. When true, persisted Redis
# keys remain visible after their TTL expires and TTL/PTTL report no expiry.
# The stored TTL bytes are not changed; setting this back to false and
# restarting restores normal expiration. Enable it on every EloqKV and DSS
# process that accesses the diagnostic store.
# ignore_redis_ttl=false

# Shard data directories.
# Format: path1,path2,...[,pathN][:weight1,weight2,...,weightN]
# Weights are optional. When omitted, disk-capacity-based weighting is used.
Expand Down
2 changes: 1 addition & 1 deletion include/redis_hash_object.h
Original file line number Diff line number Diff line change
Expand Up @@ -267,7 +267,7 @@ class RedisHashTTLObject : public RedisHashObject

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

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.

}

RedisObjectType ObjectType() const override
Expand Down
2 changes: 1 addition & 1 deletion include/redis_list_object.h
Original file line number Diff line number Diff line change
Expand Up @@ -263,7 +263,7 @@ struct RedisListTTLObject : public RedisListObject

bool HasTTL() const override
{
return true;
return !IgnoreTTL();
}

RedisObjectType ObjectType() const override
Expand Down
20 changes: 20 additions & 0 deletions include/redis_object.h
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
#pragma once

#include <algorithm>
#include <atomic>
#include <cstddef>
#include <deque>
#include <memory>
Expand Down Expand Up @@ -62,6 +63,22 @@ enum struct RedisObjectType
struct RedisEloqObject : public txservice::TxObject
{
public:
/**
* 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);
}
Comment on lines +66 to +80

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


TxRecord::Uptr Clone() const override
{
assert(false);
Expand Down Expand Up @@ -128,5 +145,8 @@ struct RedisEloqObject : public txservice::TxObject
{
return std::make_unique<RedisEloqObject>();
}

private:
inline static std::atomic_bool ignore_ttl_{false};
};
} // namespace EloqKV
2 changes: 1 addition & 1 deletion include/redis_set_object.h
Original file line number Diff line number Diff line change
Expand Up @@ -131,7 +131,7 @@ class RedisHashSetTTLObject : public RedisHashSetObject

bool HasTTL() const override
{
return true;
return !IgnoreTTL();
}

RedisObjectType ObjectType() const override
Expand Down
2 changes: 1 addition & 1 deletion include/redis_string_object.h
Original file line number Diff line number Diff line change
Expand Up @@ -282,7 +282,7 @@ struct RedisStringTTLObject : public RedisStringObject

bool HasTTL() const override
{
return true;
return !IgnoreTTL();
}

RedisObjectType ObjectType() const override
Expand Down
2 changes: 1 addition & 1 deletion include/redis_zset_object.h
Original file line number Diff line number Diff line change
Expand Up @@ -375,7 +375,7 @@ class RedisZsetTTLObject : public RedisZsetObject

bool HasTTL() const override
{
return true;
return !IgnoreTTL();
}

RedisObjectType ObjectType() const override
Expand Down
9 changes: 9 additions & 0 deletions src/redis_service.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,7 @@
#include "b255.h"
#include "catalog_factory.h"
#include "data_substrate.h"
#include "eloq_data_store_service/ignore_redis_ttl.h"
#include "eloq_metrics/include/metrics.h"
#include "eloqkv_key.h"
#include "error_messages.h"
Expand Down Expand Up @@ -240,6 +241,14 @@ bool RedisServiceImpl::Init(brpc::Server &brpc_server)
return false;
}

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";
}

Comment on lines +244 to +251

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.

// Engine registration: EloqKv
auto &ds = DataSubstrate::Instance();

Expand Down
22 changes: 22 additions & 0 deletions tests/unit/eloq/object_serialize_deserialize_test.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
#include "redis_errors.h"
#include "redis_hash_object.h"
#include "redis_list_object.h"
#include "redis_string_object.h"
#include "redis_zset_object.h"

absl::flat_hash_map<std::string_view, double> EloqKV::RedisZsetObject::*
Expand All @@ -28,6 +29,27 @@ struct Rob
}
};

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());
}
Comment on lines +32 to +51

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.


TEST_CASE("zset_object-string")
{
LOG(INFO) << "running: zset_object-string: ";
Expand Down
Loading