mirror of
https://github.com/openclaw/openclaw.git
synced 2026-05-19 16:25:50 +00:00
`session_end` was only fired when a session was replaced, reset, deleted, or
compacted -- the gateway shutdown/restart paths closed the process without
enumerating active sessions, so downstream `session_end` plugins
(e.g. claude-mem) accumulated ghost rows in `active` state across restarts.
Issue reporter saw 11 orphaned sessions cause 63 timeouts/day from agent
pool exhaustion.
Add an in-memory active-session tracker
(`src/gateway/active-sessions-shutdown-tracker.ts`) populated by
`emitGatewaySessionStartPluginHook` and forgotten unconditionally by
`emitGatewaySessionEndPluginHook` (even when no plugin listens), so any
session that has already been finalized through the normal lifecycle is
never re-fired by the shutdown drain. The close handler then calls a new
`drainActiveSessionsForShutdown({ reason })` in `session-reset-service.ts`
between the `gateway:shutdown`/`gateway:pre-restart` lifecycle hooks and
the subsystem teardown steps; the drain races a bounded 2 s total timeout
so a slow plugin cannot block SIGTERM/SIGINT, surfacing the timeout as a
`session-end-drain` warning on the shutdown result.
Extend `PluginHookSessionEndReason` with `"shutdown"` and `"restart"` so
plugins can distinguish a graceful close from a planned restart; the close
handler picks `restart` when `restartExpectedMs` is set and `shutdown`
otherwise. Update `emitGatewaySessionStartPluginHook` to also accept
`storePath`, `sessionFile`, and `agentId` so the shutdown drain can build
the same `session_end` payload shape the normal lifecycle path emits, and
update the existing call sites in `session-reset-service.ts` and
`server-methods/sessions.ts` to pass those fields through.
Tests:
- `src/gateway/active-sessions-shutdown-tracker.test.ts` (new) -- tracker
insert/forget/clear semantics, idempotent re-noting, empty-id guard,
snapshot isolation.
- `src/gateway/drain-active-sessions-for-shutdown.test.ts` (new) -- drain
fires `session_end` with the right reason for every tracked session,
skips sessions already finalized via reset/delete/compaction, and still
forgets sessions even when no `session_end` plugin is registered.
- `src/gateway/server-close.test.ts` -- four new cases covering the
shutdown/restart drain wiring, the bounded timeout warning, and the
drain-skipped-when-no-helper case.
Docs:
- `docs/plugins/hooks.md` documents the new `shutdown`/`restart` values
on `PluginHookSessionEndReason`.
- `docs/automation/hooks.md` documents the post-`gateway:shutdown`
`session_end` drain step and its bounded execution guarantee.
Fixes #57790.
|
||
|---|---|---|
| .. | ||
| reference | ||
| adding-capabilities.md | ||
| agent-tools.md | ||
| architecture-internals.md | ||
| architecture.md | ||
| building-extensions.md | ||
| building-plugins.md | ||
| bundles.md | ||
| cli-backend-plugins.md | ||
| codex-computer-use.md | ||
| codex-harness-reference.md | ||
| codex-harness-runtime.md | ||
| codex-harness.md | ||
| codex-native-plugins.md | ||
| community.md | ||
| compatibility.md | ||
| dependency-resolution.md | ||
| google-meet.md | ||
| hooks.md | ||
| install-overrides.md | ||
| manage-plugins.md | ||
| manifest.md | ||
| memory-lancedb.md | ||
| memory-wiki.md | ||
| message-presentation.md | ||
| oc-path.md | ||
| plugin-inventory.md | ||
| reference.md | ||
| sdk-agent-harness.md | ||
| sdk-channel-ingress.md | ||
| sdk-channel-message.md | ||
| sdk-channel-plugins.md | ||
| sdk-channel-turn.md | ||
| sdk-entrypoints.md | ||
| sdk-migration.md | ||
| sdk-overview.md | ||
| sdk-provider-plugins.md | ||
| sdk-runtime.md | ||
| sdk-setup.md | ||
| sdk-subpaths.md | ||
| sdk-testing.md | ||
| skill-workshop.md | ||
| voice-call.md | ||
| webhooks.md | ||
| zalouser.md | ||