Skip to content

fix: wire SNAPSHOT_INTERVAL to a periodic timer that triggers mem::snapshot-create - #1010

Closed
yingliang-zhang wants to merge 1 commit into
rohitg00:mainfrom
yingliang-zhang:fix/1006-snapshot-interval-timer
Closed

fix: wire SNAPSHOT_INTERVAL to a periodic timer that triggers mem::snapshot-create#1010
yingliang-zhang wants to merge 1 commit into
rohitg00:mainfrom
yingliang-zhang:fix/1006-snapshot-interval-timer

Conversation

@yingliang-zhang

@yingliang-zhang yingliang-zhang commented Jul 4, 2026

Copy link
Copy Markdown

Summary

The config value (default 3600s) was read and logged at boot — Git snapshots: ... (every 3600s) — but no setInterval timer was ever created. Periodic snapshots never fired automatically. Snapshots only happened when manually triggered via the API/MCP endpoint or the memory_snapshot_create MCP tool.

This means that in a long-running daemon, if no one manually triggers a snapshot, data could be lost on crash/restart with only the last manual snapshot available for recovery.

Fix

Add a setInterval that triggers mem::snapshot-create at the configured interval, following the exact same pattern as the existing auto-forget, lesson-decay, consolidation, and recent-searches-sweep timers:

const snapshotTimer = setInterval(async () => {
    try {
        await sdk.trigger({ function_id: "mem::snapshot-create", payload: {} });
    } catch {}
}, snapshotIntervalMs);
snapshotTimer.unref();

A guard (snapshotIntervalMs > 0) prevents an infinite loop if someone explicitly sets SNAPSHOT_INTERVAL=0.

How to verify

  1. Set SNAPSHOT_ENABLED=true and SNAPSHOT_INTERVAL=10 in .env
  2. Start the daemon: agentmemory
  3. Wait 15 seconds
  4. Run agentmemory mcp and trigger memory_snapshot_list
  5. Verify a periodic snapshot commit appears with a timestamp ~10s after boot
  6. Check daemon.err.log for Snapshot created info entries

Test results

  • npm run build — clean
  • npx vitest run test/snapshot.test.ts — 5/5 passed
  • Full suite: 1411/1415 passed (4 pre-existing failures in embedding-provider.test.ts unrelated to this change, confirmed by running tests on unmodified main)

Fixes #1006

Summary by CodeRabbit

  • New Features

    • Snapshots can run automatically at the configured interval when enabled.
    • Scheduled snapshots run in the background without keeping the process alive.
    • Setting the interval to zero disables periodic snapshots.
    • Errors during scheduled snapshot attempts do not interrupt normal operation.
    • Startup logging indicates whether periodic snapshots are active.
  • Bug Fixes

    • Fixed an issue that could cause a startup error when periodic snapshots were enabled.

@vercel

vercel Bot commented Jul 4, 2026

Copy link
Copy Markdown

@yingliang-zhang is attempting to deploy a commit to the rohitg00's projects Team on Vercel.

A member of the Team first needs to authorize it.

@coderabbitai

coderabbitai Bot commented Jul 4, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

📝 Walkthrough

Walkthrough

When snapshots are enabled, the startup log now references snapshotIntervalMs to report timer status. The variable is undeclared, so startup raises a ReferenceError while formatting the log.

Changes

Snapshot scheduling

Layer / File(s) Summary
Update snapshot startup logging
src/index.ts
Replaces the unconditional snapshot interval log with a conditional message based on snapshotIntervalMs. The enabled-snapshot path can raise a ReferenceError because the variable is undeclared.

Estimated code review effort: 1 (Trivial) | ~5 minutes

