ai-database 2.1.3 → 2.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +35 -1
- package/README.md +880 -669
- package/dist/actions.d.ts +2 -2
- package/dist/actions.d.ts.map +1 -1
- package/dist/actions.js +1 -1
- package/dist/actions.js.map +1 -1
- package/dist/ai-promise-db.d.ts +49 -23
- package/dist/ai-promise-db.d.ts.map +1 -1
- package/dist/ai-promise-db.js +91 -63
- package/dist/ai-promise-db.js.map +1 -1
- package/dist/authorization.d.ts.map +1 -1
- package/dist/authorization.js +38 -30
- package/dist/authorization.js.map +1 -1
- package/dist/cascade-orchestrator.d.ts +404 -0
- package/dist/cascade-orchestrator.d.ts.map +1 -0
- package/dist/cascade-orchestrator.js +828 -0
- package/dist/cascade-orchestrator.js.map +1 -0
- package/dist/cascade-write-strategy.d.ts +584 -0
- package/dist/cascade-write-strategy.d.ts.map +1 -0
- package/dist/cascade-write-strategy.js +590 -0
- package/dist/cascade-write-strategy.js.map +1 -0
- package/dist/ch-adapter.d.ts +358 -0
- package/dist/ch-adapter.d.ts.map +1 -0
- package/dist/ch-adapter.js +929 -0
- package/dist/ch-adapter.js.map +1 -0
- package/dist/client/index.d.ts +42 -0
- package/dist/client/index.d.ts.map +1 -0
- package/dist/client/index.js +43 -0
- package/dist/client/index.js.map +1 -0
- package/dist/client.d.ts +266 -0
- package/dist/client.d.ts.map +1 -0
- package/dist/client.js +81 -0
- package/dist/client.js.map +1 -0
- package/dist/constants.d.ts +64 -1
- package/dist/constants.d.ts.map +1 -1
- package/dist/constants.js +52 -2
- package/dist/constants.js.map +1 -1
- package/dist/dataloader.d.ts +99 -0
- package/dist/dataloader.d.ts.map +1 -0
- package/dist/dataloader.js +225 -0
- package/dist/dataloader.js.map +1 -0
- package/dist/db-provider-port.d.ts +501 -0
- package/dist/db-provider-port.d.ts.map +1 -0
- package/dist/db-provider-port.js +113 -0
- package/dist/db-provider-port.js.map +1 -0
- package/dist/digital-objects-provider.d.ts +49 -0
- package/dist/digital-objects-provider.d.ts.map +1 -0
- package/dist/digital-objects-provider.js +55 -0
- package/dist/digital-objects-provider.js.map +1 -0
- package/dist/do-sqlite-adapter.d.ts +402 -0
- package/dist/do-sqlite-adapter.d.ts.map +1 -0
- package/dist/do-sqlite-adapter.js +745 -0
- package/dist/do-sqlite-adapter.js.map +1 -0
- package/dist/docs-rels/custom-types.d.ts +134 -0
- package/dist/docs-rels/custom-types.d.ts.map +1 -0
- package/dist/docs-rels/custom-types.js +70 -0
- package/dist/docs-rels/custom-types.js.map +1 -0
- package/dist/docs-rels/index.d.ts +16 -0
- package/dist/docs-rels/index.d.ts.map +1 -0
- package/dist/docs-rels/index.js +16 -0
- package/dist/docs-rels/index.js.map +1 -0
- package/dist/docs-rels/migrations/index.d.ts +30 -0
- package/dist/docs-rels/migrations/index.d.ts.map +1 -0
- package/dist/docs-rels/migrations/index.js +128 -0
- package/dist/docs-rels/migrations/index.js.map +1 -0
- package/dist/docs-rels/schema.d.ts +2961 -0
- package/dist/docs-rels/schema.d.ts.map +1 -0
- package/dist/docs-rels/schema.js +244 -0
- package/dist/docs-rels/schema.js.map +1 -0
- package/dist/durable-clickhouse.d.ts.map +1 -1
- package/dist/durable-clickhouse.js +16 -13
- package/dist/durable-clickhouse.js.map +1 -1
- package/dist/durable-promise.d.ts.map +1 -1
- package/dist/durable-promise.js +34 -15
- package/dist/durable-promise.js.map +1 -1
- package/dist/errors.d.ts +127 -0
- package/dist/errors.d.ts.map +1 -0
- package/dist/errors.js +210 -0
- package/dist/errors.js.map +1 -0
- package/dist/eventbridge.d.ts +117 -0
- package/dist/eventbridge.d.ts.map +1 -0
- package/dist/eventbridge.js +238 -0
- package/dist/eventbridge.js.map +1 -0
- package/dist/events.d.ts +2 -2
- package/dist/events.d.ts.map +1 -1
- package/dist/events.js +1 -1
- package/dist/events.js.map +1 -1
- package/dist/execution-queue.d.ts.map +1 -1
- package/dist/execution-queue.js +4 -5
- package/dist/execution-queue.js.map +1 -1
- package/dist/index.d.ts +35 -8
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +106 -6
- package/dist/index.js.map +1 -1
- package/dist/linguistic.d.ts +3 -108
- package/dist/linguistic.d.ts.map +1 -1
- package/dist/linguistic.js +3 -372
- package/dist/linguistic.js.map +1 -1
- package/dist/logger.d.ts +132 -0
- package/dist/logger.d.ts.map +1 -0
- package/dist/logger.js +137 -0
- package/dist/logger.js.map +1 -0
- package/dist/memory-provider.d.ts +128 -0
- package/dist/memory-provider.d.ts.map +1 -1
- package/dist/memory-provider.js +592 -257
- package/dist/memory-provider.js.map +1 -1
- package/dist/pg-adapter.d.ts +424 -0
- package/dist/pg-adapter.d.ts.map +1 -0
- package/dist/pg-adapter.js +921 -0
- package/dist/pg-adapter.js.map +1 -0
- package/dist/pipelines-iceberg-emitter.d.ts +327 -0
- package/dist/pipelines-iceberg-emitter.d.ts.map +1 -0
- package/dist/pipelines-iceberg-emitter.js +351 -0
- package/dist/pipelines-iceberg-emitter.js.map +1 -0
- package/dist/provider-capabilities.d.ts +146 -0
- package/dist/provider-capabilities.d.ts.map +1 -0
- package/dist/provider-capabilities.js +214 -0
- package/dist/provider-capabilities.js.map +1 -0
- package/dist/rdb-provider-adapter.d.ts +195 -0
- package/dist/rdb-provider-adapter.d.ts.map +1 -0
- package/dist/rdb-provider-adapter.js +291 -0
- package/dist/rdb-provider-adapter.js.map +1 -0
- package/dist/schema/cascade.d.ts +48 -17
- package/dist/schema/cascade.d.ts.map +1 -1
- package/dist/schema/cascade.js +477 -278
- package/dist/schema/cascade.js.map +1 -1
- package/dist/schema/definition-caches.d.ts +24 -0
- package/dist/schema/definition-caches.d.ts.map +1 -0
- package/dist/schema/definition-caches.js +26 -0
- package/dist/schema/definition-caches.js.map +1 -0
- package/dist/schema/dependency-graph.d.ts +21 -109
- package/dist/schema/dependency-graph.d.ts.map +1 -1
- package/dist/schema/dependency-graph.js +25 -333
- package/dist/schema/dependency-graph.js.map +1 -1
- package/dist/schema/diff.d.ts +103 -0
- package/dist/schema/diff.d.ts.map +1 -0
- package/dist/schema/diff.js +329 -0
- package/dist/schema/diff.js.map +1 -0
- package/dist/schema/entity-operations.d.ts +99 -0
- package/dist/schema/entity-operations.d.ts.map +1 -0
- package/dist/schema/entity-operations.js +818 -0
- package/dist/schema/entity-operations.js.map +1 -0
- package/dist/schema/index.d.ts +28 -34
- package/dist/schema/index.d.ts.map +1 -1
- package/dist/schema/index.js +454 -521
- package/dist/schema/index.js.map +1 -1
- package/dist/schema/migration.d.ts +205 -0
- package/dist/schema/migration.d.ts.map +1 -0
- package/dist/schema/migration.js +327 -0
- package/dist/schema/migration.js.map +1 -0
- package/dist/schema/nl-query-generator.d.ts +68 -0
- package/dist/schema/nl-query-generator.d.ts.map +1 -0
- package/dist/schema/nl-query-generator.js +362 -0
- package/dist/schema/nl-query-generator.js.map +1 -0
- package/dist/schema/nl-query.d.ts +65 -0
- package/dist/schema/nl-query.d.ts.map +1 -0
- package/dist/schema/nl-query.js +178 -0
- package/dist/schema/nl-query.js.map +1 -0
- package/dist/schema/parse.d.ts.map +1 -1
- package/dist/schema/parse.js +144 -89
- package/dist/schema/parse.js.map +1 -1
- package/dist/schema/provider.d.ts +37 -0
- package/dist/schema/provider.d.ts.map +1 -1
- package/dist/schema/provider.js +15 -7
- package/dist/schema/provider.js.map +1 -1
- package/dist/schema/resolve.d.ts +46 -5
- package/dist/schema/resolve.d.ts.map +1 -1
- package/dist/schema/resolve.js +237 -95
- package/dist/schema/resolve.js.map +1 -1
- package/dist/schema/search-utils.d.ts +76 -0
- package/dist/schema/search-utils.d.ts.map +1 -0
- package/dist/schema/search-utils.js +86 -0
- package/dist/schema/search-utils.js.map +1 -0
- package/dist/schema/seed.d.ts +53 -0
- package/dist/schema/seed.d.ts.map +1 -0
- package/dist/schema/seed.js +94 -0
- package/dist/schema/seed.js.map +1 -0
- package/dist/schema/semantic.d.ts +10 -0
- package/dist/schema/semantic.d.ts.map +1 -1
- package/dist/schema/semantic.js +192 -86
- package/dist/schema/semantic.js.map +1 -1
- package/dist/schema/sub-apis.d.ts +52 -0
- package/dist/schema/sub-apis.d.ts.map +1 -0
- package/dist/schema/sub-apis.js +216 -0
- package/dist/schema/sub-apis.js.map +1 -0
- package/dist/schema/system-entities.d.ts +42 -0
- package/dist/schema/system-entities.d.ts.map +1 -0
- package/dist/schema/system-entities.js +101 -0
- package/dist/schema/system-entities.js.map +1 -0
- package/dist/schema/types.d.ts +91 -9
- package/dist/schema/types.d.ts.map +1 -1
- package/dist/schema/union-fallback.d.ts.map +1 -1
- package/dist/schema/union-fallback.js +21 -15
- package/dist/schema/union-fallback.js.map +1 -1
- package/dist/schema/value-generators/ai.d.ts +54 -0
- package/dist/schema/value-generators/ai.d.ts.map +1 -0
- package/dist/schema/value-generators/ai.js +136 -0
- package/dist/schema/value-generators/ai.js.map +1 -0
- package/dist/schema/value-generators/index.d.ts +126 -0
- package/dist/schema/value-generators/index.d.ts.map +1 -0
- package/dist/schema/value-generators/index.js +219 -0
- package/dist/schema/value-generators/index.js.map +1 -0
- package/dist/schema/value-generators/placeholder.d.ts +52 -0
- package/dist/schema/value-generators/placeholder.d.ts.map +1 -0
- package/dist/schema/value-generators/placeholder.js +328 -0
- package/dist/schema/value-generators/placeholder.js.map +1 -0
- package/dist/schema/value-generators/types.d.ts +116 -0
- package/dist/schema/value-generators/types.d.ts.map +1 -0
- package/dist/schema/value-generators/types.js +11 -0
- package/dist/schema/value-generators/types.js.map +1 -0
- package/dist/schema/version.d.ts +111 -0
- package/dist/schema/version.d.ts.map +1 -0
- package/dist/schema/version.js +190 -0
- package/dist/schema/version.js.map +1 -0
- package/dist/schema.d.ts +1095 -24
- package/dist/schema.d.ts.map +1 -1
- package/dist/schema.js +2852 -40
- package/dist/schema.js.map +1 -1
- package/dist/semantic-vectors.d.ts +39 -0
- package/dist/semantic-vectors.d.ts.map +1 -0
- package/dist/semantic-vectors.js +334 -0
- package/dist/semantic-vectors.js.map +1 -0
- package/dist/semantic.d.ts +29 -1
- package/dist/semantic.d.ts.map +1 -1
- package/dist/semantic.js +26 -16
- package/dist/semantic.js.map +1 -1
- package/dist/telemetry.d.ts +128 -0
- package/dist/telemetry.d.ts.map +1 -0
- package/dist/telemetry.js +305 -0
- package/dist/telemetry.js.map +1 -0
- package/dist/tests.d.ts.map +1 -1
- package/dist/tests.js +30 -22
- package/dist/tests.js.map +1 -1
- package/dist/type-guards.d.ts +50 -5
- package/dist/type-guards.d.ts.map +1 -1
- package/dist/type-guards.js +87 -16
- package/dist/type-guards.js.map +1 -1
- package/dist/types.d.ts +33 -245
- package/dist/types.d.ts.map +1 -1
- package/dist/types.js +62 -72
- package/dist/types.js.map +1 -1
- package/dist/validation.d.ts +2 -5
- package/dist/validation.d.ts.map +1 -1
- package/dist/validation.js +65 -93
- package/dist/validation.js.map +1 -1
- package/dist/worker/db-provider.d.ts +168 -0
- package/dist/worker/db-provider.d.ts.map +1 -0
- package/dist/worker/db-provider.js +277 -0
- package/dist/worker/db-provider.js.map +1 -0
- package/dist/worker/index.d.ts +35 -0
- package/dist/worker/index.d.ts.map +1 -0
- package/dist/worker/index.js +37 -0
- package/dist/worker/index.js.map +1 -0
- package/dist/worker.d.ts +779 -0
- package/dist/worker.d.ts.map +1 -0
- package/dist/worker.js +2786 -0
- package/dist/worker.js.map +1 -0
- package/package.json +46 -16
- package/src/docs-rels/migrations/0001-init.sql +125 -0
- package/LICENSE +0 -21
|
@@ -0,0 +1,590 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Cascade Write Strategy — sharded parallel writes for cascade generation
|
|
3
|
+
*
|
|
4
|
+
* Phase 2 entry point of the cascade epic per
|
|
5
|
+
* [ADR-0003](../../../docs/adr/0003-storage-strategy-pg-clickhouse-default.md)
|
|
6
|
+
* and the
|
|
7
|
+
* [implementation plan](../../../docs/plans/2026-05-05-cascade-storage-execution-implementation.md).
|
|
8
|
+
*
|
|
9
|
+
* This module is **strategy + scaffolding** — the *primitive* the cascade
|
|
10
|
+
* orchestrator (`aip-8yal`) calls. It does not run the orchestration loop
|
|
11
|
+
* itself, does not call LLMs, and does not implement the dual-write to
|
|
12
|
+
* Pipelines/Iceberg fan-out (that's `aip-0ypt`). It does:
|
|
13
|
+
*
|
|
14
|
+
* 1. **Shard-key derivation** — given a cascade context, pick the
|
|
15
|
+
* {@link ShardRef} the next batch should land in. Built-in strategies
|
|
16
|
+
* cover the three sharding models declared on `DBProvider`:
|
|
17
|
+
* `per-cascade` (DO SQLite default), `partitioned-by-tenant` (PG
|
|
18
|
+
* schema-per-tenant or `tenant_id` partition key), `unsharded`.
|
|
19
|
+
*
|
|
20
|
+
* 2. **Bulk-write API** — {@link writeBatch} routes a batch of Things +
|
|
21
|
+
* Actions through the adapter's cascade fast path. For PG, that's the
|
|
22
|
+
* **CTE jsonb-bulk shape** proven by the substrate-write-probes
|
|
23
|
+
* (91 ms p50 for 500 things + 499 actions on Neon HTTP — see
|
|
24
|
+
* `docs/reviews/2026-05-05-cascade-poc-evaluation.md`). For DO SQLite,
|
|
25
|
+
* the routing layer pins the shard and forwards the batch into the
|
|
26
|
+
* per-cascade DO. For ClickHouse, JSONEachRow is the path.
|
|
27
|
+
*
|
|
28
|
+
* 3. **Read-back-during-traversal API** — {@link readShardLocal} performs a
|
|
29
|
+
* point read against the same shard the batch was written to. Cascade
|
|
30
|
+
* generation reads back just-written entities to inform the next
|
|
31
|
+
* generation step; cross-shard reads on the hot path are explicitly
|
|
32
|
+
* not supported.
|
|
33
|
+
*
|
|
34
|
+
* 4. **Pipelines fan-out hook** — a {@link AnalyticalEmitter} callback the
|
|
35
|
+
* caller may pass to {@link writeBatch}. The cascade-write-strategy
|
|
36
|
+
* invokes it post-commit so Stack B's dual-write
|
|
37
|
+
* (DO SQLite local → Pipelines → Iceberg → ClickHouse) can be wired
|
|
38
|
+
* later by `aip-0ypt` without changing this surface.
|
|
39
|
+
*
|
|
40
|
+
* ## Why a separate module
|
|
41
|
+
*
|
|
42
|
+
* The cascade orchestrator is long, has its own retry/validation/policy
|
|
43
|
+
* concerns, and needs swappable storage. Pulling the write-strategy
|
|
44
|
+
* primitive out keeps the orchestration module focused, lets us unit-test
|
|
45
|
+
* shard-key derivation independently of LLM calls, and keeps the
|
|
46
|
+
* provenance of the write shape (the substrate-write-probes verdict)
|
|
47
|
+
* documented in one place rather than scattered through orchestrator code.
|
|
48
|
+
*
|
|
49
|
+
* @see {@link ../docs/adr/0003-storage-strategy-pg-clickhouse-default.md}
|
|
50
|
+
* @see {@link ../docs/reviews/2026-05-05-cascade-poc-evaluation.md}
|
|
51
|
+
* @packageDocumentation
|
|
52
|
+
*/
|
|
53
|
+
import { getProviderCapabilities } from './db-provider-port.js';
|
|
54
|
+
/**
|
|
55
|
+
* Built-in cascade sharding strategies.
|
|
56
|
+
*
|
|
57
|
+
* Each maps the abstract {@link ShardingModel} declared on a `DBProvider`
|
|
58
|
+
* to a concrete routing-key derivation. Adapters consult their adapter's
|
|
59
|
+
* declared sharding model via {@link getProviderCapabilities} when
|
|
60
|
+
* picking a default; callers can override.
|
|
61
|
+
*
|
|
62
|
+
* - {@link perCascade} — one shard per cascade. Default for
|
|
63
|
+
* `do-sqlite` adapter (per ADR-0003 enabling pattern). Throws if
|
|
64
|
+
* {@link CascadeShardContext.cascadeId} is missing.
|
|
65
|
+
* - {@link partitionedByTenant} — one shard per tenant. Default for
|
|
66
|
+
* `pg+pgvector` adapter. Throws if {@link CascadeShardContext.tenantId}
|
|
67
|
+
* is missing.
|
|
68
|
+
* - {@link unsharded} — single global shard. Default for `memory` and any
|
|
69
|
+
* adapter that does not declare a sharding model. Always returns the
|
|
70
|
+
* constant key `'__shared__'`.
|
|
71
|
+
*/
|
|
72
|
+
export const CascadeShardingStrategies = {
|
|
73
|
+
/**
|
|
74
|
+
* One shard per cascade. Stack B's enabling pattern: every active
|
|
75
|
+
* cascade gets its own DO (or its own PG partition / temp schema)
|
|
76
|
+
* giving full single-shard write throughput in parallel.
|
|
77
|
+
*
|
|
78
|
+
* @param defaultCascadeId - Fallback when the per-op context omits
|
|
79
|
+
* `cascadeId`. Useful when the orchestrator has a stable cascade
|
|
80
|
+
* scope but individual write batches don't restate it.
|
|
81
|
+
*/
|
|
82
|
+
perCascade(defaultCascadeId) {
|
|
83
|
+
return (ctx) => {
|
|
84
|
+
const cascadeId = ctx.cascadeId ?? defaultCascadeId;
|
|
85
|
+
if (!cascadeId) {
|
|
86
|
+
throw new Error('CascadeShardingStrategies.perCascade: no cascadeId in context. ' +
|
|
87
|
+
'Pass `cascadeId` on the CascadeShardContext, or supply a ' +
|
|
88
|
+
'default via perCascade(defaultCascadeId).');
|
|
89
|
+
}
|
|
90
|
+
return {
|
|
91
|
+
key: `cascade:${cascadeId}`,
|
|
92
|
+
model: 'per-cascade',
|
|
93
|
+
context: { ...ctx, cascadeId },
|
|
94
|
+
};
|
|
95
|
+
};
|
|
96
|
+
},
|
|
97
|
+
/**
|
|
98
|
+
* One shard per tenant. The natural shape for multi-tenant Postgres
|
|
99
|
+
* (schema-per-tenant or `tenant_id` partition key). Many cascades
|
|
100
|
+
* within the same tenant share a partition; tenants are isolated.
|
|
101
|
+
*
|
|
102
|
+
* @param defaultTenantId - Fallback when the per-op context omits
|
|
103
|
+
* `tenantId`.
|
|
104
|
+
*/
|
|
105
|
+
partitionedByTenant(defaultTenantId) {
|
|
106
|
+
return (ctx) => {
|
|
107
|
+
const tenantId = ctx.tenantId ?? defaultTenantId;
|
|
108
|
+
if (!tenantId) {
|
|
109
|
+
throw new Error('CascadeShardingStrategies.partitionedByTenant: no tenantId in ' +
|
|
110
|
+
'context. Pass `tenantId` on the CascadeShardContext, or supply ' +
|
|
111
|
+
'a default via partitionedByTenant(defaultTenantId).');
|
|
112
|
+
}
|
|
113
|
+
return {
|
|
114
|
+
key: `tenant:${tenantId}`,
|
|
115
|
+
model: 'partitioned-by-tenant',
|
|
116
|
+
context: { ...ctx, tenantId },
|
|
117
|
+
};
|
|
118
|
+
};
|
|
119
|
+
},
|
|
120
|
+
/**
|
|
121
|
+
* Single global shard. Default for in-memory / dev / single small PG
|
|
122
|
+
* deployments. Cascade throughput hits the underlying adapter's
|
|
123
|
+
* single-writer ceiling.
|
|
124
|
+
*/
|
|
125
|
+
unsharded() {
|
|
126
|
+
return (ctx) => ({
|
|
127
|
+
key: '__shared__',
|
|
128
|
+
model: 'unsharded',
|
|
129
|
+
context: { ...ctx },
|
|
130
|
+
});
|
|
131
|
+
},
|
|
132
|
+
};
|
|
133
|
+
/**
|
|
134
|
+
* The cascade write strategy primitive.
|
|
135
|
+
*
|
|
136
|
+
* Composes a `DBProvider` adapter with a sharding strategy and exposes
|
|
137
|
+
* the bulk-write + read-back surface the cascade orchestrator
|
|
138
|
+
* (`aip-8yal`) calls per traversal step. This module owns:
|
|
139
|
+
*
|
|
140
|
+
* - Routing-key derivation ({@link pickShard})
|
|
141
|
+
* - Bulk write via the adapter's cascade fast path ({@link writeBatch})
|
|
142
|
+
* - Local read-back from the same shard ({@link readShardLocal})
|
|
143
|
+
* - Analytical fan-out hook (post-commit; opt-in)
|
|
144
|
+
*
|
|
145
|
+
* It does NOT own:
|
|
146
|
+
*
|
|
147
|
+
* - LLM-driven generation (the orchestrator calls it before issuing batches)
|
|
148
|
+
* - Validation / policy / retry (the orchestrator wraps the strategy)
|
|
149
|
+
* - Pipelines→Iceberg dual-write semantics (`aip-0ypt`)
|
|
150
|
+
* - Cross-shard joins (out of scope per ADR-0003 hot-path constraint)
|
|
151
|
+
*
|
|
152
|
+
* @example
|
|
153
|
+
* ```ts
|
|
154
|
+
* import {
|
|
155
|
+
* CascadeWriteStrategy,
|
|
156
|
+
* createPostgresProvider,
|
|
157
|
+
* } from 'ai-database'
|
|
158
|
+
*
|
|
159
|
+
* const adapter = createPostgresProvider({ executor, namespace: 'tenant-9' })
|
|
160
|
+
* const strategy = new CascadeWriteStrategy({
|
|
161
|
+
* adapter,
|
|
162
|
+
* sharding: 'partitioned-by-tenant',
|
|
163
|
+
* defaultTenantId: 'tenant-9',
|
|
164
|
+
* })
|
|
165
|
+
*
|
|
166
|
+
* const shard = strategy.pickShard({
|
|
167
|
+
* rootEntity: { $id: 'fh-1', $type: 'FoundingHypothesis' },
|
|
168
|
+
* tenantId: 'tenant-9',
|
|
169
|
+
* })
|
|
170
|
+
*
|
|
171
|
+
* await strategy.writeBatch(shard, {
|
|
172
|
+
* things: [{ id: 'cust-1', type: 'Customer', data: { name: 'Acme' } }],
|
|
173
|
+
* actions: [{ verb: 'placedBy', subject: 'order-1', object: 'cust-1', status: 'completed' }],
|
|
174
|
+
* })
|
|
175
|
+
* ```
|
|
176
|
+
*/
|
|
177
|
+
export class CascadeWriteStrategy {
|
|
178
|
+
adapter;
|
|
179
|
+
strategy;
|
|
180
|
+
maxBatchSize;
|
|
181
|
+
emitter;
|
|
182
|
+
constructor(options) {
|
|
183
|
+
this.adapter = options.adapter;
|
|
184
|
+
this.strategy = resolveShardingStrategy(options);
|
|
185
|
+
this.maxBatchSize = options.maxBatchSize ?? 1000;
|
|
186
|
+
this.emitter = options.analyticalEmitter;
|
|
187
|
+
}
|
|
188
|
+
/**
|
|
189
|
+
* Derive the {@link ShardRef} the next batch should land in. Pure —
|
|
190
|
+
* never touches the adapter.
|
|
191
|
+
*
|
|
192
|
+
* Throws when the active strategy needs context the caller didn't
|
|
193
|
+
* supply (e.g. `'per-cascade'` with no `cascadeId`).
|
|
194
|
+
*/
|
|
195
|
+
pickShard(context) {
|
|
196
|
+
return this.strategy(context);
|
|
197
|
+
}
|
|
198
|
+
/**
|
|
199
|
+
* Bulk-commit a batch of Things + Actions to the shard.
|
|
200
|
+
*
|
|
201
|
+
* - When the adapter is {@link BulkCommitCapable}, the entire batch
|
|
202
|
+
* travels in a single fast-path call — for PG that's the CTE
|
|
203
|
+
* jsonb-bulk shape (91 ms p50 / 500 things on Neon HTTP), for CH
|
|
204
|
+
* the JSONEachRow path.
|
|
205
|
+
* - When the adapter is not bulk-capable (in-memory, DO SQLite via
|
|
206
|
+
* the current wire shape), the strategy falls back to per-op
|
|
207
|
+
* `create()` + `relate()` calls. This still flows through the
|
|
208
|
+
* shard-aware adapter so reads land on the same shard, but
|
|
209
|
+
* throughput is the per-op ceiling.
|
|
210
|
+
* - Batches larger than {@link maxBatchSize} are split into rounds.
|
|
211
|
+
* Rounds run sequentially within a single `writeBatch` call to
|
|
212
|
+
* preserve write-order guarantees the orchestrator may rely on
|
|
213
|
+
* (e.g. parents before children). Sibling parallelism is the
|
|
214
|
+
* orchestrator's concern, not this primitive's.
|
|
215
|
+
*
|
|
216
|
+
* Post-commit, if an {@link AnalyticalEmitter} was configured, it is
|
|
217
|
+
* invoked once per chunk so Stack B's analytical fan-out can mirror
|
|
218
|
+
* the same batch into Pipelines→Iceberg. Emitter failures are logged
|
|
219
|
+
* and swallowed — they MUST NOT fail the cascade write.
|
|
220
|
+
*/
|
|
221
|
+
async writeBatch(shard, batch) {
|
|
222
|
+
const things = batch.things ?? [];
|
|
223
|
+
const actions = batch.actions ?? [];
|
|
224
|
+
if (things.length === 0 && actions.length === 0) {
|
|
225
|
+
return { thingsInserted: 0, actionsInserted: 0, shard };
|
|
226
|
+
}
|
|
227
|
+
const boundAdapter = this.bindAdapterToShard(shard);
|
|
228
|
+
const chunks = chunkBatch({ things, actions }, this.maxBatchSize);
|
|
229
|
+
let thingsInserted = 0;
|
|
230
|
+
let actionsInserted = 0;
|
|
231
|
+
for (const chunk of chunks) {
|
|
232
|
+
const result = await this.writeChunk(boundAdapter, chunk);
|
|
233
|
+
thingsInserted += result.thingsInserted;
|
|
234
|
+
actionsInserted += result.actionsInserted;
|
|
235
|
+
// Post-commit fan-out hook for aip-0ypt. Failures are non-fatal —
|
|
236
|
+
// the cascade local commit is the source of truth for traversal.
|
|
237
|
+
if (this.emitter) {
|
|
238
|
+
try {
|
|
239
|
+
await this.emitter({ shard, batch: chunk, result });
|
|
240
|
+
}
|
|
241
|
+
catch {
|
|
242
|
+
// Analytical fan-out is best-effort; log site is the caller's
|
|
243
|
+
// concern (we don't pull a logger dependency here).
|
|
244
|
+
}
|
|
245
|
+
}
|
|
246
|
+
}
|
|
247
|
+
return { thingsInserted, actionsInserted, shard };
|
|
248
|
+
}
|
|
249
|
+
/**
|
|
250
|
+
* Read a Thing back from the same shard the batch was written to.
|
|
251
|
+
*
|
|
252
|
+
* Cascade generation reads back just-written entities to inform the
|
|
253
|
+
* next traversal step (e.g. resolve a freshly-written `Customer`
|
|
254
|
+
* before generating its `Orders`). Cross-shard reads are explicitly
|
|
255
|
+
* not supported on the hot path per ADR-0003.
|
|
256
|
+
*
|
|
257
|
+
* Returns `null` if the entity is not in the shard. The caller may
|
|
258
|
+
* still attempt a cross-shard read via the unsharded adapter surface
|
|
259
|
+
* if needed for cold-path reconciliation.
|
|
260
|
+
*/
|
|
261
|
+
async readShardLocal(shard, type, id) {
|
|
262
|
+
const boundAdapter = this.bindAdapterToShard(shard);
|
|
263
|
+
return boundAdapter.get(type, id);
|
|
264
|
+
}
|
|
265
|
+
/**
|
|
266
|
+
* Read a list of just-written entities from the shard. Wraps
|
|
267
|
+
* `adapter.list(type)` after binding the shard context.
|
|
268
|
+
*
|
|
269
|
+
* Use when the cascade needs to enumerate all of a type the current
|
|
270
|
+
* cascade has produced (e.g. all `OrderItem` for the current
|
|
271
|
+
* `Order`). For point reads, prefer {@link readShardLocal}.
|
|
272
|
+
*/
|
|
273
|
+
async listShardLocal(shard, type, options) {
|
|
274
|
+
const boundAdapter = this.bindAdapterToShard(shard);
|
|
275
|
+
return boundAdapter.list(type, options);
|
|
276
|
+
}
|
|
277
|
+
// ===========================================================================
|
|
278
|
+
// Internal helpers
|
|
279
|
+
// ===========================================================================
|
|
280
|
+
/**
|
|
281
|
+
* Bind the adapter to the shard so subsequent ops route correctly.
|
|
282
|
+
*
|
|
283
|
+
* For DO SQLite, {@link DOSqliteAdapter.withContext} is used to pin
|
|
284
|
+
* the cascade/tenant id. For PG/CH, the `ns` column on the adapter
|
|
285
|
+
* already carries the partition key, so this is a no-op (return
|
|
286
|
+
* `this`).
|
|
287
|
+
*/
|
|
288
|
+
bindAdapterToShard(shard) {
|
|
289
|
+
const bindable = this.adapter;
|
|
290
|
+
if (typeof bindable.withContext === 'function') {
|
|
291
|
+
return bindable.withContext({ ...shard.context });
|
|
292
|
+
}
|
|
293
|
+
return this.adapter;
|
|
294
|
+
}
|
|
295
|
+
/**
|
|
296
|
+
* Write a single chunk through the adapter's cascade fast path or
|
|
297
|
+
* the per-op fallback.
|
|
298
|
+
*/
|
|
299
|
+
async writeChunk(adapter, chunk) {
|
|
300
|
+
const things = chunk.things ?? [];
|
|
301
|
+
const actions = chunk.actions ?? [];
|
|
302
|
+
const bulkCapable = adapter;
|
|
303
|
+
if (typeof bulkCapable.commitBatch === 'function') {
|
|
304
|
+
// PG / CH fast path. PG uses the CTE jsonb-bulk shape (proven by
|
|
305
|
+
// the substrate-write-probes); CH uses JSONEachRow. Both shapes
|
|
306
|
+
// are documented on the respective adapter.
|
|
307
|
+
return bulkCapable.commitBatch({
|
|
308
|
+
...(things.length > 0 && { things }),
|
|
309
|
+
...(actions.length > 0 && {
|
|
310
|
+
actions: actions.map((a) => ({
|
|
311
|
+
...(a.id !== undefined && { id: a.id }),
|
|
312
|
+
verb: a.verb,
|
|
313
|
+
subject: a.subject,
|
|
314
|
+
object: a.object,
|
|
315
|
+
roles: a.roles,
|
|
316
|
+
data: a.data,
|
|
317
|
+
status: a.status,
|
|
318
|
+
})),
|
|
319
|
+
}),
|
|
320
|
+
});
|
|
321
|
+
}
|
|
322
|
+
// Fallback: per-op writes. Used by DO SQLite (bulk path lives at the
|
|
323
|
+
// DO wire level — out of scope for this bead) and the in-memory
|
|
324
|
+
// adapter. Sequential within a chunk so writes appear in the order
|
|
325
|
+
// the orchestrator emitted them; parallelism is the orchestrator's
|
|
326
|
+
// concern.
|
|
327
|
+
let thingsInserted = 0;
|
|
328
|
+
for (const thing of things) {
|
|
329
|
+
try {
|
|
330
|
+
await adapter.create(thing.type, thing.id, thing.data);
|
|
331
|
+
thingsInserted += 1;
|
|
332
|
+
}
|
|
333
|
+
catch (err) {
|
|
334
|
+
// Best-effort idempotency: swallow already-exists errors so
|
|
335
|
+
// re-runs of a content-hashed cascade don't fail. Surface
|
|
336
|
+
// anything else.
|
|
337
|
+
if (!isAlreadyExistsError(err))
|
|
338
|
+
throw err;
|
|
339
|
+
}
|
|
340
|
+
}
|
|
341
|
+
let actionsInserted = 0;
|
|
342
|
+
for (const action of actions) {
|
|
343
|
+
// Use recordAction when available (SVO surface); fall back to
|
|
344
|
+
// relate() if the adapter only exposes the structural surface.
|
|
345
|
+
const svo = adapter;
|
|
346
|
+
if (typeof svo.recordAction === 'function') {
|
|
347
|
+
await svo.recordAction({
|
|
348
|
+
verb: action.verb,
|
|
349
|
+
...(action.subject !== undefined && { subject: action.subject }),
|
|
350
|
+
...(action.object !== undefined && { object: action.object }),
|
|
351
|
+
...(action.roles !== undefined && { roles: action.roles }),
|
|
352
|
+
...(action.data !== undefined && { data: action.data }),
|
|
353
|
+
...(action.status !== undefined && { status: action.status }),
|
|
354
|
+
});
|
|
355
|
+
}
|
|
356
|
+
else if (action.subject && action.object) {
|
|
357
|
+
// Best-effort fallback — the adapter doesn't speak SVO. We have
|
|
358
|
+
// no type information for relate(), which expects fromType /
|
|
359
|
+
// toType; we use the data fields if present, else a generic
|
|
360
|
+
// 'Thing' placeholder. Adapters in this position are dev-only
|
|
361
|
+
// (in-memory tests) so this is acceptable.
|
|
362
|
+
const fromType = action.data?.['fromType'] ?? 'Thing';
|
|
363
|
+
const toType = action.data?.['toType'] ?? 'Thing';
|
|
364
|
+
await adapter.relate(fromType, action.subject, action.verb, toType, action.object);
|
|
365
|
+
}
|
|
366
|
+
actionsInserted += 1;
|
|
367
|
+
}
|
|
368
|
+
return { thingsInserted, actionsInserted };
|
|
369
|
+
}
|
|
370
|
+
}
|
|
371
|
+
// =============================================================================
|
|
372
|
+
// PG-specific bulk-write helper — the proven CTE jsonb-bulk shape
|
|
373
|
+
// =============================================================================
|
|
374
|
+
/**
|
|
375
|
+
* Stand-alone helper that emits the PG cascade-write SQL the
|
|
376
|
+
* substrate-write-probes proved out: a single CTE round-trip with
|
|
377
|
+
* bulk `VALUES (...), (...)` inserts and `ON CONFLICT DO NOTHING`.
|
|
378
|
+
*
|
|
379
|
+
* **This is the shape the canonical PG adapter's
|
|
380
|
+
* {@link PostgresProvider.commitBatch} uses.** The helper is exported so
|
|
381
|
+
* cascade orchestrators that bypass the adapter (e.g. running raw SQL
|
|
382
|
+
* for benchmarking) can still use the proven shape without re-deriving
|
|
383
|
+
* it. The adapter's `commitBatch` remains the recommended path.
|
|
384
|
+
*
|
|
385
|
+
* Returns the SQL text + ordered positional params. Things take 4
|
|
386
|
+
* columns: `(ns, id, type, data)`. Actions take 10 columns:
|
|
387
|
+
* `(ns, id, verb, subject, object, roles, data, status, created_at, completed_at)`.
|
|
388
|
+
*
|
|
389
|
+
* Why: documenting the shape in a stand-alone helper anchors the write
|
|
390
|
+
* shape to the substrate-write-probes evidence (91 ms p50 for 500 docs +
|
|
391
|
+
* 499 rels on Neon HTTP, sublinear scaling above N=100). Future schema
|
|
392
|
+
* changes that invalidate the column list will land here visibly.
|
|
393
|
+
*
|
|
394
|
+
* @internal Use {@link PostgresProvider.commitBatch} for production code.
|
|
395
|
+
*/
|
|
396
|
+
export function buildPgCommitBatchSql(input) {
|
|
397
|
+
const { schema, namespace, things, actions, now } = input;
|
|
398
|
+
if (things.length === 0 && actions.length === 0)
|
|
399
|
+
return null;
|
|
400
|
+
const thingCols = 4;
|
|
401
|
+
const actionCols = 10;
|
|
402
|
+
const thingOffset = things.length * thingCols;
|
|
403
|
+
const thingPlaceholders = things
|
|
404
|
+
.map((_, i) => {
|
|
405
|
+
const base = i * thingCols;
|
|
406
|
+
return `($${base + 1}, $${base + 2}, $${base + 3}, $${base + 4}::jsonb)`;
|
|
407
|
+
})
|
|
408
|
+
.join(', ');
|
|
409
|
+
const actionPlaceholders = actions
|
|
410
|
+
.map((_, i) => {
|
|
411
|
+
const base = thingOffset + i * actionCols;
|
|
412
|
+
return `($${base + 1}, $${base + 2}, $${base + 3}, $${base + 4}, $${base + 5}, $${base + 6}::jsonb, $${base + 7}::jsonb, $${base + 8}, $${base + 9}, $${base + 10})`;
|
|
413
|
+
})
|
|
414
|
+
.join(', ');
|
|
415
|
+
const params = [];
|
|
416
|
+
for (const t of things) {
|
|
417
|
+
params.push(namespace, t.id, t.type, JSON.stringify(t.data));
|
|
418
|
+
}
|
|
419
|
+
for (const a of actions) {
|
|
420
|
+
const status = a.status ?? 'pending';
|
|
421
|
+
const completedAt = status === 'completed' || status === 'failed' || status === 'cancelled' ? now : null;
|
|
422
|
+
params.push(namespace, a.id ?? generateId(), a.verb, a.subject ?? null, a.object ?? null, JSON.stringify(a.roles ?? {}), JSON.stringify(a.data ?? {}), status, now, completedAt);
|
|
423
|
+
}
|
|
424
|
+
const ctes = [];
|
|
425
|
+
if (things.length > 0) {
|
|
426
|
+
ctes.push(`inserted_things AS (
|
|
427
|
+
INSERT INTO ${schema}.things (ns, id, type, data) VALUES ${thingPlaceholders}
|
|
428
|
+
ON CONFLICT ON CONSTRAINT things_pk DO NOTHING
|
|
429
|
+
RETURNING 1
|
|
430
|
+
)`);
|
|
431
|
+
}
|
|
432
|
+
if (actions.length > 0) {
|
|
433
|
+
ctes.push(`inserted_actions AS (
|
|
434
|
+
INSERT INTO ${schema}.actions
|
|
435
|
+
(ns, id, verb, subject, object, roles, data, status, created_at, completed_at)
|
|
436
|
+
VALUES ${actionPlaceholders}
|
|
437
|
+
ON CONFLICT ON CONSTRAINT actions_pk DO NOTHING
|
|
438
|
+
RETURNING 1
|
|
439
|
+
)`);
|
|
440
|
+
}
|
|
441
|
+
const sql = `WITH ${ctes.join(', ')}
|
|
442
|
+
SELECT
|
|
443
|
+
${things.length > 0 ? `(SELECT COUNT(*) FROM inserted_things)::int` : '0'} AS things_inserted,
|
|
444
|
+
${actions.length > 0 ? `(SELECT COUNT(*) FROM inserted_actions)::int` : '0'} AS actions_inserted`;
|
|
445
|
+
return { sql, params };
|
|
446
|
+
}
|
|
447
|
+
// =============================================================================
|
|
448
|
+
// DO SQLite shard-routing helper
|
|
449
|
+
// =============================================================================
|
|
450
|
+
/**
|
|
451
|
+
* Resolve the DO id name for a given shard from a Cloudflare DO
|
|
452
|
+
* namespace binding.
|
|
453
|
+
*
|
|
454
|
+
* The actual shard pinning happens inside `DOSqliteAdapter` —
|
|
455
|
+
* {@link DOSqliteAdapter.withContext} consumes the `ShardRef.context`
|
|
456
|
+
* when subsequent ops are issued, and the adapter's internal
|
|
457
|
+
* `resolveStub` calls `namespace.idFromName(...).` This helper exposes
|
|
458
|
+
* the same routing logic for callers that need to **manually** route a
|
|
459
|
+
* batch into a per-cascade DO without going through the adapter (e.g.
|
|
460
|
+
* direct fetch into a DO that hasn't been wrapped yet).
|
|
461
|
+
*
|
|
462
|
+
* For canonical use, prefer the adapter — `withContext(shard.context)`
|
|
463
|
+
* encapsulates this.
|
|
464
|
+
*
|
|
465
|
+
* @example
|
|
466
|
+
* ```ts
|
|
467
|
+
* import { resolveDOIdName, CascadeShardingStrategies } from 'ai-database'
|
|
468
|
+
*
|
|
469
|
+
* const strategy = CascadeShardingStrategies.perCascade()
|
|
470
|
+
* const shard = strategy({ cascadeId: 'abc' })
|
|
471
|
+
* const idName = resolveDOIdName(shard) // 'cascade:abc'
|
|
472
|
+
* const id = env.DATABASE.idFromName(idName)
|
|
473
|
+
* const stub = env.DATABASE.get(id)
|
|
474
|
+
* await stub.fetch(...)
|
|
475
|
+
* ```
|
|
476
|
+
*/
|
|
477
|
+
export function resolveDOIdName(shard) {
|
|
478
|
+
return shard.key;
|
|
479
|
+
}
|
|
480
|
+
// =============================================================================
|
|
481
|
+
// Helpers — chunking, error classification, id generation, strategy resolution
|
|
482
|
+
// =============================================================================
|
|
483
|
+
/**
|
|
484
|
+
* Split a batch into chunks no larger than `maxBatchSize` rows
|
|
485
|
+
* (Things + Actions counted together).
|
|
486
|
+
*
|
|
487
|
+
* The substrate-write-probes verdict shows sublinear scaling above N=100
|
|
488
|
+
* for the CTE shape — a single round-trip carrying 500 things + 499 rels
|
|
489
|
+
* lands in 91 ms p50. We default to 1000 rows/chunk in the strategy;
|
|
490
|
+
* callers can override via {@link CascadeWriteStrategyOptions.maxBatchSize}.
|
|
491
|
+
*
|
|
492
|
+
* Things and Actions are kept together within a chunk so a parent +
|
|
493
|
+
* child + their relation can fit in one round-trip when the orchestrator
|
|
494
|
+
* emits them as one batch. When the chunk boundary falls inside a
|
|
495
|
+
* Thing/Action group the orchestrator built, callers should size their
|
|
496
|
+
* batches (or the `maxBatchSize`) to avoid splitting groups.
|
|
497
|
+
*
|
|
498
|
+
* @internal exported for tests.
|
|
499
|
+
*/
|
|
500
|
+
export function chunkBatch(batch, maxBatchSize) {
|
|
501
|
+
if (maxBatchSize <= 0) {
|
|
502
|
+
throw new Error('chunkBatch: maxBatchSize must be > 0');
|
|
503
|
+
}
|
|
504
|
+
const things = batch.things ?? [];
|
|
505
|
+
const actions = batch.actions ?? [];
|
|
506
|
+
const total = things.length + actions.length;
|
|
507
|
+
if (total <= maxBatchSize)
|
|
508
|
+
return [{ things, actions }];
|
|
509
|
+
const chunks = [];
|
|
510
|
+
let ti = 0;
|
|
511
|
+
let ai = 0;
|
|
512
|
+
while (ti < things.length || ai < actions.length) {
|
|
513
|
+
const remainingThings = things.length - ti;
|
|
514
|
+
const takeThings = Math.min(remainingThings, maxBatchSize);
|
|
515
|
+
const remaining = maxBatchSize - takeThings;
|
|
516
|
+
const takeActions = Math.min(actions.length - ai, remaining);
|
|
517
|
+
chunks.push({
|
|
518
|
+
things: things.slice(ti, ti + takeThings),
|
|
519
|
+
actions: actions.slice(ai, ai + takeActions),
|
|
520
|
+
});
|
|
521
|
+
ti += takeThings;
|
|
522
|
+
ai += takeActions;
|
|
523
|
+
}
|
|
524
|
+
return chunks;
|
|
525
|
+
}
|
|
526
|
+
/**
|
|
527
|
+
* Classify an error as the adapter's idempotent-conflict signal so
|
|
528
|
+
* per-op fallback writes can swallow re-runs.
|
|
529
|
+
*/
|
|
530
|
+
function isAlreadyExistsError(err) {
|
|
531
|
+
if (!err)
|
|
532
|
+
return false;
|
|
533
|
+
const msg = err instanceof Error ? err.message : String(err);
|
|
534
|
+
// Loose match — adapters use different wording. Cascade re-runs depend
|
|
535
|
+
// on content-hashed ids, so a true conflict is benign.
|
|
536
|
+
return /already exists|duplicate|unique constraint|conflict/i.test(msg);
|
|
537
|
+
}
|
|
538
|
+
/**
|
|
539
|
+
* Resolve the active sharding strategy from constructor options. Falls
|
|
540
|
+
* back to the adapter's declared {@link ShardingModel} when the caller
|
|
541
|
+
* didn't supply one.
|
|
542
|
+
*/
|
|
543
|
+
function resolveShardingStrategy(opts) {
|
|
544
|
+
const sharding = opts.sharding;
|
|
545
|
+
if (typeof sharding === 'function')
|
|
546
|
+
return sharding;
|
|
547
|
+
const declared = sharding ?? getProviderCapabilities(opts.adapter).shardingModel;
|
|
548
|
+
switch (declared) {
|
|
549
|
+
case 'per-cascade':
|
|
550
|
+
return CascadeShardingStrategies.perCascade(opts.defaultCascadeId);
|
|
551
|
+
case 'partitioned-by-tenant':
|
|
552
|
+
return CascadeShardingStrategies.partitionedByTenant(opts.defaultTenantId);
|
|
553
|
+
case 'unsharded':
|
|
554
|
+
return CascadeShardingStrategies.unsharded();
|
|
555
|
+
default:
|
|
556
|
+
// Custom / forward-compat shard models declared by future adapters
|
|
557
|
+
// fall back to unsharded; callers should pass an explicit strategy.
|
|
558
|
+
return CascadeShardingStrategies.unsharded();
|
|
559
|
+
}
|
|
560
|
+
}
|
|
561
|
+
function generateId() {
|
|
562
|
+
if (typeof crypto !== 'undefined' && typeof crypto.randomUUID === 'function') {
|
|
563
|
+
return crypto.randomUUID();
|
|
564
|
+
}
|
|
565
|
+
// Tests in environments without `crypto` get a deterministic prefix +
|
|
566
|
+
// timestamp; production paths always have crypto available.
|
|
567
|
+
return `cascade-${Date.now()}-${Math.random().toString(36).slice(2)}`;
|
|
568
|
+
}
|
|
569
|
+
/**
|
|
570
|
+
* Convenience factory.
|
|
571
|
+
*
|
|
572
|
+
* @example
|
|
573
|
+
* ```ts
|
|
574
|
+
* import {
|
|
575
|
+
* createCascadeWriteStrategy,
|
|
576
|
+
* createPostgresProvider,
|
|
577
|
+
* } from 'ai-database'
|
|
578
|
+
*
|
|
579
|
+
* const adapter = createPostgresProvider({ executor, namespace: 't9' })
|
|
580
|
+
* const strategy = createCascadeWriteStrategy({
|
|
581
|
+
* adapter,
|
|
582
|
+
* sharding: 'partitioned-by-tenant',
|
|
583
|
+
* defaultTenantId: 't9',
|
|
584
|
+
* })
|
|
585
|
+
* ```
|
|
586
|
+
*/
|
|
587
|
+
export function createCascadeWriteStrategy(options) {
|
|
588
|
+
return new CascadeWriteStrategy(options);
|
|
589
|
+
}
|
|
590
|
+
//# sourceMappingURL=cascade-write-strategy.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cascade-write-strategy.js","sourceRoot":"","sources":["../src/cascade-write-strategy.ts"],"names":[],"mappings":"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"}
|