Updated documentation to reflect storage refactor and route dispatcher changes.

2026-03-09 20:01:16 -04:00
parent 988cecbabb
commit 2da7f1fc0f
5 changed files with 9 additions and 7 deletions
+1 -1
@@ -50,7 +50,7 @@ owlbot:
| `host` | `"127.0.0.1"` | `OWLBOT_HOST` | `--host` | Address to bind the web server. Set to `"0.0.0.0"` to listen on all interfaces. |
| `port` | `8081` | `OWLBOT_PORT` | `--port` | Port for the web server. |
| `command_prefix` | `"!"` | `OWLBOT_COMMAND_PREFIX` | | Prefix character for chat commands (e.g., `!help`). |
| `handler_timeout` | `30.0` | `OWLBOT_HANDLER_TIMEOUT` | | Maximum seconds a handler can run before it is cancelled and its storage changes rolled back. |
| `handler_timeout` | `30.0` | `OWLBOT_HANDLER_TIMEOUT` | | Maximum seconds a handler can run before it is cancelled. |
| `storage_dir` | `"data"` | `OWLBOT_STORAGE_DIR` | `-s`, `--storage-dir` | Directory for per-module SQLite database files. Each module gets a `<module_name>.db` file here. Relative paths are resolved from the working directory. |
| `modules_dir` | `"modules"` | `OWLBOT_MODULES_DIR` | `-m`, `--modules` | Directory for user-written modules. Built-in modules are loaded from the package regardless of this setting. Relative paths are resolved from the working directory. |
| `pool_size` | `4` | `OWLBOT_POOL_SIZE` | | Maximum SQLite connections per module in the connection pool. Connections are created lazily as needed. |
+1 -1
@@ -14,7 +14,7 @@ Owlbot's core is a framework for building and running modules. If the included m
- **[Modular architecture](Modules)**: Each module is a single Python file or package. Add, remove, or disable modules independently.
- **[Event system](Modules-Events)**: React to chat messages, user joins/parts, stream start/stop, name changes, and moderation events.
- **[Command system](Modules-Commands)**: Register chat commands with permissions, cooldowns, and aliases.
- **[Per-module storage](Modules-Storage)**: Each module gets its own SQLite database with automatic transaction management.
- **[Per-module storage](Modules-Storage)**: Each module gets its own SQLite database with automatic connection management.
- **[YAML configuration](Modules-Config)**: One config file for the bot and all modules.
- **[HTTP routes](Modules-Routes)**: Modules can serve web pages, APIs, and webhooks.
+1 -1
@@ -25,7 +25,7 @@ If the module defines a function decorated with `@on_setup`, it is called with a
`@on_setup` is optional. Modules that only use decorator-based handlers and don't need storage or config can skip it entirely.
If `@on_setup` raises an exception, the module is completely rolled back: any storage changes are undone, all registered handlers, commands, and routes are removed, and the module is unloaded. Other modules are not affected and continue loading normally.
If `@on_setup` raises an exception, the module is fully cleaned up: all registered handlers, commands, and routes are removed, storage is closed, and the module is unloaded. Other modules are not affected and continue loading normally. Any storage operations that already completed (such as `CREATE TABLE`) will have been committed independently.
## 4. Runtime
+1 -1
@@ -155,7 +155,7 @@ async def incoming_webhook(ctx: RouteContext) -> None:
## Error Handling
If a route handler raises an exception, the error is logged, any storage changes are rolled back, and the client receives an empty `500` response. The same applies if the handler exceeds the configured `handler_timeout` (default 30 seconds); it is cancelled and the client receives a `500`.
If a route handler raises an exception, the error is logged and the client receives an empty `500` response. The same applies if the handler exceeds the configured `handler_timeout` (default 30 seconds); it is cancelled and the client receives a `500`.
## URL Building
+5 -3
@@ -1,6 +1,6 @@
# Modules - Storage
Each module gets its own SQLite database file, isolated from other modules. Storage is accessed through `ctx.storage`. The API is async and handles connection pooling, WAL mode, and transaction management automatically. Queries are written in standard SQL.
Each module gets its own SQLite database file, isolated from other modules. Storage is accessed through `ctx.storage`. The API is async and handles connection pooling and WAL mode automatically. Each operation auto-commits independently; use `transaction()` when you need atomicity across multiple operations. Queries are written in standard SQL.
## Schema Setup
@@ -123,9 +123,9 @@ Never use f-strings or string formatting for SQL parameters. This prevents SQL i
## Transactions
Each handler invocation runs inside a single transaction. All storage operations within the handler share that transaction. If the handler completes normally, everything is committed together. If it raises an exception, everything is rolled back. No manual commit or rollback is needed.
Each storage operation auto-commits independently. A call to `execute()`, `fetch_one()`, or any other query method acquires a connection, commits on success (or rolls back on failure), and releases the connection immediately. No connection is held between calls.
For finer-grained control within a handler, use the `transaction()` context manager to group operations that should succeed or fail together independently of the rest of the handler:
When multiple operations must succeed or fail together, use the `transaction()` context manager:
```python
async with ctx.storage.transaction():
@@ -134,6 +134,8 @@ async with ctx.storage.transaction():
# Both committed together on success, or both rolled back if either fails
```
Outside of a `transaction()` block, each operation is its own atomic unit. A handler that calls `execute()` three times makes three independent commits.
## Connection Pooling
Storage uses a connection pool with lazy creation. Connections are created on-demand up to `pool_size` (default 4, configurable in `config.yaml` under `owlbot.pool_size`). WAL (Write-Ahead Logging) mode is enabled on all connections so concurrent readers and a single writer don't block each other.