mirror of
https://github.com/openclaw/openclaw.git
synced 2026-04-03 03:03:24 -04:00
fix: unify session maintenance and cron run pruning (#13083)
* fix: prune stale session entries, cap entry count, and rotate sessions.json
The sessions.json file grows unbounded over time. Every heartbeat tick (default: 30m)
triggers multiple full rewrites, and session keys from groups, threads, and DMs
accumulate indefinitely with large embedded objects (skillsSnapshot,
systemPromptReport). At >50MB the synchronous JSON parse blocks the event loop,
causing Telegram webhook timeouts and effectively taking the bot down.
Three mitigations, all running inside saveSessionStoreUnlocked() on every write:
1. Prune stale entries: remove entries with updatedAt older than 30 days
(configurable via session.maintenance.pruneDays in openclaw.json)
2. Cap entry count: keep only the 500 most recently updated entries
(configurable via session.maintenance.maxEntries). Entries without updatedAt
are evicted first.
3. File rotation: if the existing sessions.json exceeds 10MB before a write,
rename it to sessions.json.bak.{timestamp} and keep only the 3 most recent
backups (configurable via session.maintenance.rotateBytes).
All three thresholds are configurable under session.maintenance in openclaw.json
with Zod validation. No env vars.
Existing tests updated to use Date.now() instead of epoch-relative timestamps
(1, 2, 3) that would be incorrectly pruned as stale.
27 new tests covering pruning, capping, rotation, and integration scenarios.
* feat: auto-prune expired cron run sessions (#12289)
Add TTL-based reaper for isolated cron run sessions that accumulate
indefinitely in sessions.json.
New config option:
cron.sessionRetention: string | false (default: '24h')
The reaper runs piggy-backed on the cron timer tick, self-throttled
to sweep at most every 5 minutes. It removes session entries matching
the pattern cron:<jobId>:run:<uuid> whose updatedAt + retention < now.
Design follows the Kubernetes ttlSecondsAfterFinished pattern:
- Sessions are persisted normally (observability/debugging)
- A periodic reaper prunes expired entries
- Configurable retention with sensible default
- Set to false to disable pruning entirely
Files changed:
- src/config/types.cron.ts: Add sessionRetention to CronConfig
- src/config/zod-schema.ts: Add Zod validation for sessionRetention
- src/cron/session-reaper.ts: New reaper module (sweepCronRunSessions)
- src/cron/session-reaper.test.ts: 12 tests covering all paths
- src/cron/service/state.ts: Add cronConfig/sessionStorePath to deps
- src/cron/service/timer.ts: Wire reaper into onTimer tick
- src/gateway/server-cron.ts: Pass config and session store path to deps
Closes #12289
* fix: sweep cron session stores per agent
* docs: add changelog for session maintenance (#13083) (thanks @skyfallsin, @Glucksberg)
* fix: add warn-only session maintenance mode
* fix: warn-only maintenance defaults to active session
* fix: deliver maintenance warnings to active session
* docs: add session maintenance examples
* fix: accept duration and size maintenance thresholds
* refactor: share cron run session key check
* fix: format issues and replace defaultRuntime.warn with console.warn
---------
Co-authored-by: Pradeep Elankumaran <pradeepe@gmail.com>
Co-authored-by: Glucksberg <markuscontasul@gmail.com>
Co-authored-by: max <40643627+quotentiroler@users.noreply.github.com>
Co-authored-by: quotentiroler <max.nussbaumer@maxhealth.tech>
This commit is contained in:
committed by
GitHub
parent
0657d7c772
commit
e19a23520c
@@ -160,6 +160,12 @@ Save to `~/.openclaw/openclaw.json` and you can DM the bot from that number.
|
||||
},
|
||||
resetTriggers: ["/new", "/reset"],
|
||||
store: "~/.openclaw/agents/default/sessions/sessions.json",
|
||||
maintenance: {
|
||||
mode: "warn",
|
||||
pruneAfter: "30d",
|
||||
maxEntries: 500,
|
||||
rotateBytes: "10mb",
|
||||
},
|
||||
typingIntervalSeconds: 5,
|
||||
sendPolicy: {
|
||||
default: "allow",
|
||||
@@ -344,6 +350,7 @@ Save to `~/.openclaw/openclaw.json` and you can DM the bot from that number.
|
||||
enabled: true,
|
||||
store: "~/.openclaw/cron/cron.json",
|
||||
maxConcurrentRuns: 2,
|
||||
sessionRetention: "24h",
|
||||
},
|
||||
|
||||
// Webhooks
|
||||
|
||||
@@ -2767,6 +2767,12 @@ Controls session scoping, reset policy, reset triggers, and where the session st
|
||||
// Default is already per-agent under ~/.openclaw/agents/<agentId>/sessions/sessions.json
|
||||
// You can override with {agentId} templating:
|
||||
store: "~/.openclaw/agents/{agentId}/sessions/sessions.json",
|
||||
maintenance: {
|
||||
mode: "warn",
|
||||
pruneAfter: "30d",
|
||||
maxEntries: 500,
|
||||
rotateBytes: "10mb",
|
||||
},
|
||||
// Direct chats collapse to agent:<agentId>:<mainKey> (default: "main").
|
||||
mainKey: "main",
|
||||
agentToAgent: {
|
||||
@@ -2803,6 +2809,11 @@ Fields:
|
||||
- `agentToAgent.maxPingPongTurns`: max reply-back turns between requester/target (0–5, default 5).
|
||||
- `sendPolicy.default`: `allow` or `deny` fallback when no rule matches.
|
||||
- `sendPolicy.rules[]`: match by `channel`, `chatType` (`direct|group|room`), or `keyPrefix` (e.g. `cron:`). First deny wins; otherwise allow.
|
||||
- `maintenance`: session store maintenance settings for pruning, capping, and rotation.
|
||||
- `mode`: `"warn"` (default) warns the active session (best-effort delivery) when it would be evicted without enforcing maintenance. `"enforce"` applies pruning and rotation.
|
||||
- `pruneAfter`: remove entries older than this duration (for example `"30m"`, `"1h"`, `"30d"`). Default "30d".
|
||||
- `maxEntries`: cap the number of session entries kept (default 500).
|
||||
- `rotateBytes`: rotate `sessions.json` when it exceeds this size (for example `"10kb"`, `"1mb"`, `"10mb"`). Default "10mb".
|
||||
|
||||
### `skills` (skills config)
|
||||
|
||||
@@ -3407,10 +3418,15 @@ Cron is a Gateway-owned scheduler for wakeups and scheduled jobs. See [Cron jobs
|
||||
cron: {
|
||||
enabled: true,
|
||||
maxConcurrentRuns: 2,
|
||||
sessionRetention: "24h",
|
||||
},
|
||||
}
|
||||
```
|
||||
|
||||
Fields:
|
||||
|
||||
- `sessionRetention`: how long to keep completed cron run sessions before pruning. Accepts a duration string like `"24h"` or `"7d"`. Use `false` to disable pruning. Default is 24h.
|
||||
|
||||
---
|
||||
|
||||
_Next: [Agent Runtime](/concepts/agent)_ 🦞
|
||||
|
||||
Reference in New Issue
Block a user