Skip to content

Add auto-repair options for broken AOF tail on startup#7

Open
tomerqodo wants to merge 22 commits into
coderabbit_full_base_add_auto-repair_options_for_broken_aof_tail_on_startup_pr7from
coderabbit_full_head_add_auto-repair_options_for_broken_aof_tail_on_startup_pr7
Open

Add auto-repair options for broken AOF tail on startup#7
tomerqodo wants to merge 22 commits into
coderabbit_full_base_add_auto-repair_options_for_broken_aof_tail_on_startup_pr7from
coderabbit_full_head_add_auto-repair_options_for_broken_aof_tail_on_startup_pr7

Conversation

@tomerqodo

@tomerqodo tomerqodo commented Jan 30, 2026

Copy link
Copy Markdown

Benchmark PR from agentic-review-benchmarks#7

Summary by CodeRabbit

  • New Features
    • Added automatic recovery from corrupted AOF files. When corruption is detected in the middle of the file, the server can automatically truncate the corrupted section and recover if the corruption size is below a configured threshold. This allows continued operation with a warning, while larger corruption requires manual intervention.

✏️ Tip: You can customize this high-level summary in your review settings.

@coderabbitai

coderabbitai Bot commented Jan 30, 2026

Copy link
Copy Markdown
📝 Walkthrough

Walkthrough

This change introduces automatic AOF corruption recovery functionality to Redis. Two new configuration options (aof-load-broken and aof-load-broken-max-size) enable truncation and recovery of mid-file corrupted AOF data when the corrupted portion falls below a configurable threshold, complementing the existing end-of-file truncation mechanism.

Changes

Cohort / File(s) Summary
Configuration Options
redis.conf, src/config.c
Added two new configuration parameters: aof-load-broken (boolean, default disabled) and aof-load-broken-max-size (numeric, default 4096 bytes) to control corruption recovery behavior during AOF loading.
Core AOF Loading Logic
src/aof.c
Modified loadSingleAppendOnlyFile to handle mid-file corruption by truncating at the last valid position when corruption size is within limits; updated loadAppendOnlyFiles to recognize the new AOF_BROKEN_RECOVERED status alongside existing AOF_TRUNCATED handling.
Server State & Constants
src/server.h
Added new AOF_BROKEN_RECOVERED constant (value 6) for recovery status tracking; extended redisServer struct with aof_load_broken and aof_load_broken_max_size fields; renamed header guard from __REDIS_H to _REDIS_H.
Integration Tests
tests/integration/aof.tcl
Added comprehensive test suite covering corrupted base AOF recovery, incremental AOF corruption scenarios, mixed file sequences, size threshold enforcement, and logging validation to verify recovery behavior under various corruption conditions.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Poem

🐰 A broken tail of files once lost,
Now hops back whole, whatever cost!
With limits set and warnings clear,
Our AOF recovery's here! ✨

🚥 Pre-merge checks | ✅ 3
✅ Passed checks (3 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title accurately reflects the main feature: adding auto-repair options for handling broken AOF (Append-Only File) tails during startup, which is confirmed by changes across configuration, core AOF loading logic, and comprehensive tests.
Docstring Coverage ✅ Passed Docstring coverage is 100.00% which is sufficient. The required threshold is 80.00%.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing touches
  • 📝 Generate docstrings
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch coderabbit_full_head_add_auto-repair_options_for_broken_aof_tail_on_startup_pr7

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 and usage tips.

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

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
src/aof.c (1)

1893-1895: ⚠️ Potential issue | 🟠 Major

Bug: stopLoading does not treat AOF_BROKEN_RECOVERED as success.

When AOF recovery succeeds with AOF_BROKEN_RECOVERED, the stopLoading call marks it as a failure because only AOF_OK and AOF_TRUNCATED are considered successful outcomes. This means successful broken-tail recovery will incorrectly report loading failure.

Proposed fix
 cleanup:
-    stopLoading(ret == AOF_OK || ret == AOF_TRUNCATED);
+    stopLoading(ret == AOF_OK || ret == AOF_TRUNCATED || ret == AOF_BROKEN_RECOVERED);
     return ret;
 }
🤖 Fix all issues with AI agents
In `@tests/integration/aof.tcl`:
- Around line 723-726: The test currently uses "exec rm -f
$aof_dirpath/appendonly.aof.*" which does not glob in Tcl; replace that with a
glob-based removal and manifest rewrite: use "glob -nocomplain
$aof_dirpath/appendonly.aof.*" to collect incremental AOF files then "file
delete" each returned path so only the base AOF remains, and update the manifest
(appendonly.aof.manifest) in the same directory to list only the base file
(ensure start_server_aof/test "Corrupted base AOF (last file): should recover"
sees a base-only manifest); keep references to $aof_dirpath, appendonly.aof.*,
and the manifest file when making the change.
🧹 Nitpick comments (3)
src/server.h (1)

15-16: Header guard still uses reserved identifier namespace.

The change from __REDIS_H to _REDIS_H is an improvement, but identifiers starting with an underscore followed by an uppercase letter are still reserved by the C standard (C99 §7.1.3) in the global namespace. Consider using REDIS_SERVER_H or REDIS_H without a leading underscore for full compliance.

This is a minor concern since the pattern is common in practice and unlikely to cause issues.

♻️ Suggested fix
-#ifndef _REDIS_H
-#define _REDIS_H
+#ifndef REDIS_SERVER_H
+#define REDIS_SERVER_H

Note: The corresponding #endif at the end of the file would not need to change.

src/config.c (1)

3257-3259: Consider allowing memory-unit suffixes for aof-load-broken-max-size.
Using INTEGER_CONFIG rejects values like 4kb even though this is a byte-size option. Switching to MEMORY_CONFIG preserves defaults and aligns with other size configs.

Proposed change
-    createOffTConfig("aof-load-broken-max-size", NULL, MODIFIABLE_CONFIG, 0, LONG_MAX, server.aof_load_broken_max_size, 4*1024, INTEGER_CONFIG, NULL, NULL),
+    createOffTConfig("aof-load-broken-max-size", NULL, MODIFIABLE_CONFIG, 0, LONG_MAX, server.aof_load_broken_max_size, 4*1024, MEMORY_CONFIG, NULL, NULL),
src/aof.c (1)

1830-1843: Inconsistency: AOF_BROKEN_RECOVERED handling differs between BASE and INCR files.

Line 1841 includes AOF_BROKEN_RECOVERED in the goto cleanup condition, but line 1875 (INCR handling) does not. This causes asymmetric behavior:

  • For INCR files: AOF_BROKEN_RECOVERED on last file proceeds normally through cleanup
  • For BASE files: AOF_BROKEN_RECOVERED always jumps to cleanup, even when it's the last file and recovery succeeded

If the BASE file is the only file (no INCR files), this still works, but the explicit inclusion of AOF_BROKEN_RECOVERED here appears inconsistent with the INCR handling pattern.

Suggested fix for consistency
-        if (ret == AOF_OPEN_ERR || ret == AOF_FAILED || ret == AOF_BROKEN_RECOVERED) {
+        if (ret == AOF_OPEN_ERR || ret == AOF_FAILED) {
             goto cleanup;
         }

Comment thread tests/integration/aof.tcl
Comment on lines +723 to +726
# Remove all incr AOF files to make the base file being the last file
exec rm -f $aof_dirpath/appendonly.aof.*
start_server_aof [list dir $server_path aof-load-broken yes] {
test "Corrupted base AOF (last file): should recover" {

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major

Fix incremental AOF cleanup—exec doesn’t glob in Tcl.
exec rm -f $aof_dirpath/appendonly.aof.* passes the * literally, so no files are removed (and if globbed, it would also delete the base + manifest). This makes the “base is last file” recovery test unreliable. Use glob/file delete and rewrite a base-only manifest.

Proposed fix
-    exec rm -f $aof_dirpath/appendonly.aof.*
+    foreach f [glob -nocomplain "$aof_dirpath/appendonly.aof.*.incr.aof"] {
+        file delete -force $f
+    }
+    create_aof_manifest $aof_dirpath $aof_manifest_file {
+        append_to_manifest "file appendonly.aof.1.base.aof seq 1 type b\n"
+    }
🤖 Prompt for AI Agents
In `@tests/integration/aof.tcl` around lines 723 - 726, The test currently uses
"exec rm -f $aof_dirpath/appendonly.aof.*" which does not glob in Tcl; replace
that with a glob-based removal and manifest rewrite: use "glob -nocomplain
$aof_dirpath/appendonly.aof.*" to collect incremental AOF files then "file
delete" each returned path so only the base AOF remains, and update the manifest
(appendonly.aof.manifest) in the same directory to list only the base file
(ensure start_server_aof/test "Corrupted base AOF (last file): should recover"
sees a base-only manifest); keep references to $aof_dirpath, appendonly.aof.*,
and the manifest file when making the change.

@coderabbitai

coderabbitai Bot commented Feb 2, 2026

Copy link
Copy Markdown
✅ Actions performed

Review triggered.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

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.

2 participants