perf: hourly update check only with a browser open; opt-in retention, incremental auto-vacuum and Compact
- update-scheduler: default interval 1 h (DASHBOARD_UPDATE_CHECK_INTERVAL_MS and its 60 s floor kept); a scheduled tick with no /ws client is skipped, and the next browser to connect gets one catch-up check when the last one is stale (websocket.js onConnection). Manual check unchanged. - db-retention.js: shared session purge (used by POST /api/settings/cleanup too), opt-in AGENTHUB_RETENTION_DAYS applied by the hourly maintenance in 25-session transactions with yields (max 5000/run), bounded incremental_vacuum when the freelist is large, and a manual Compact (VACUUM in a worker, converting to auto_vacuum=INCREMENTAL). - db.js: new databases are INCREMENTAL; an existing one up to 32 MB is converted at startup. - GET/PUT /api/settings/retention, POST /api/settings/compact (confirm: true); Settings → Data → Session cleanup gets the Automatic cleanup control and Compact now (en + vi).
This commit is contained in:
@@ -11,6 +11,9 @@
|
||||
* - GET /api/settings/backup (Settings)
|
||||
* - PUT /api/settings/backup (Settings)
|
||||
* - POST /api/settings/backup/run (Settings)
|
||||
* - GET /api/settings/retention (Settings)
|
||||
* - PUT /api/settings/retention (Settings)
|
||||
* - POST /api/settings/compact (Settings)
|
||||
* - GET /api/workflows/runs (Workflows)
|
||||
* - GET /api/workflows/runs/{runId} (Workflows)
|
||||
* - GET /api/remote-sources (Remote Sources)
|
||||
@@ -1225,6 +1228,117 @@ const paths = {
|
||||
},
|
||||
},
|
||||
|
||||
"/api/settings/retention": (() => {
|
||||
const state = {
|
||||
description: "Automatic retention setting, database space and the last Compact",
|
||||
content: {
|
||||
"application/json": {
|
||||
schema: {
|
||||
type: "object",
|
||||
required: ["days", "max_days", "env_owned", "compacting"],
|
||||
properties: {
|
||||
days: {
|
||||
type: "integer",
|
||||
minimum: 0,
|
||||
maximum: 3650,
|
||||
description:
|
||||
"Finished sessions older than this many days are purged by the hourly maintenance; 0 = off (the default)",
|
||||
},
|
||||
max_days: { type: "integer" },
|
||||
env_owned: { type: "object", properties: { days: { type: "boolean" } } },
|
||||
last_run: {
|
||||
type: "object",
|
||||
nullable: true,
|
||||
description:
|
||||
"This process's last hourly maintenance: {at, retention?: {purged_sessions, purged_events, purged_agents, error?}, reclaim: {reclaimed_pages, error?}, ms}",
|
||||
},
|
||||
space: {
|
||||
type: "object",
|
||||
nullable: true,
|
||||
properties: {
|
||||
auto_vacuum: { type: "string", enum: ["none", "full", "incremental"] },
|
||||
page_size: { type: "integer" },
|
||||
page_count: { type: "integer" },
|
||||
freelist_pages: { type: "integer" },
|
||||
free_bytes: { type: "integer" },
|
||||
},
|
||||
},
|
||||
db_size: { type: "integer", description: "Database file size in bytes" },
|
||||
compacting: { type: "boolean" },
|
||||
last_compact: {
|
||||
type: "object",
|
||||
nullable: true,
|
||||
description:
|
||||
"This process's last Compact: {at, ok, size_before?, size_after?, ms?, error?}",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
};
|
||||
return {
|
||||
get: {
|
||||
tags: ["Settings"],
|
||||
summary: "Automatic retention and database space",
|
||||
operationId: "getRetention",
|
||||
responses: { 200: state },
|
||||
},
|
||||
put: {
|
||||
tags: ["Settings"],
|
||||
summary: "Set the automatic retention",
|
||||
description:
|
||||
"Persisted to the settings file as AGENTHUB_RETENTION_DAYS. 0 turns it off. Same-origin only; in server mode an admin's.",
|
||||
operationId: "setRetention",
|
||||
requestBody: {
|
||||
required: true,
|
||||
content: {
|
||||
"application/json": {
|
||||
schema: {
|
||||
type: "object",
|
||||
required: ["days"],
|
||||
properties: { days: { type: "integer", minimum: 0, maximum: 3650 } },
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
responses: {
|
||||
200: { ...state, description: "The new state" },
|
||||
400: { description: "INVALID_INPUT: days is not a whole number from 0 to 3650" },
|
||||
403: { description: "EBADORIGIN: another site asked" },
|
||||
409: { description: "EENVOWNED: the environment set AGENTHUB_RETENTION_DAYS" },
|
||||
500: { description: "ESAVE: the settings file could not be written" },
|
||||
},
|
||||
},
|
||||
};
|
||||
})(),
|
||||
|
||||
"/api/settings/compact": {
|
||||
post: {
|
||||
tags: ["Settings"],
|
||||
summary: "Compact the database now (full VACUUM)",
|
||||
description:
|
||||
"Rewrites the database in a worker thread, switching it to incremental auto_vacuum, then truncates the WAL. Hook writes wait while it runs. Answers at once; poll GET /api/settings/retention while `compacting`. Same-origin only; in server mode an admin's.",
|
||||
operationId: "compactDatabase",
|
||||
requestBody: {
|
||||
required: true,
|
||||
content: {
|
||||
"application/json": {
|
||||
schema: {
|
||||
type: "object",
|
||||
required: ["confirm"],
|
||||
properties: { confirm: { type: "boolean", enum: [true] } },
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
responses: {
|
||||
202: { description: "Started (or already running); the retention state" },
|
||||
400: { description: "ECONFIRM: confirm: true is missing" },
|
||||
403: { description: "EBADORIGIN: another site asked" },
|
||||
},
|
||||
},
|
||||
},
|
||||
|
||||
"/api/settings/codex-hooks": (() => {
|
||||
const status = {
|
||||
description: "Where AgentHub's Codex hooks stand",
|
||||
|
||||
Reference in New Issue
Block a user