Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -83,13 +83,13 @@ RUN --mount=type=cache,target=/root/.cache/uv,id=uv-${TARGETPLATFORM} \
fi; \
case "${UV_LOCK_STRATEGY}" in \
locked) \
uv sync --locked --no-editable --reinstall-package openviking --extra bot --extra gemini --extra opengauss \
uv sync --locked --no-editable --reinstall-package openviking --extra bot --extra gemini --extra opengauss --extra expiry \
;; \
auto) \
if ! uv lock --check; then \
uv lock; \
fi; \
uv sync --locked --no-editable --reinstall-package openviking --extra bot --extra gemini --extra opengauss \
uv sync --locked --no-editable --reinstall-package openviking --extra bot --extra gemini --extra opengauss --extra expiry \
;; \
*) \
echo "Unsupported UV_LOCK_STRATEGY: ${UV_LOCK_STRATEGY}" >&2; \
Expand Down
1 change: 1 addition & 0 deletions MANIFEST.in
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ include Cargo.lock
graft crates/ragfs
graft crates/ragfs-python
recursive-include openviking *.yaml
recursive-include openviking/scheduling/expiry *.lua
recursive-include openviking_gateway *.json

# sdist should be source-only: never ship runtime binaries from working tree
Expand Down
18 changes: 9 additions & 9 deletions docs/en/api/05-sessions.md
Original file line number Diff line number Diff line change
Expand Up @@ -48,15 +48,15 @@ Create a new session. Sessions are containers for conversations, storing message

`auto_commit_policy` fields (all optional; omitted fields fall back to the defaults when a policy is present):

| Field | Type | Default | Max | Description |
|-------|------|---------|-----|-------------|
| `pending_token_threshold` | int | 150000 | 1000000 | When uncommitted pending tokens exceed this value (strictly greater-than), an auto commit is triggered after a message write. |
| `message_count_threshold` | int | 100 | 1000 | When the uncommitted live message count exceeds this value (strictly greater-than), an auto commit is triggered after a message write. |
| `idle_timeout_seconds` | int | 86400 | 604800 | After this many idle seconds, a session with uncommitted content becomes eligible for the server-side idle scheduler. An idle-timeout commit archives the full backlog and ignores `keep_recent_count`. |
| `keep_recent_count` | int | 0 | 500 | Number of recent live messages to keep (not archived) on a threshold-triggered auto commit. Idle-timeout commits ignore this and commit everything. |
| `min_commit_interval_seconds` | int | 0 | 604800 | Minimum seconds between two automatic commits (throttle). |

All fields have a minimum of `0` and are clamped into `[0, max]`. Unknown keys are rejected with `InvalidArgumentError`. Idle commits also require `memory.session_auto_commit.enabled` on the server; setting `idle_timeout_seconds` alone does not start the scanner.
| Field | Type | Default | Min | Max | Description |
|-------|------|---------|-----|-----|-------------|
| `pending_token_threshold` | int | 150000 | 0 | 1000000 | When uncommitted pending tokens exceed this value (strictly greater-than), an auto commit is triggered after a message write. |
| `message_count_threshold` | int | 100 | 0 | 1000 | When the uncommitted live message count exceeds this value (strictly greater-than), an auto commit is triggered after a message write. |
| `idle_timeout_seconds` | int | 86400 | 0 (off) or 300 | 604800 | After this many idle seconds, a session with uncommitted content becomes eligible for the server-side idle scheduler. An idle-timeout commit archives the full backlog and ignores `keep_recent_count`. |
| `keep_recent_count` | int | 0 | 0 | 500 | Number of recent live messages to keep (not archived) on a threshold-triggered auto commit. Idle-timeout commits ignore this and commit everything. |
| `min_commit_interval_seconds` | int | 0 | 0 | 604800 | Minimum seconds between two automatic commits (throttle). |

New `idle_timeout_seconds` inputs must be `0` (off) or at least `300`; values above `604800` are clamped to that maximum. For stored-data compatibility, existing positive values below 300 continue to be read unchanged. Other fields have a minimum of `0` and are clamped to their ranges. Unknown keys are rejected with `InvalidArgumentError`. Idle commits also require `memory.session_auto_commit.enabled` on the server; setting `idle_timeout_seconds` alone does not start the scanner.

#### 3. Usage Examples

