Skip to content

Commit 68cd5e7

Browse files
committed
docs: correct catalog capabilities and worker requirements
1 parent 5a786cf commit 68cd5e7

9 files changed

Lines changed: 72 additions & 22 deletions

File tree

‎docs/api/index.md‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@ added incrementally.
3232
| [Auth & Secrets](auth.md) | `AuthContext`, `CallContext`, bearer/JWT authenticators, secret protocol | HTTP: `[http]`; JWT: `[oauth]` |
3333
| [Observability](observability.md) | OpenTelemetry tracing, worker logging configuration | `[otel]` for tracing |
3434
| [HTTP](http.md) | Worker page, blob storage, request-size middleware | `pip install vgi-python[http]` |
35-
| [Transactor](transactor.md) | `TransactorClient`, `TransactorProtocol` | `pip install vgi-python[transactor]` |
35+
| [Transactor](transactor.md) | `TransactorClient`, `TransactorProtocol` | `[transactor]` extra and a [compatible engine build](transactor.md#runtime-requirements) |
3636
| [Exceptions](exceptions.md) | VGI exception types | — |
3737

3838
## Import Convention

‎docs/api/transactor.md‎

Lines changed: 22 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,27 @@
66
[function patterns](../how-to/function-patterns.md) if you're new to VGI.
77

88
The transactor is a long-lived subprocess that gives worker functions transactional access to a
9-
database, mediated by `TransactorClient` over the `TransactorProtocol`. Requires
10-
`pip install vgi-python[transactor]`.
9+
database, mediated by `TransactorClient` over the `TransactorProtocol`.
10+
11+
## Runtime requirements
12+
13+
The bundled transactor requires both:
14+
15+
- `pip install 'vgi-python[transactor]'` for its Python dependencies.
16+
- A VGI fork build of `duckdb-python` providing `DuckDBPyConnection.subcursor()`,
17+
which lets reads share an open write transaction. This extension has not yet
18+
been merged into Haybarn or upstream DuckDB; installing the extra alone is
19+
insufficient.
20+
21+
Engine resolution prefers `haybarn` when installed, then falls back to `duckdb`.
22+
Use an environment where the selected engine provides `subcursor()`; installing
23+
a compatible `duckdb` build alongside an incompatible `haybarn` installation
24+
does not override that preference.
25+
26+
These requirements apply to the bundled transactor. Workers can implement
27+
[table writes](../catalog-interface.md#table-writes-and-indexes) against their own
28+
backing data sources without using it.
29+
30+
## API
1131

1232
::: vgi.transactor

‎docs/authentication.md‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ the principal in the `AuthContext` available to functions.
2424
| Variable | Description |
2525
|----------|-------------|
2626
| `VGI_BEARER_TOKENS` | Comma-separated `token=principal` pairs for static bearer auth |
27-
| `VGI_JWT_ISSUER` | JWT issuer URL (requires `vgi[oauth]` extra) |
27+
| `VGI_JWT_ISSUER` | JWT issuer URL (requires `vgi-python[oauth]` extra) |
2828
| `VGI_JWT_AUDIENCE` | JWT audience string, comma-separated for multiple audiences (required when `VGI_JWT_ISSUER` is set) |
2929
| `VGI_JWT_JWKS_URI` | JWKS endpoint URL (auto-discovered from issuer if omitted) |
3030
| `VGI_OAUTH_RESOURCE` | OAuth resource URL for RFC 9728 metadata |

‎docs/catalog-interface.md‎

Lines changed: 28 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -944,16 +944,41 @@ if __name__ == "__main__":
944944

945945
---
946946

947-
## API Limitations
947+
## Catalog capabilities and limitations { #api-limitations }
948948

949949
The current CatalogInterface has the following limitations:
950950

951951
- **Functions**: Cannot be created or dropped via catalog methods (use `Worker.functions`)
952952
- **Tags**: Cannot be updated after object creation
953953
- **Schema metadata**: Comments and tags cannot be updated on schemas
954954
- **Constraints**: Only NOT NULL can be added/dropped (no ALTER for UNIQUE/CHECK)
955-
- **Indexes**: Not supported
956-
- **INSERT/UPDATE/DELETE**: Not yet implemented (metadata only)
955+
956+
### Table writes and indexes
957+
958+
`INSERT`, `UPDATE`, and `DELETE` are supported when the catalog supplies a write
959+
function for the operation. For declarative catalogs, configure the
960+
[`Table`][vgi.catalog.descriptors.Table] descriptor:
961+
962+
| Operation | Descriptor field | Requirement |
963+
|-----------|------------------|-------------|
964+
| `INSERT` | `insert_function` | A `TableInOutGenerator` that accepts rows to insert |
965+
| `UPDATE` | `update_function` | A write function and a scan `function` that provides row IDs |
966+
| `DELETE` | `delete_function` | A write function and a scan `function` that provides row IDs |
967+
968+
Each field defaults to `None`, which leaves that operation unsupported. Custom
969+
catalogs implement `table_insert_function_get()`, `table_update_function_get()`,
970+
or `table_delete_function_get()` to return the corresponding `ScanFunctionResult`.
971+
The worker's write functions implement the changes to the backing data source;
972+
declaring a table alone does not make it writable.
973+
974+
`ReadOnlyCatalogInterface` rejects catalog DDL, but can expose these write functions
975+
on declarative tables. Table writes do not require the bundled
976+
[transactor](api/transactor.md); that is an optional database-access service with
977+
additional engine requirements.
978+
979+
Index metadata can be declared with [`Index`][vgi.catalog.descriptors.Index]. Custom
980+
catalogs can implement `index_get()`, `index_create()`, and `index_drop()`; support
981+
depends on the catalog implementation and backing data source.
957982

958983
---
959984

‎docs/cli.md‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -545,7 +545,7 @@ vgi-fixture-worker --log-format json
545545
| `VGI_QUIET=1` | Suppress the interactive-terminal startup warning (same as `--quiet`) |
546546
| `VGI_FILTER_DEBUG=1` | Enable filter pushdown debug logging |
547547
| `VGI_BEARER_TOKENS` | Comma-separated `token=principal` pairs for static bearer auth (HTTP only) |
548-
| `VGI_JWT_ISSUER` | JWT issuer URL for JWT/JWKS auth (requires `vgi[oauth]` extra) |
548+
| `VGI_JWT_ISSUER` | JWT issuer URL for JWT/JWKS auth (requires `vgi-python[oauth]` extra) |
549549
| `VGI_JWT_AUDIENCE` | JWT audience string, comma-separated for multiple audiences (required when `VGI_JWT_ISSUER` is set) |
550550
| `VGI_JWT_JWKS_URI` | JWKS endpoint URL (auto-discovered if omitted) |
551551
| `VGI_OAUTH_RESOURCE` | OAuth resource URL for RFC 9728 metadata |

‎docs/how-to/function-patterns.md‎

Lines changed: 9 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
---
2-
description: "How to write each of the four VGI function patterns: scalar, table, table-in-out, and aggregate — with a complete runnable worker for each."
2+
description: "How to write each of the five VGI function patterns: scalar, table, table-in-out, aggregate, and buffering — with a complete runnable worker for each."
33
---
44

55
# Function patterns
@@ -178,11 +178,14 @@ ATTACH 'aggregates' (TYPE vgi, LOCATION 'uv run sum_worker.py');
178178
SELECT category, aggregates.vgi_sum(value) FROM t GROUP BY category;
179179
```
180180

181-
??? info "State must be an `ArrowSerializableDataclass`"
182-
Table generators and aggregates keep state between calls. Because that state is serialized
183-
across parallel workers (aggregates) and HTTP round-trips, the framework requires it to extend
184-
`ArrowSerializableDataclass`. Annotate fields with `ArrowType(...)` so the wire type is
185-
explicit.
181+
??? info "State must be serializable"
182+
Table generators and aggregates keep state between calls. A state type must provide
183+
`serialize_to_bytes()` and `deserialize_from_bytes()` so the framework can carry it across
184+
HTTP round-trips or persist it between aggregate calls. `ArrowSerializableDataclass`
185+
implements these methods for you and is the usual starting point. Custom state types can
186+
implement the same [`StreamStateCodec`][vgi.function.StreamStateCodec] contract without
187+
inheriting from `ArrowSerializableDataclass`. See
188+
[State Class](../aggregate-functions.md#state-class) for both approaches.
186189

187190
## Buffering
188191

‎docs/how-to/state-storage.md‎

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -22,9 +22,11 @@ function that coordinates partial results across workers.
2222

2323
## Two kinds of "state" — don't confuse them
2424

25-
- **Generator cursor state** — the small `ArrowSerializableDataclass` a table generator keeps
26-
*within one scan* (see [streaming with state](function-patterns.md#streaming-with-state)). It
27-
lives in the worker for the duration of the call.
25+
- **Generator cursor state** — the small serializable object a table generator keeps
26+
*within one scan* (see [streaming with state](function-patterns.md#streaming-with-state)).
27+
Over HTTP, the framework serializes it between requests. `ArrowSerializableDataclass`
28+
supplies the serialization methods; custom types can implement
29+
[`StreamStateCodec`][vgi.function.StreamStateCodec] instead.
2830
- **Shared storage** (this page) — state that must outlive a single call or be shared across
2931
**separate worker processes**, e.g. combining partial aggregate results. This is backed by a
3032
pluggable store.

‎docs/shared-storage.md‎

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ variable.
1010
| Backend | Value | Use Case | Dependencies |
1111
|---------|-------|----------|-------------|
1212
| SQLite | `sqlite` (default) | Local / subprocess transport | None (stdlib) |
13-
| Azure SQL | `azure-sql` | Azure cloud deployments | `vgi[azure]` |
13+
| Azure SQL | `azure-sql` | Azure cloud deployments | `vgi-python[azure]` |
1414
| Cloudflare DO | `cloudflare-do` | Edge / multi-cloud deployments | None (stdlib) |
1515

1616
## SQLite (Default)
@@ -36,7 +36,7 @@ workers run on separate hosts.
3636
1. Install the Azure extra:
3737

3838
```bash
39-
pip install vgi[azure]
39+
pip install 'vgi-python[azure]'
4040
```
4141

4242
2. Create an Azure SQL Database (Serverless recommended for cost):

‎vgi/_duckdb.py‎

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -7,8 +7,8 @@
77
fixtures) resolves it through this module, which prefers Query Farm's
88
``haybarn`` distribution when installed and falls back to stock ``duckdb``.
99
10-
Install one via the extras: ``pip install vgi[haybarn]`` (preferred) or
11-
``pip install vgi[duckdb]``.
10+
Install one via the extras: ``pip install 'vgi-python[haybarn]'`` (preferred) or
11+
``pip install 'vgi-python[duckdb]'``.
1212
"""
1313

1414
from __future__ import annotations
@@ -50,7 +50,7 @@ def engine_module() -> ModuleType:
5050
else:
5151
raise ImportError(
5252
"No DuckDB-compatible engine is installed. Install 'haybarn' (preferred) "
53-
"or 'duckdb', e.g. `pip install vgi[haybarn]` or `pip install vgi[duckdb]`."
53+
"or 'duckdb', e.g. `pip install 'vgi-python[haybarn]'` or `pip install 'vgi-python[duckdb]'`."
5454
)
5555
return _engine
5656

0 commit comments

Comments
 (0)