Suggested reviewers: rohitg00, honor2030

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Linked Issues check ⚠️ Warning The timer objective is not met because snapshots enabled with SNAPSHOT_INTERVAL causes a ReferenceError from the undeclared snapshotIntervalMs variable [#1006]. Declare and initialize snapshotIntervalMs before using it, then verify timer creation, the SNAPSHOT_INTERVAL=0 guard, and startup logging.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly describes adding a periodic snapshot timer driven by SNAPSHOT_INTERVAL.
Out of Scope Changes check ✅ Passed The reported changes concern snapshot timer setup and its boot log, which are within the linked issue scope [#1006].
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
✨ Finishing Touches 💡 1
🛠️ Fix failing CI checks 💡
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests

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
Contributor

Choose a reason for hiding this comment

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

🧹 Nitpick comments (1)
src/index.ts (1)

359-361: 🎯 Functional Correctness | 🔵 Trivial | ⚡ Quick win

Boot log doesn't reflect whether the periodic timer actually started.

This bootLog always fires when snapshotConfig.enabled, even if snapshotIntervalMs was 0 and the guard at Line 351 skipped creating the timer. Operators would see "Git snapshots: ... (every 0s)" implying periodic snapshots are running, when in fact only manual/API-triggered snapshots work — the exact gap this PR is meant to close.

📝 Proposed fix to clarify boot log
-    bootLog(
-      `Git snapshots: ${snapshotConfig.dir} (every ${snapshotConfig.interval}s)`,
-    );
+    bootLog(
+      snapshotIntervalMs > 0
+        ? `Git snapshots: ${snapshotConfig.dir} (every ${snapshotConfig.interval}s)`
+        : `Git snapshots: ${snapshotConfig.dir} (periodic timer disabled, SNAPSHOT_INTERVAL=0 — manual/API trigger only)`,
+    );
🤖 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/index.ts` around lines 359 - 361, The boot log in the snapshot startup
path is misleading because it always reports periodic Git snapshots even when
the timer was not created. Update the logic around the snapshot initialization
in src/index.ts so the `bootLog` tied to the snapshot setup only runs when
`snapshotIntervalMs` is actually greater than zero and the interval timer is
started, and use the existing snapshot-related symbols like `snapshotConfig` and
`snapshotIntervalMs` to keep the message aligned with real behavior.
🤖 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.

Nitpick comments:
In `@src/index.ts`:
- Around line 359-361: The boot log in the snapshot startup path is misleading
because it always reports periodic Git snapshots even when the timer was not
created. Update the logic around the snapshot initialization in src/index.ts so
the `bootLog` tied to the snapshot setup only runs when `snapshotIntervalMs` is
actually greater than zero and the interval timer is started, and use the
existing snapshot-related symbols like `snapshotConfig` and `snapshotIntervalMs`
to keep the message aligned with real behavior.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: e9c1354b-6df0-4347-a598-53b4256c0abe

📥 Commits

Reviewing files that changed from the base of the PR and between 93ae9bc and 1470ddc.

📒 Files selected for processing (1)
  • src/index.ts

@yingliang-zhang

Copy link
Copy Markdown
Author

Addressed the CodeRabbit nitpick in commit 4b11197 — the boot log now shows periodic timer disabled, SNAPSHOT_INTERVAL=0 — manual trigger only when the guard skips the timer, instead of the misleading every 0s.

…timer

Address CodeRabbit nitpick: the boot log always reported 'every Ns'
even when the timer guard (snapshotIntervalMs > 0) skipped creating
it, making SNAPSHOT_INTERVAL=0 misleadingly look like periodic
snapshots were running.

Signed-off-by: yingliang-zhang <zhangyingliang@outlook.com>
@yingliang-zhang
yingliang-zhang force-pushed the fix/1006-snapshot-interval-timer branch from 4b11197 to 3f3d93f Compare August 4, 2026 02:33

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

🧹 Nitpick comments (1)
src/index.ts (1)

163-164: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Remove the new explanatory comments.

The comments at Lines 163-164 and 357-361 explain implementation behavior. Remove them and keep the code self-describing through clear identifiers and structure.

As per coding guidelines: “Do not add comments explaining what code does; use clear naming instead.”

Also applies to: 357-361

🤖 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/index.ts` around lines 163 - 164, Remove the explanatory comments at the
indicated locations, including the block around the environment-loading logic
near the relevant initialization code, while preserving all surrounding
behavior. Keep the implementation self-describing through its existing
identifiers and structure without adding replacement comments.

Source: Coding guidelines

🤖 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 `@src/index.ts`:
- Around line 373-375: Declare and initialize snapshotIntervalMs in the snapshot
startup flow before the timer guard and boot log, deriving it from the
configured snapshot interval in milliseconds. Reuse this variable in the
existing conditional log while preserving the enabled and manual-trigger-only
messages.

---

Nitpick comments:
In `@src/index.ts`:
- Around line 163-164: Remove the explanatory comments at the indicated
locations, including the block around the environment-loading logic near the
relevant initialization code, while preserving all surrounding behavior. Keep
the implementation self-describing through its existing identifiers and
structure without adding replacement comments.
🪄 Autofix (Beta)

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: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: 0f3638e7-3aed-46a9-9241-43f01b45b8ac

📥 Commits

Reviewing files that changed from the base of the PR and between 4b11197 and 3f3d93f.

📒 Files selected for processing (1)
  • src/index.ts

Comment thread src/index.ts
Comment on lines +373 to +375
snapshotIntervalMs > 0
? `Git snapshots: ${snapshotConfig.dir} (every ${snapshotConfig.interval}s)`
: `Git snapshots: ${snapshotConfig.dir} (periodic timer disabled, SNAPSHOT_INTERVAL=0 — manual trigger only)`,

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 | 🔴 Critical | ⚡ Quick win

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "== locate files =="
git ls-files | rg '(^|/)src/index\.ts$|package\.json$' || true

echo "== relevant section =="
if [ -f src/index.ts ]; then
  wc -l src/index.ts
  sed -n '330,390p' src/index.ts | nl -ba -v330
fi

echo "== definitions/usages =="
rg -n "snapshotIntervalMs|snapshotConfig|snapshot" src/index.ts package.json || true

echo "== package module type =="
if [ -f package.json ]; then
  node -e "const p=require('./package.json'); console.log(JSON.stringify({type:p.type, main:p.main, dependencies:p.dependencies || {}, devDependencies:p.devDependencies || {}}, null, 2))"
fi

Repository: rohitg00/agentmemory

Length of output: 440


🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "== locate files =="
git ls-files | rg '(^|/)src/index\.ts$|package\.json$' || true

echo "== package module type =="
if [ -f package.json ]; then
  node -e "const p=require('./package.json'); console.log(JSON.stringify({type:p.type, main:p.main, dependencies:p.dependencies || {}, devDependencies:p.devDependencies || {}}, null, 2))"
fi

echo "== relevant src/index.ts section and identifiers =="
if [ -f src/index.ts ]; then
  wc -l src/index.ts
  sed -n '320,400p' src/index.ts | nl -ba -v320
  echo "== identifier occurrences =="
  rg -n "snapshotIntervalMs|snapshotConfig|GIT_SNAPSHOT|SNAPSHOT|interval" src/index.ts || true
fi

Repository: rohitg00/agentmemory

Length of output: 945


🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "== package name/context =="
sed -n '1,25p' src/index.ts

echo "== snapshot identifier occurrences =="
python3 - <<'PY'
from pathlib import Path
p=Path('src/index.ts')
print(f'src/index.ts lines={len(p.read_text().splitlines())}')
for i,line in enumerate(p.read_text().splitlines(),1):
    if 'snapshotIntervalMs' in line or 'snapshotConfig' in line or 'interval' in line and ('Snapshot' in line or 'SNAPSHOT' in line or 'git' in line.lower()):
        print(f'{i}: {line}')
PY

echo "== lines 330-390 =="
python3 - <<'PY'
from pathlib import Path
lines=Path('src/index.ts').read_text().splitlines()
for i in range(330, min(len(lines),390)+1):
    print(f'{i}: {lines[i-1]}')
PY

Repository: rohitg00/agentmemory

Length of output: 4037


Declare snapshotIntervalMs before the snapshot boot log.

snapshotIntervalMs is not defined in src/index.ts, so TypeScript rejects this file and execution raises ReferenceError when snapshots are enabled. Add the millisecond value before the timer guard and reuse it in the log.

🤖 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/index.ts` around lines 373 - 375, Declare and initialize
snapshotIntervalMs in the snapshot startup flow before the timer guard and boot
log, deriving it from the configured snapshot interval in milliseconds. Reuse
this variable in the existing conditional log while preserving the enabled and
manual-trigger-only messages.

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.

Bug: SNAPSHOT_INTERVAL config is read and logged but no setInterval timer triggers mem::snapshot-create

1 participant