Expand Down
58 changes: 47 additions & 11 deletions docs/en/guides/01-configuration.md
Original file line number Diff line number Diff line change
Expand Up @@ -1760,6 +1760,7 @@ For memory-related settings, add a `memory` section in `ov.conf`:
"memory": {
"session_auto_commit": {
"enabled": false,
"idle_backend": "local",
"check_interval_seconds": 600.0,
"scan_rate_limit_files_per_second": 2.0
}
Expand All @@ -1770,6 +1771,7 @@ For memory-related settings, add a `memory` section in `ov.conf`:
| Parameter | Type | Description | Default |
|-----------|------|-------------|---------|
| `enabled` | bool | Master switch for automatic session commits. When enabled, newly created sessions without an explicit `auto_commit_policy` get a default policy, and the idle-timeout background scheduler is started. When disabled, neither happens | `false` |
| `idle_backend` | string | Idle-timeout discovery backend: `local` scans session metadata; `redis` uses distributed expiry scheduling | `local` |
| `check_interval_seconds` | float | Minimum interval between two idle scan rounds in seconds. Must be greater than `0` | `600.0` |
| `scan_rate_limit_files_per_second` | float | Maximum number of session `.meta.json` files read per second during an idle scan. Must be greater than `0`. Bounds background storage IO when the sessions tree is very large | `2.0` |

Expand All @@ -1780,22 +1782,56 @@ Notes:
- When `enabled=false`, sessions created without an explicit or `server.user_config_defaults.auto_commit_policy` policy keep auto commit disabled and return `auto_commit_policy: null`; `SessionAutoCommitScheduler` is not started.
- When `enabled=true`:
- Sessions without an explicit or deployment-default policy get the built-in policy below.
- `SessionAutoCommitScheduler` starts a scan round immediately, then waits at least `check_interval_seconds` before the next round. If a round already took longer than that interval, the next round starts immediately.
- Within a round, session `.meta.json` files are read serially at no more than `scan_rate_limit_files_per_second` to avoid IO spikes.
- It does not perform a dedicated startup recovery sweep; idle detection happens only on periodic scans.
- With `idle_backend="local"`, `SessionAutoCommitScheduler` starts a scan round immediately, then waits at least `check_interval_seconds` before the next round. Session `.meta.json` files are read serially at no more than `scan_rate_limit_files_per_second`.
- With `idle_backend="redis"`, the server enables expiry reporting, publishing, and callback consumption together using the top-level `expiry` configuration.
- Token- and message-count auto commit run inline after message writes, do not depend on the scheduler, but still require the session to carry an `auto_commit_policy`.

#### Distributed Expiry Configuration

All API, publisher, and callback instances that share expiry state must use the same stable `service_name`. It identifies the deployed document service, not an individual pod.

```json
{
"expiry": {
"service_name": "openviking-documents",
"publisher_separate_process": true,
"shard_count": 128,
"session_consumer_concurrency": 8,
"redis": {
"mode": "cluster",
"endpoints": ["redis://redis-proxy.example.com:6379"],
"username": "openviking",
"password_env": "OPENVIKING_EXPIRY_REDIS_PASSWORD"
}
}
}
```

| Parameter | Type | Description | Default |
|-----------|------|-------------|---------|
| `service_name` | string | Stable document service name shared by all instances using the same expiry data | `""` |
| `publisher_separate_process` | bool | Let `openviking-server` supervise publisher in a dedicated child process; when `false`, publisher runs in each API process | `true` |
| `shard_count` | int | Number of logical expiry shards; all instances sharing a namespace must use the same value, in the range `1..512` | `128` |
| `session_consumer_concurrency` | int | Concurrent Session expiry callbacks per API process; must be greater than `0` | `8` |
| `redis.mode` | string | Redis deployment mode: `standalone` or `cluster` | `standalone` |
| `redis.endpoints` | string array | Redis endpoints; a cluster may use one proxy endpoint | `[]` |
| `redis.username` | string | Redis ACL username | `""` |
| `redis.password_env` | string | Environment variable containing the Redis password; startup fails if it is not set | `""` |
| `redis.password` | string | Legacy plaintext password; prefer `password_env`; mutually exclusive with it | `""` |

`service_name` and Redis endpoints are required when Redis idle auto commit is enabled. Credentials must use the dedicated fields above and cannot be embedded in endpoint URIs. With the default `publisher_separate_process=true`, `openviking-server` starts one internal publisher before serving traffic, stops it during shutdown, and exits if that child fails unexpectedly. This publisher is not exposed as a public CLI command.

##### Per-session Auto Commit Policy

When a session carries an `auto_commit_policy`, any field you omit falls back to the built-in default below. Sessions without a stored policy keep auto commit disabled. Values are clamped into `[0, max]`, and unknown keys are rejected with `InvalidArgumentError`. See [Sessions API](../api/05-sessions.md#create-session) for how to set and view it.
When a session carries an `auto_commit_policy`, any field you omit falls back to the built-in default below. Sessions without a stored policy keep auto commit disabled. Except for the idle-timeout write minimum, values are clamped into `[0, max]`; unknown keys are rejected with `InvalidArgumentError`. See [Sessions API](../api/05-sessions.md#create-session) for how to set and view it.

| Field | Type | Default | Max | Description |
|-------|------|---------|-----|-------------|
| `pending_token_threshold` | int | 150000 | 1000000 | When uncommitted pending tokens exceed this value (strictly greater-than), an auto commit is triggered after a message write. |
| `message_count_threshold` | int | 100 | 1000 | When the uncommitted live message count exceeds this value (strictly greater-than), an auto commit is triggered after a message write. |
| `idle_timeout_seconds` | int | 86400 | 604800 | After this many idle seconds, a session with uncommitted content becomes eligible for the server-side idle scheduler. Idle-timeout commits archive the full backlog and ignore `keep_recent_count`. |
| `keep_recent_count` | int | 0 | 500 | Number of recent live messages to keep (not archived) on a threshold-triggered auto commit. Idle-timeout commits ignore this and commit everything. |
| `min_commit_interval_seconds` | int | 0 | 604800 | Minimum seconds between two automatic commits (throttle). |
| Field | Type | Default | Min | Max | Description |
|-------|------|---------|-----|-----|-------------|
| `pending_token_threshold` | int | 150000 | 0 | 1000000 | When uncommitted pending tokens exceed this value (strictly greater-than), an auto commit is triggered after a message write. |
| `message_count_threshold` | int | 100 | 0 | 1000 | When the uncommitted live message count exceeds this value (strictly greater-than), an auto commit is triggered after a message write. |
| `idle_timeout_seconds` | int | 86400 | 0 (off) or 300 | 604800 | New positive inputs have a five-minute minimum; existing stored positive values below 300 continue to be read unchanged. Idle-timeout commits archive the full backlog and ignore `keep_recent_count`. |
| `keep_recent_count` | int | 0 | 0 | 500 | Number of recent live messages to keep (not archived) on a threshold-triggered auto commit. Idle-timeout commits ignore this and commit everything. |
| `min_commit_interval_seconds` | int | 0 | 0 | 604800 | Minimum seconds between two automatic commits (throttle). |

Code entry: `openviking/session/auto_commit_policy.py:AutoCommitPolicy`.

Expand Down
18 changes: 9 additions & 9 deletions docs/zh/api/05-sessions.md
Original file line number Diff line number Diff line change
Expand Up @@ -48,15 +48,15 @@ Session API 按认证用户作用域访问会话,并返回 canonical user sess

`auto_commit_policy` 字段(均为可选;存在 policy 时,未传字段回退到默认值):

| 字段 | 类型 | 默认值 | 上限 | 说明 |
|------|------|--------|------|------|
| `pending_token_threshold` | int | 150000 | 1000000 | 当未提交的 pending token 超过该值(严格大于)时,会在消息写入后触发一次自动 commit。 |
| `message_count_threshold` | int | 100 | 1000 | 当未提交的 live message 数量超过该值(严格大于)时,会在消息写入后触发一次自动 commit。 |
| `idle_timeout_seconds` | int | 86400 | 604800 | 有未提交内容的 session 在空闲这么多秒后,进入服务端 idle scheduler 的处理范围。idle 触发的 commit 会归档全部积压消息,并忽略 `keep_recent_count`。 |
| `keep_recent_count` | int | 0 | 500 | 阈值触发的自动 commit 后保留(不归档)的最近 live message 数量。idle 超时触发的 commit 会忽略该值并归档所有消息。 |
| `min_commit_interval_seconds` | int | 0 | 604800 | 两次自动 commit 之间的最小间隔秒数(节流)。 |

所有字段最小值为 `0`,会被 clamp 到 `[0, 上限]`。未知字段会以 `InvalidArgumentError` 拒绝。idle 超时还要求服务端开启 `memory.session_auto_commit.enabled`;仅设置 `idle_timeout_seconds` 不会启动扫描器。
| 字段 | 类型 | 默认值 | 最小值 | 上限 | 说明 |
|------|------|--------|--------|------|------|
| `pending_token_threshold` | int | 150000 | 0 | 1000000 | 当未提交的 pending token 超过该值(严格大于)时,会在消息写入后触发一次自动 commit。 |
| `message_count_threshold` | int | 100 | 0 | 1000 | 当未提交的 live message 数量超过该值(严格大于)时,会在消息写入后触发一次自动 commit。 |
| `idle_timeout_seconds` | int | 86400 | 0(关闭)或 300 | 604800 | 有未提交内容的 session 在空闲这么多秒后,进入服务端 idle scheduler 的处理范围。idle 触发的 commit 会归档全部积压消息,并忽略 `keep_recent_count`。 |
| `keep_recent_count` | int | 0 | 0 | 500 | 阈值触发的自动 commit 后保留(不归档)的最近 live message 数量。idle 超时触发的 commit 会忽略该值并归档所有消息。 |
| `min_commit_interval_seconds` | int | 0 | 0 | 604800 | 两次自动 commit 之间的最小间隔秒数(节流)。 |

新传入的 `idle_timeout_seconds` 必须为 `0`(关闭)或不小于 `300`,超过 `604800` 时会被 clamp 到该上限;为兼容存量数据,已经保存的小于 300 的正值仍按原值读取。其他字段最小值为 `0`,并会被 clamp 到各自范围。未知字段会以 `InvalidArgumentError` 拒绝。idle 超时还要求服务端开启 `memory.session_auto_commit.enabled`;仅设置 `idle_timeout_seconds` 不会启动扫描器。

#### 3. 使用示例

Expand Down
Loading
Loading