Skip to content

fix(state): throttle repeated VACUUM rewrites - #67351

Closed
nkreadly07 wants to merge 2 commits into
NousResearch:mainfrom
nkreadly07:fix/state-db-vacuum-throttle
Closed

fix(state): throttle repeated VACUUM rewrites#67351
nkreadly07 wants to merge 2 commits into
NousResearch:mainfrom
nkreadly07:fix/state-db-vacuum-throttle

Conversation

@nkreadly07

@nkreadly07 nkreadly07 commented Jul 19, 2026

Copy link
Copy Markdown
Contributor

Summary

  • throttle state.db VACUUM rewrites independently from the normal auto-prune cadence
  • expose the threshold as sessions.min_vacuum_interval_days with a 30-day default
  • wire the setting through both CLI and gateway startup maintenance
  • persist the last successful VACUUM timestamp in state_meta
  • keep failed VACUUM attempts retryable because the timestamp is written only after success
  • document the behavior in the English and Chinese session guides
  • cover success, suppression, expiry, failed-VACUUM retry, and config propagation

VACUUM rewrites the complete SQLite database and holds an exclusive lock. Auto-maintenance may run daily across long-lived entrypoints, so it should not repeat that expensive rewrite merely because rows were pruned during another routine sweep. This keeps pruning cadence unchanged while limiting VACUUM independently through normal config.yaml behavior.

Related: #54189

Verification

  • uv run --extra dev pytest tests/test_hermes_state.py tests/test_session_vacuum_config.py -q --tb=short379 passed
  • uv run --extra dev ruff check hermes_state.py cli.py gateway/run.py hermes_cli/config.py tests/test_hermes_state.py tests/test_session_vacuum_config.py — passed
  • uv run python -m py_compile hermes_state.py cli.py gateway/run.py hermes_cli/config.py tests/test_hermes_state.py tests/test_session_vacuum_config.py — passed
  • git diff --check origin/main...HEAD — passed
  • independent read-only review — approved, no blocking correctness, compatibility, test, or documentation findings

Review follow-up

Addressed the sweeper feedback in 4bbf0ce66:

  • added sessions.min_vacuum_interval_days: 30 to DEFAULT_CONFIG
  • forwarded it from both startup callers
  • updated session-maintenance documentation and config examples
  • added a failed-VACUUM regression proving the marker remains unset and the next due call retries

Notes

  • rebased onto current upstream main (5854aad8b) after the review follow-up
  • no environment variable or migration is required; behavioral configuration remains in config.yaml
  • existing user configs receive the default through the normal deep merge
  • the last_vacuum marker is written only after VACUUM succeeds

@nkreadly07
nkreadly07 force-pushed the fix/state-db-vacuum-throttle branch from 6c1716a to df6bb05 Compare July 19, 2026 07:01

@teknium1 teknium1 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.

Thanks for addressing the expensive full-database rewrite. The repeated-VACUUM premise is real on current main: hermes_state.py:7609-7612 invokes VACUUM after every eligible pruning sweep, and the PR's success-only last_vacuum write is the right retry shape.

Problems

  • The new 30-day threshold is only a hard-coded SessionDB default. Current entrypoints pass no corresponding setting (cli.py:1860-1865; gateway/run.py:3309-3314), while AGENTS.md:102-105 requires behavioral thresholds in config.yaml. It also makes the current documentation inaccurate: website/docs/user-guide/sessions.md:692 says every successful prune is followed by VACUUM.
  • The added tests cover successful recording, recent-marker suppression, and expiry, but not the stated failed-VACUUM retry guarantee. Add a raising vacuum() case that verifies no last_vacuum marker is written and a later due call retries.

Suggested changes

  • Add and document sessions.min_vacuum_interval_days: 30, then pass it from both startup callers.
  • Add the failed-VACUUM regression test.

Automated hermes-sweeper review.

Comment thread hermes_state.py
@@ -7564,12 +7564,16 @@ def maybe_auto_prune_and_vacuum(
min_interval_hours: int = 24,
vacuum: bool = True,
sessions_dir: Optional[Path] = None,
min_vacuum_interval_days: int = 30,

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.

Please surface this behavioral threshold through sessions configuration and wire it from the CLI and gateway callers. Current callers only pass min_interval_hours, and the existing docs promise VACUUM after every pruning sweep; a hard-coded 30-day product behavior leaves both configuration and documentation out of sync.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Addressed in 393fd1cf8: added sessions.min_vacuum_interval_days: 30 to DEFAULT_CONFIG, wired it through both CLI and gateway startup callers, updated the English and Chinese session docs/config examples, and added a failed-VACUUM regression proving the success marker remains unset and the next due call retries. Focused validation now passes 379 tests plus Ruff, py_compile, and git diff --check.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Rebase note: upstream main advanced after the follow-up push, so the branch was rebased onto 5854aad8b and revalidated (379 tests plus Ruff, py_compile, and diff check). The review-response commit is now 4bbf0ce66; behavior is unchanged from the earlier referenced SHA.

@alt-glitch alt-glitch added type/perf Performance improvement or optimization P2 Medium — degraded but workaround exists comp/cron Cron scheduler and job management sweeper:risk-session-state Sweeper risk: may lose/corrupt/mis-associate session or context state labels Jul 19, 2026
@teknium1 teknium1 added sweeper:risk-compatibility Sweeper risk: may break existing users, config, migrations, defaults, or upgrades sweeper:blast-moderate Sweeper blast radius: moderate — a subsystem or single platform labels Jul 19, 2026
@kshitijk4poor

Copy link
Copy Markdown
Collaborator

Merged via #76839 — thank you @nkreadly07. Both your commits were cherry-picked, so you remain the author in git history.

The fix was correct and complete as written: the pruned > 0 VACUUM gate really did rewrite the whole DB on every startup sweep once pruning freed rows, and your last_vacuum stamp + min_vacuum_interval_days throttle (with the failed-VACUUM-doesn't-stamp retry path and corrupt-meta fallback) is exactly the right shape. Your 4 throttle tests + config/CLI-forwarding tests all pass on current main and fail when the fix is reverted (mutation-checked).

The only salvage work was mechanical retargeting: your branch predated the DEFAULT_CONFIG move to hermes_cli/config_defaults.py (1fe0611), so the config hunk was re-aimed there, plus docs/test conflict resolution. No behavior changes to your code.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

comp/cron Cron scheduler and job management P2 Medium — degraded but workaround exists sweeper:blast-moderate Sweeper blast radius: moderate — a subsystem or single platform sweeper:risk-compatibility Sweeper risk: may break existing users, config, migrations, defaults, or upgrades sweeper:risk-session-state Sweeper risk: may lose/corrupt/mis-associate session or context state type/perf Performance improvement or optimization

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants