@earth-app/collegedb 1.0.8 → 1.1.1
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/README.md +590 -132
- package/dist/durable.d.ts +8 -4
- package/dist/durable.d.ts.map +1 -1
- package/dist/errors.d.ts +1 -1
- package/dist/index.d.ts +7 -6
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +9 -7
- package/dist/index.js.map +10 -9
- package/dist/kvmap.d.ts +68 -5
- package/dist/kvmap.d.ts.map +1 -1
- package/dist/migrations.d.ts +22 -19
- package/dist/migrations.d.ts.map +1 -1
- package/dist/providers.d.ts +284 -0
- package/dist/providers.d.ts.map +1 -0
- package/dist/router.d.ts +10 -10
- package/dist/router.d.ts.map +1 -1
- package/dist/types.d.ts +143 -14
- package/dist/types.d.ts.map +1 -1
- package/package.json +40 -16
package/README.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# CollegeDB
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
Universal Database Horizontal Sharding Router
|
|
4
4
|
|
|
5
5
|
[](https://www.typescriptlang.org/)
|
|
6
6
|
[](https://github.com/earth-app/CollegeDB/issues)
|
|
@@ -8,7 +8,32 @@ _Cloudflare D1 Horizontal Sharding Router_
|
|
|
8
8
|
[](LICENSE)
|
|
9
9
|

|
|
10
10
|
|
|
11
|
-
A TypeScript library for **true horizontal scaling** of SQLite-style databases
|
|
11
|
+
A TypeScript library for **true horizontal scaling** of SQLite-style databases primarily for Cloudflare using D1 and KV, with additional provider adapters for Redis/Valkey KV and PostgreSQL/MySQL/SQLite SQL backends, plus Drizzle ORM interop across those SQL providers. CollegeDB distributes your data across multiple database shards, with each table's records split by primary key across different database instances.
|
|
12
|
+
|
|
13
|
+
## Table of Contents
|
|
14
|
+
|
|
15
|
+
- [Why CollegeDB](#why-collegedb)
|
|
16
|
+
- [Features](#features)
|
|
17
|
+
- [Getting Started](#getting-started)
|
|
18
|
+
- [Benchmark Suite](#benchmark-suite)
|
|
19
|
+
- [Provider Adapters](#provider-adapters)
|
|
20
|
+
- [NuxtHub + Drizzle Recipes](#nuxthub--drizzle-recipes)
|
|
21
|
+
- [Sandbox Benchmarks (Docker Compose)](#sandbox-benchmarks-docker-compose)
|
|
22
|
+
- [Basic Usage](#basic-usage)
|
|
23
|
+
- [Multi-Key Shard Mappings](#multi-key-shard-mappings)
|
|
24
|
+
- [Drop-in Replacement for Existing Databases](#drop-in-replacement-for-existing-databases)
|
|
25
|
+
- [Troubleshooting](#troubleshooting)
|
|
26
|
+
- [API Reference](#api-reference)
|
|
27
|
+
- [Architecture](#architecture)
|
|
28
|
+
- [Cloudflare Setup](#cloudflare-setup)
|
|
29
|
+
- [Monitoring and Maintenance](#monitoring-and-maintenance)
|
|
30
|
+
- [Performance Analysis](#performance-analysis)
|
|
31
|
+
- [Advanced Configuration](#advanced-configuration)
|
|
32
|
+
- [Quick Reference](#quick-reference)
|
|
33
|
+
- [Contributing](#contributing)
|
|
34
|
+
- [License](#license)
|
|
35
|
+
|
|
36
|
+
## Why CollegeDB
|
|
12
37
|
|
|
13
38
|
CollegeDB implements **data distribution** where a single logical table is physically stored across multiple D1 databases:
|
|
14
39
|
|
|
@@ -39,30 +64,19 @@ This allows you to:
|
|
|
39
64
|
- **Scale geographically** by placing shards in different regions
|
|
40
65
|
- **Increase write throughput** by parallelizing across multiple database instances
|
|
41
66
|
|
|
42
|
-
##
|
|
67
|
+
## Features
|
|
43
68
|
|
|
44
|
-
|
|
69
|
+
- Automatic query routing (primary key to shard mapping)
|
|
70
|
+
- Provider adapters for Redis/Valkey/NuxtHub KV plus PostgreSQL/MySQL/SQLite SQL
|
|
71
|
+
- Drizzle interop through existing SQL providers (`createPostgreSQLProvider`, `createMySQLProvider`, `createSQLiteProvider`)
|
|
72
|
+
- Hyperdrive helpers for PostgreSQL and MySQL
|
|
73
|
+
- Multiple allocation strategies: round-robin, random, hash, location-aware, and mixed read/write strategies
|
|
74
|
+
- Durable Object shard coordination and shard statistics
|
|
75
|
+
- Migration helpers for integrating existing datasets and rebalancing mappings
|
|
45
76
|
|
|
46
|
-
|
|
47
|
-
- **Route queries automatically** based on primary key mappings
|
|
48
|
-
- **Maintain consistency** with KV-based shard mapping
|
|
49
|
-
- **Optimize for geography** with location-aware shard allocation
|
|
50
|
-
- **Monitor and rebalance** shard distribution
|
|
51
|
-
- **Handle migrations** between shards seamlessly
|
|
77
|
+
## Getting Started
|
|
52
78
|
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
- **🔀 Automatic Query Routing**: Primary key → shard mapping using Cloudflare KV
|
|
56
|
-
- **🎯 Multiple Allocation Strategies**: Round-robin, random, hash-based, and location-aware distribution
|
|
57
|
-
- **🔄 Mixed Strategy Support**: Different strategies for reads vs writes (e.g., location for writes, hash for reads)
|
|
58
|
-
- **📊 Shard Coordination**: Durable Objects for allocation and statistics
|
|
59
|
-
- **🛠 Migration Support**: Move data between shards with zero downtime
|
|
60
|
-
- **🔄 Automatic Drop-in Replacement**: Zero-config integration with existing databases
|
|
61
|
-
- **🤖 Smart Migration Detection**: Automatically discovers and maps existing data
|
|
62
|
-
- **⚡ High Performance**: Optimized for Cloudflare Workers runtime
|
|
63
|
-
- **🔧 TypeScript First**: Full type safety and excellent DX
|
|
64
|
-
|
|
65
|
-
## Installation
|
|
79
|
+
### Installation
|
|
66
80
|
|
|
67
81
|
```bash
|
|
68
82
|
bun add @earth-app/collegedb
|
|
@@ -70,6 +84,373 @@ bun add @earth-app/collegedb
|
|
|
70
84
|
npm install @earth-app/collegedb
|
|
71
85
|
```
|
|
72
86
|
|
|
87
|
+
### NuxtHub + Drizzle with CollegeDB Routing
|
|
88
|
+
|
|
89
|
+
Keep NuxtHub + Drizzle for schema/migrations and add CollegeDB as your routing layer.
|
|
90
|
+
|
|
91
|
+
```typescript
|
|
92
|
+
import { db as hubDb } from '@nuxthub/db';
|
|
93
|
+
import { kv } from '@nuxthub/kv';
|
|
94
|
+
import { sql } from 'drizzle-orm';
|
|
95
|
+
import { drizzle } from 'drizzle-orm/d1';
|
|
96
|
+
import { createNuxtHubKVProvider, createSQLiteProvider, first, initialize, run } from '@earth-app/collegedb';
|
|
97
|
+
|
|
98
|
+
let initialized = false;
|
|
99
|
+
|
|
100
|
+
function ensureCollegeDB(env: { DB_SECONDARY: D1Database }) {
|
|
101
|
+
if (initialized) return;
|
|
102
|
+
|
|
103
|
+
initialize({
|
|
104
|
+
kv: createNuxtHubKVProvider(kv),
|
|
105
|
+
shards: {
|
|
106
|
+
'db-primary': createSQLiteProvider(hubDb, sql),
|
|
107
|
+
'db-secondary': createSQLiteProvider(drizzle(env.DB_SECONDARY), sql)
|
|
108
|
+
},
|
|
109
|
+
strategy: 'hash'
|
|
110
|
+
});
|
|
111
|
+
|
|
112
|
+
initialized = true;
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
export default defineEventHandler(async (event) => {
|
|
116
|
+
const env = event.context.cloudflare.env;
|
|
117
|
+
ensureCollegeDB(env);
|
|
118
|
+
|
|
119
|
+
await run('post:123', 'INSERT OR REPLACE INTO blog_posts (id, title) VALUES (?, ?)', ['post:123', 'Hello from CollegeDB']);
|
|
120
|
+
|
|
121
|
+
const post = await first<{ id: string; title: string }>('post:123', 'SELECT id, title FROM blog_posts WHERE id = ?', ['post:123']);
|
|
122
|
+
|
|
123
|
+
return { post };
|
|
124
|
+
});
|
|
125
|
+
```
|
|
126
|
+
|
|
127
|
+
### Drop-in Pattern for Existing `hub:db` + `hub:kv` Code
|
|
128
|
+
|
|
129
|
+
```typescript
|
|
130
|
+
// before
|
|
131
|
+
import { eq } from 'drizzle-orm';
|
|
132
|
+
import { db } from 'hub:db';
|
|
133
|
+
import { kv } from 'hub:kv';
|
|
134
|
+
import { blogPosts } from '~/server/db/schema';
|
|
135
|
+
|
|
136
|
+
const cached = await kv.get('nuxtpress:post:slug');
|
|
137
|
+
if (cached) return cached;
|
|
138
|
+
|
|
139
|
+
const rows = await db.select().from(blogPosts).where(eq(blogPosts.slug, slug)).limit(1);
|
|
140
|
+
await kv.set('nuxtpress:post:slug', rows[0], { ttl: 3600 });
|
|
141
|
+
```
|
|
142
|
+
|
|
143
|
+
```typescript
|
|
144
|
+
// after (CollegeDB routing + same NuxtHub KV cache)
|
|
145
|
+
import { kv } from '@nuxthub/kv';
|
|
146
|
+
import { sql } from 'drizzle-orm';
|
|
147
|
+
import { db } from 'hub:db';
|
|
148
|
+
import { createNuxtHubKVProvider, createSQLiteProvider, first, initialize } from '@earth-app/collegedb';
|
|
149
|
+
|
|
150
|
+
let initialized = false;
|
|
151
|
+
|
|
152
|
+
function setup() {
|
|
153
|
+
if (initialized) return;
|
|
154
|
+
initialize({
|
|
155
|
+
kv: createNuxtHubKVProvider(kv),
|
|
156
|
+
shards: {
|
|
157
|
+
'db-primary': createSQLiteProvider(db, sql)
|
|
158
|
+
},
|
|
159
|
+
strategy: 'hash'
|
|
160
|
+
});
|
|
161
|
+
initialized = true;
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
setup();
|
|
165
|
+
|
|
166
|
+
const cacheKey = `nuxtpress:post:${slug}`;
|
|
167
|
+
const cached = await kv.get(cacheKey);
|
|
168
|
+
if (cached) return cached;
|
|
169
|
+
|
|
170
|
+
const row = await first<{ id: string; slug: string; title: string }>(
|
|
171
|
+
cacheKey,
|
|
172
|
+
'SELECT id, slug, title FROM blog_posts WHERE slug = ? LIMIT 1',
|
|
173
|
+
[slug]
|
|
174
|
+
);
|
|
175
|
+
|
|
176
|
+
await kv.set(cacheKey, row, { ttl: 3600 });
|
|
177
|
+
```
|
|
178
|
+
|
|
179
|
+
## Benchmark Suite
|
|
180
|
+
|
|
181
|
+
CollegeDB includes a benchmark runner that executes each SQL+KV combination across adapter profiles, then generates a report with profile-specific matrices.
|
|
182
|
+
|
|
183
|
+
### Adapter Profiles
|
|
184
|
+
|
|
185
|
+
| Profile | Purpose |
|
|
186
|
+
| ---------- | ----------------------------------------------------------------------- |
|
|
187
|
+
| native | Direct provider clients (Cloudflare bindings or driver-native adapters) |
|
|
188
|
+
| drizzle | Drizzle interop through SQL provider adapters |
|
|
189
|
+
| hyperdrive | Hyperdrive connection-string wrappers for PostgreSQL/MySQL |
|
|
190
|
+
| nuxthub | NuxtHub-style KV adapter with SQL provider interop |
|
|
191
|
+
|
|
192
|
+
### Scenario Catalog
|
|
193
|
+
|
|
194
|
+
| Scenario Key | Scenario | What Happens | Workload Per Run |
|
|
195
|
+
| ----------------- | -------------------------------- | --------------------------------------------------------------------------------------------------- | ---------------------------------------------------------------------- |
|
|
196
|
+
| basic_crud | Basic CRUD round-trip | Insert, read, update, and delete a user via routed queries. | 20 iterations; 4 routed SQL ops per iteration |
|
|
197
|
+
| advanced_usage | Advanced lookup workflow | Writes user+post, adds lookup aliases, then validates join and alias-based lookup. | 15 iterations; ~5 routed SQL ops + KV lookup-key updates per iteration |
|
|
198
|
+
| migration_mapping | Migration-style mapping creation | Inserts legacy records on a fixed shard, then builds shard mappings in batch and validates routing. | 10 iterations; 20 legacy records mapped per iteration |
|
|
199
|
+
| bulk_crud | Bulk CRUD pressure | Performs bulk inserts, half updates, and full delete sweep, then validates shard-wide totals. | 7 iterations; 160 inserts + 80 updates + 160 deletes per iteration |
|
|
200
|
+
| indexing | Indexed query scan | Creates an index on posts(user_id) and repeatedly queries the indexed path. | 15 iterations after warmup dataset build |
|
|
201
|
+
| metadata_fetch | Metadata inspection | Reads table metadata/introspection rows from one shard. | 14 iterations; 1 metadata query per iteration |
|
|
202
|
+
| pragma_or_info | PRAGMA / server info | Runs provider-specific PRAGMA/info query to sample low-level metadata latency. | 14 iterations; 1 pragma/info query per iteration |
|
|
203
|
+
| counting | Cross-shard counting | Counts users across all shards to measure fanout aggregation overhead. | 14 iterations; all-shard count aggregation per iteration |
|
|
204
|
+
| shard_fanout | Shard fanout query | Runs query fanout to all shards and aggregates shard-level responses. | 14 iterations; 1 all-shards query per iteration |
|
|
205
|
+
| reassignment | Shard reassignment flow | Creates a record, reassigns it to another shard, and verifies routed reads still succeed. | 10 iterations; insert + reassignment + verification per iteration |
|
|
206
|
+
|
|
207
|
+
### Report Matrices
|
|
208
|
+
|
|
209
|
+
Each generated report includes:
|
|
210
|
+
|
|
211
|
+
- `Matrix: SQL x KV (Overall)`
|
|
212
|
+
- `Matrix: Adapter Profiles (Overall Avg)`
|
|
213
|
+
- `Matrix: Core Scenario Latency (avg/p95)`
|
|
214
|
+
- `Matrix: Introspection and Routing Latency (avg/p95)`
|
|
215
|
+
- `Cloudflare Worker (wrangler dev --local)`
|
|
216
|
+
- `Matrix: Cloudflare Adapter Profiles (Overall Avg)`
|
|
217
|
+
|
|
218
|
+
### Common Commands
|
|
219
|
+
|
|
220
|
+
```bash
|
|
221
|
+
bun run test:sandbox
|
|
222
|
+
bun run test:sandbox:drizzle
|
|
223
|
+
bun run test:sandbox:nuxthub
|
|
224
|
+
bun run test:sandbox:hyperdrive
|
|
225
|
+
```
|
|
226
|
+
|
|
227
|
+
For Docker-based benchmark details and filtering options, see [Sandbox Benchmarks (Docker Compose)](#sandbox-benchmarks-docker-compose).
|
|
228
|
+
|
|
229
|
+
## Provider Adapters
|
|
230
|
+
|
|
231
|
+
CollegeDB can run with either native Cloudflare bindings or custom providers as long as they match the exported `KVStorage` and `SQLDatabase` interfaces.
|
|
232
|
+
|
|
233
|
+
Drizzle interop is enabled by passing a Drizzle `sql` tag as the optional second argument to `createPostgreSQLProvider`, `createMySQLProvider`, or `createSQLiteProvider`.
|
|
234
|
+
|
|
235
|
+
Supported adapters:
|
|
236
|
+
|
|
237
|
+
- `createRedisKVProvider`
|
|
238
|
+
- `createValkeyKVProvider`
|
|
239
|
+
- `createNuxtHubKVProvider`
|
|
240
|
+
- `createPostgreSQLProvider`
|
|
241
|
+
- `createMySQLProvider`
|
|
242
|
+
- `createSQLiteProvider`
|
|
243
|
+
- `createDrizzleSQLProvider` (compatibility helper)
|
|
244
|
+
- `createHyperdrivePostgresProvider`
|
|
245
|
+
- `createHyperdriveMySQLProvider`
|
|
246
|
+
|
|
247
|
+
```typescript
|
|
248
|
+
import { createClient as createRedisClient } from 'redis';
|
|
249
|
+
import { Pool } from 'pg';
|
|
250
|
+
import { createPostgreSQLProvider, createRedisKVProvider, initialize, run, type CollegeDBConfig } from '@earth-app/collegedb';
|
|
251
|
+
|
|
252
|
+
const redisClient = createRedisClient({ url: process.env.REDIS_URL });
|
|
253
|
+
const pgPool = new Pool({ connectionString: process.env.POSTGRES_URL });
|
|
254
|
+
|
|
255
|
+
const config: CollegeDBConfig = {
|
|
256
|
+
kv: createRedisKVProvider(redisClient),
|
|
257
|
+
shards: {
|
|
258
|
+
'pg-east': createPostgreSQLProvider(pgPool)
|
|
259
|
+
},
|
|
260
|
+
strategy: 'hash',
|
|
261
|
+
disableAutoMigration: true
|
|
262
|
+
};
|
|
263
|
+
|
|
264
|
+
async function bootstrap() {
|
|
265
|
+
await redisClient.connect();
|
|
266
|
+
initialize(config);
|
|
267
|
+
await run('user-1', 'INSERT INTO users (id, name) VALUES (?, ?)', ['user-1', 'Taylor']);
|
|
268
|
+
}
|
|
269
|
+
|
|
270
|
+
bootstrap().catch(console.error);
|
|
271
|
+
```
|
|
272
|
+
|
|
273
|
+
For Hyperdrive-backed SQL connections, use `createHyperdrivePostgresProvider` or `createHyperdriveMySQLProvider` with your database client factory.
|
|
274
|
+
|
|
275
|
+
### NuxtHub Runtime Example (D1 + KV)
|
|
276
|
+
|
|
277
|
+
```typescript
|
|
278
|
+
import { db } from '@nuxthub/db';
|
|
279
|
+
import { kv } from '@nuxthub/kv';
|
|
280
|
+
import { sql } from 'drizzle-orm';
|
|
281
|
+
import { createNuxtHubKVProvider, createSQLiteProvider, initialize, run, first } from '@earth-app/collegedb';
|
|
282
|
+
|
|
283
|
+
initialize({
|
|
284
|
+
kv: createNuxtHubKVProvider(kv),
|
|
285
|
+
shards: {
|
|
286
|
+
'db-primary': createSQLiteProvider(db, sql)
|
|
287
|
+
},
|
|
288
|
+
strategy: 'hash'
|
|
289
|
+
});
|
|
290
|
+
|
|
291
|
+
await run('draft:home', 'INSERT OR REPLACE INTO drafts (id, content) VALUES (?, ?)', ['draft:home', '# Home']);
|
|
292
|
+
|
|
293
|
+
const draft = await first<{ id: string; content: string }>('draft:home', 'SELECT id, content FROM drafts WHERE id = ?', ['draft:home']);
|
|
294
|
+
```
|
|
295
|
+
|
|
296
|
+
### Keep Drizzle Schema + Migrations, Route Queries with CollegeDB
|
|
297
|
+
|
|
298
|
+
CollegeDB does not replace your Drizzle schema or NuxtHub migration workflow.
|
|
299
|
+
|
|
300
|
+
```bash
|
|
301
|
+
npx nuxt db generate
|
|
302
|
+
npx nuxt db migrate
|
|
303
|
+
```
|
|
304
|
+
|
|
305
|
+
Use those migrations as-is, then route runtime reads/writes through CollegeDB adapters.
|
|
306
|
+
|
|
307
|
+
For a complete non-Cloudflare setup, see `examples/provider-sandbox.ts`.
|
|
308
|
+
|
|
309
|
+
## NuxtHub + Drizzle Recipes
|
|
310
|
+
|
|
311
|
+
### Multi-Vendor Shards (Cloudflare + Postgres/MySQL)
|
|
312
|
+
|
|
313
|
+
NuxtHub supports multiple deployment/database vendors. CollegeDB can shard across any SQL backends that Drizzle can connect to.
|
|
314
|
+
|
|
315
|
+
```typescript
|
|
316
|
+
import { sql } from 'drizzle-orm';
|
|
317
|
+
import { drizzle as drizzlePg } from 'drizzle-orm/postgres-js';
|
|
318
|
+
import { drizzle as drizzleMySQL } from 'drizzle-orm/mysql2';
|
|
319
|
+
import { drizzle as drizzleD1 } from 'drizzle-orm/d1';
|
|
320
|
+
import { kv } from '@nuxthub/kv';
|
|
321
|
+
import postgres from 'postgres';
|
|
322
|
+
import mysql from 'mysql2/promise';
|
|
323
|
+
import {
|
|
324
|
+
createMySQLProvider,
|
|
325
|
+
createNuxtHubKVProvider,
|
|
326
|
+
createPostgreSQLProvider,
|
|
327
|
+
createSQLiteProvider,
|
|
328
|
+
initialize,
|
|
329
|
+
run
|
|
330
|
+
} from '@earth-app/collegedb';
|
|
331
|
+
|
|
332
|
+
const pgClient = postgres(process.env.POSTGRES_URL!);
|
|
333
|
+
const mysqlPool = mysql.createPool(process.env.MYSQL_URL!);
|
|
334
|
+
|
|
335
|
+
function setup(env: { DB_CF: D1Database }) {
|
|
336
|
+
initialize({
|
|
337
|
+
kv: createNuxtHubKVProvider(kv),
|
|
338
|
+
shards: {
|
|
339
|
+
'db-cf': createSQLiteProvider(drizzleD1(env.DB_CF), sql),
|
|
340
|
+
'db-pg': createPostgreSQLProvider(drizzlePg(pgClient), sql),
|
|
341
|
+
'db-mysql': createMySQLProvider(drizzleMySQL(mysqlPool), sql)
|
|
342
|
+
},
|
|
343
|
+
strategy: 'hash'
|
|
344
|
+
});
|
|
345
|
+
}
|
|
346
|
+
|
|
347
|
+
export default defineEventHandler(async (event) => {
|
|
348
|
+
setup(event.context.cloudflare.env);
|
|
349
|
+
|
|
350
|
+
await run('tenant:acme:user:1', 'INSERT INTO users (id, name) VALUES (?, ?)', ['tenant:acme:user:1', 'Ada']);
|
|
351
|
+
});
|
|
352
|
+
```
|
|
353
|
+
|
|
354
|
+
### Keep NuxtHub Cache/KV Semantics Intact
|
|
355
|
+
|
|
356
|
+
Use NuxtHub KV for app cache while CollegeDB uses its own key namespace for shard mappings:
|
|
357
|
+
|
|
358
|
+
```typescript
|
|
359
|
+
import { kv } from '@nuxthub/kv';
|
|
360
|
+
import { first } from '@earth-app/collegedb';
|
|
361
|
+
|
|
362
|
+
const cacheKey = `nuxtpress:post:${slug}`;
|
|
363
|
+
const cached = await kv.get(cacheKey);
|
|
364
|
+
if (cached) return cached;
|
|
365
|
+
|
|
366
|
+
const post = await first(cacheKey, 'SELECT * FROM blog_posts WHERE slug = ? LIMIT 1', [slug]);
|
|
367
|
+
await kv.set(cacheKey, post, { ttl: 3600 });
|
|
368
|
+
```
|
|
369
|
+
|
|
370
|
+
## Sandbox Benchmarks (Docker Compose)
|
|
371
|
+
|
|
372
|
+
CollegeDB ships with an integration sandbox runner that benchmarks real latency across provider combinations.
|
|
373
|
+
|
|
374
|
+
Requirements:
|
|
375
|
+
|
|
376
|
+
- Docker + Docker Compose plugin
|
|
377
|
+
- Bun
|
|
378
|
+
- Wrangler (installed as a dev dependency and invoked by scripts)
|
|
379
|
+
|
|
380
|
+
The Cloudflare benchmark path runs against the dedicated sandbox worker:
|
|
381
|
+
|
|
382
|
+
- Worker entry: `sandbox/worker.ts`
|
|
383
|
+
- Wrangler config: `sandbox/wrangler.jsonc`
|
|
384
|
+
|
|
385
|
+
Main commands:
|
|
386
|
+
|
|
387
|
+
```bash
|
|
388
|
+
# Run full SQL x KV matrix plus Cloudflare local benchmark
|
|
389
|
+
bun run test:sandbox
|
|
390
|
+
|
|
391
|
+
# Run full SQL x KV matrix only
|
|
392
|
+
bun run test:sandbox:all
|
|
393
|
+
|
|
394
|
+
# Run Cloudflare local benchmark only (wrangler dev --local)
|
|
395
|
+
bun run test:sandbox:cloudflare
|
|
396
|
+
```
|
|
397
|
+
|
|
398
|
+
Provider filters:
|
|
399
|
+
|
|
400
|
+
```bash
|
|
401
|
+
# One SQL provider against all KV providers (native profile by default)
|
|
402
|
+
bun run test:sandbox:mysql
|
|
403
|
+
bun run test:sandbox:postgres
|
|
404
|
+
bun run test:sandbox:mariadb
|
|
405
|
+
bun run test:sandbox:sqlite
|
|
406
|
+
|
|
407
|
+
# One KV provider against all SQL providers (native profile by default)
|
|
408
|
+
bun run test:sandbox:redis
|
|
409
|
+
bun run test:sandbox:valkey
|
|
410
|
+
|
|
411
|
+
# Run all SQL x KV combinations for one adapter profile
|
|
412
|
+
bun run test:sandbox:drizzle
|
|
413
|
+
bun run test:sandbox:nuxthub
|
|
414
|
+
bun run test:sandbox:hyperdrive
|
|
415
|
+
|
|
416
|
+
# Explicit pairwise combinations
|
|
417
|
+
bun run test:sandbox:postgres+redis
|
|
418
|
+
bun run test:sandbox:postgres+valkey
|
|
419
|
+
bun run test:sandbox:mysql+redis
|
|
420
|
+
bun run test:sandbox:mysql+valkey
|
|
421
|
+
bun run test:sandbox:mariadb+redis
|
|
422
|
+
bun run test:sandbox:mariadb+valkey
|
|
423
|
+
bun run test:sandbox:sqlite+redis
|
|
424
|
+
bun run test:sandbox:sqlite+valkey
|
|
425
|
+
```
|
|
426
|
+
|
|
427
|
+
Output behavior:
|
|
428
|
+
|
|
429
|
+
- Every run writes a timestamped Markdown report to `sandbox/results/`
|
|
430
|
+
- `sandbox/results/latest.md` is always updated to the newest report
|
|
431
|
+
- The runner prints the report in-terminal using Bun's Markdown renderer with ANSI formatting
|
|
432
|
+
- `test:sandbox` includes native, drizzle, hyperdrive, and nuxthub adapter profiles across supported SQL/KV combinations plus Cloudflare profile runs
|
|
433
|
+
|
|
434
|
+
Benchmark coverage includes:
|
|
435
|
+
|
|
436
|
+
- basic CRUD
|
|
437
|
+
- advanced lookup/routing workflows
|
|
438
|
+
- migration-style mapping creation
|
|
439
|
+
- bulk CRUD
|
|
440
|
+
- indexing queries
|
|
441
|
+
- metadata fetch
|
|
442
|
+
- pragma/info queries (provider-specific)
|
|
443
|
+
- counting across shards
|
|
444
|
+
- shard fanout aggregation
|
|
445
|
+
- shard reassignment workflow
|
|
446
|
+
|
|
447
|
+
How to read benchmark rows:
|
|
448
|
+
|
|
449
|
+
- Latency cells are formatted as `average / p95` in milliseconds.
|
|
450
|
+
- `FAILED` means the scenario returned an error.
|
|
451
|
+
- `N/A` means the scenario was intentionally skipped in that environment.
|
|
452
|
+
- Use the detailed section for full `avg`, `p50`, `p95`, `min`, `max`, and sample count (`n`).
|
|
453
|
+
|
|
73
454
|
## Basic Usage
|
|
74
455
|
|
|
75
456
|
```typescript
|
|
@@ -88,7 +469,7 @@ collegedb(
|
|
|
88
469
|
},
|
|
89
470
|
async () => {
|
|
90
471
|
// Create schema on new shards only (existing shards auto-detected)
|
|
91
|
-
await createSchema(env['db-new-shard']);
|
|
472
|
+
await createSchema(env['db-new-shard'], 'CREATE TABLE IF NOT EXISTS users (id TEXT PRIMARY KEY, name TEXT, email TEXT)');
|
|
92
473
|
|
|
93
474
|
// Insert data (automatically routed to appropriate shard)
|
|
94
475
|
await run('user-123', 'INSERT INTO users (id, name, email) VALUES (?, ?, ?)', ['user-123', 'Johnson', 'alice@example.com']);
|
|
@@ -222,8 +603,6 @@ collegedb(
|
|
|
222
603
|
|
|
223
604
|
### Adding Lookup Keys to Existing Mappings
|
|
224
605
|
|
|
225
|
-
s
|
|
226
|
-
|
|
227
606
|
```typescript
|
|
228
607
|
const mapper = new KVShardMapper(env.KV);
|
|
229
608
|
|
|
@@ -529,13 +908,13 @@ for (const [table, pkColumn] of Object.entries(customIntegration)) {
|
|
|
529
908
|
}
|
|
530
909
|
```
|
|
531
910
|
|
|
532
|
-
##
|
|
911
|
+
## API Reference
|
|
533
912
|
|
|
534
913
|
| Function | Description | Parameters |
|
|
535
914
|
| ------------------------------------------ | ---------------------------------------------------------------- | -------------------------- |
|
|
536
915
|
| `collegedb(config, callback)` | Initialize CollegeDB, then run a callback | `CollegeDBConfig, () => T` |
|
|
537
916
|
| `initialize(config)` | Initialize CollegeDB with configuration | `CollegeDBConfig` |
|
|
538
|
-
| `createSchema(
|
|
917
|
+
| `createSchema(db, schema)` | Create schema on a shard database | `SQLDatabase, string` |
|
|
539
918
|
| `prepare(key, sql)` | Prepare a SQL statement for execution | `string, string` |
|
|
540
919
|
| `run(key, sql, bindings)` | Execute a SQL query with primary key routing | `string, string, any[]` |
|
|
541
920
|
| `first(key, sql, bindings)` | Execute a SQL query and return first result | `string, string, any[]` |
|
|
@@ -552,17 +931,33 @@ for (const [table, pkColumn] of Object.entries(customIntegration)) {
|
|
|
552
931
|
| `getDatabaseSizeForShard(shard)` | Get size of a specific shard in bytes | `string` |
|
|
553
932
|
| `flush()` | Clear all shard mappings (development only) | `void` |
|
|
554
933
|
|
|
934
|
+
### Provider Adapter Functions
|
|
935
|
+
|
|
936
|
+
| Function | Description | Parameters |
|
|
937
|
+
| ---------------------------------------------------------- | -------------------------------------------------------------------- | -------------------------------------------------------- |
|
|
938
|
+
| `createRedisKVProvider(client, options?)` | Adapt a Redis client to CollegeDB's `KVStorage` contract | `RedisLikeClient, { scanCount?: number }` |
|
|
939
|
+
| `createValkeyKVProvider(client, options?)` | Adapt a Valkey client to CollegeDB's `KVStorage` contract | `RedisLikeClient, { scanCount?: number }` |
|
|
940
|
+
| `createNuxtHubKVProvider(client)` | Adapt NuxtHub/Unstorage-style KV clients to `KVStorage` | `NuxtHubKVLike` |
|
|
941
|
+
| `createPostgreSQLProvider(client, sqlTag?)` | Adapt PostgreSQL or Drizzle PostgreSQL clients | `PostgresClientLike, sqlTag?` |
|
|
942
|
+
| `createMySQLProvider(client, sqlTag?)` | Adapt MySQL/MariaDB or Drizzle MySQL/MariaDB clients | `MySQLClientLike, sqlTag?` |
|
|
943
|
+
| `createSQLiteProvider(client, sqlTag?)` | Adapt SQLite/D1 or Drizzle SQLite/D1 clients | `SQLiteClientLike, sqlTag?` |
|
|
944
|
+
| `createDrizzleSQLProvider(client, sqlTag)` | Generic Drizzle adapter (optional helper) | `DrizzleClientLike, DrizzleSqlTagLike` |
|
|
945
|
+
| `createHyperdrivePostgresProvider(binding, clientFactory)` | Create a PostgreSQL `SQLDatabase` adapter using a Hyperdrive binding | `HyperdriveBindingLike, HyperdrivePostgresClientFactory` |
|
|
946
|
+
| `createHyperdriveMySQLProvider(binding, clientFactory)` | Create a MySQL `SQLDatabase` adapter using a Hyperdrive binding | `HyperdriveBindingLike, HyperdriveMySQLClientFactory` |
|
|
947
|
+
| `isKVStorage(value)` | Runtime guard for `KVStorage` | `unknown` |
|
|
948
|
+
| `isSQLDatabase(value)` | Runtime guard for `SQLDatabase` | `unknown` |
|
|
949
|
+
|
|
555
950
|
### Drop-in Replacement Functions
|
|
556
951
|
|
|
557
952
|
| Function | Description | Parameters |
|
|
558
953
|
| ----------------------------------------- | ---------------------------------------------- | ------------------------------ |
|
|
559
|
-
| `autoDetectAndMigrate(d1, shard, config)` | Automatically detect and migrate existing data | `
|
|
560
|
-
| `checkMigrationNeeded(d1, shard, config)` | Check if database needs migration | `
|
|
561
|
-
| `validateTableForSharding(d1, table)` | Check if table is suitable for sharding | `
|
|
562
|
-
| `discoverExistingPrimaryKeys(d1, table)` | Find all primary keys in existing table | `
|
|
563
|
-
| `integrateExistingDatabase(d1, shard)` | Complete drop-in integration of existing DB | `
|
|
954
|
+
| `autoDetectAndMigrate(d1, shard, config)` | Automatically detect and migrate existing data | `SQLDatabase, string, config` |
|
|
955
|
+
| `checkMigrationNeeded(d1, shard, config)` | Check if database needs migration | `SQLDatabase, string, config` |
|
|
956
|
+
| `validateTableForSharding(d1, table)` | Check if table is suitable for sharding | `SQLDatabase, string` |
|
|
957
|
+
| `discoverExistingPrimaryKeys(d1, table)` | Find all primary keys in existing table | `SQLDatabase, string` |
|
|
958
|
+
| `integrateExistingDatabase(d1, shard)` | Complete drop-in integration of existing DB | `SQLDatabase, string, mapper` |
|
|
564
959
|
| `createMappingsForExistingKeys(keys)` | Create shard mappings for existing keys | `string[], string[], strategy` |
|
|
565
|
-
| `listTables(d1)` | Get list of tables in database | `
|
|
960
|
+
| `listTables(d1)` | Get list of tables in database | `SQLDatabase` |
|
|
566
961
|
| `clearMigrationCache()` | Clear automatic migration cache | `void` |
|
|
567
962
|
|
|
568
963
|
### Error Handling
|
|
@@ -645,15 +1040,19 @@ The main configuration interface supports both single strategies and mixed strat
|
|
|
645
1040
|
|
|
646
1041
|
```typescript
|
|
647
1042
|
interface CollegeDBConfig {
|
|
648
|
-
kv:
|
|
1043
|
+
kv: KVStorage;
|
|
649
1044
|
coordinator?: DurableObjectNamespace;
|
|
650
|
-
shards: Record<string,
|
|
1045
|
+
shards: Record<string, SQLDatabase>;
|
|
651
1046
|
strategy?: ShardingStrategy | MixedShardingStrategy;
|
|
652
1047
|
targetRegion?: D1Region;
|
|
653
1048
|
shardLocations?: Record<string, ShardLocation>;
|
|
654
1049
|
disableAutoMigration?: boolean; // Default: false
|
|
655
1050
|
hashShardMappings?: boolean; // Default: true
|
|
656
1051
|
maxDatabaseSize?: number; // Default: undefined (no limit)
|
|
1052
|
+
mappingCacheTtlMs?: number; // Default: 30000
|
|
1053
|
+
knownShardsCacheTtlMs?: number; // Default: 10000
|
|
1054
|
+
sizeCacheTtlMs?: number; // Default: 30000
|
|
1055
|
+
migrationConcurrency?: number; // Default: 25
|
|
657
1056
|
}
|
|
658
1057
|
```
|
|
659
1058
|
|
|
@@ -706,7 +1105,7 @@ const mixedStrategyConfig: CollegeDBConfig = {
|
|
|
706
1105
|
|
|
707
1106
|
### Database Size Management
|
|
708
1107
|
|
|
709
|
-
CollegeDB supports automatic size-based shard exclusion to prevent individual shards from becoming too large. This feature helps maintain optimal performance and prevents hitting
|
|
1108
|
+
CollegeDB supports automatic size-based shard exclusion to prevent individual shards from becoming too large. This feature helps maintain optimal performance and prevents hitting database storage limits.
|
|
710
1109
|
|
|
711
1110
|
#### Configuration
|
|
712
1111
|
|
|
@@ -782,12 +1181,12 @@ const config: CollegeDBConfig = {
|
|
|
782
1181
|
// "Excluded 2 shards due to size limits: db-east, db-central"
|
|
783
1182
|
```
|
|
784
1183
|
|
|
785
|
-
#### Performance Impact
|
|
1184
|
+
#### Size-Limit Performance Impact
|
|
786
1185
|
|
|
787
1186
|
- **Size Check Frequency**: Only performed during new allocations (not on reads)
|
|
788
1187
|
- **Query Efficiency**: Uses fast SQLite pragmas (microsecond execution time)
|
|
789
1188
|
- **Parallel Execution**: Size checks run concurrently across all shards
|
|
790
|
-
- **Caching**:
|
|
1189
|
+
- **Caching**: Size checks are cached in-memory (controlled by `sizeCacheTtlMs`, default `30000`)
|
|
791
1190
|
|
|
792
1191
|
### Types
|
|
793
1192
|
|
|
@@ -796,6 +1195,13 @@ CollegeDB exports TypeScript types for better development experience and type sa
|
|
|
796
1195
|
| Type | Description | Example |
|
|
797
1196
|
| ----------------------- | ------------------------------ | --------------------------------------------------- |
|
|
798
1197
|
| `CollegeDBConfig` | Main configuration object | `{ kv, shards, strategy }` |
|
|
1198
|
+
| `KVStorage` | Provider-agnostic KV contract | `createRedisKVProvider(redisClient)` |
|
|
1199
|
+
| `SQLDatabase` | Provider-agnostic SQL contract | `createPostgreSQLProvider(pgPool)` |
|
|
1200
|
+
| `NuxtHubKVLike` | NuxtHub/Unstorage KV contract | `createNuxtHubKVProvider(kv)` |
|
|
1201
|
+
| `DrizzleClientLike` | Minimal Drizzle DB contract | `createPostgreSQLProvider(drizzleDb, sql)` |
|
|
1202
|
+
| `DrizzleSqlTagLike` | Drizzle SQL tag contract | `createSQLiteProvider(drizzleDb, sql)` |
|
|
1203
|
+
| `QueryResult` | Standard query response shape | `{ success, results, meta }` |
|
|
1204
|
+
| `QueryResultMeta` | Query execution metadata | `{ duration, changes?, last_row_id? }` |
|
|
799
1205
|
| `ShardingStrategy` | Single strategy options | `'hash' \| 'location' \| 'round-robin' \| 'random'` |
|
|
800
1206
|
| `MixedShardingStrategy` | Mixed strategy configuration | `{ read: 'hash', write: 'location' }` |
|
|
801
1207
|
| `OperationType` | Database operation types | `'read' \| 'write'` |
|
|
@@ -829,7 +1235,7 @@ const config: CollegeDBConfig = {
|
|
|
829
1235
|
};
|
|
830
1236
|
```
|
|
831
1237
|
|
|
832
|
-
##
|
|
1238
|
+
## Architecture
|
|
833
1239
|
|
|
834
1240
|
```txt
|
|
835
1241
|
┌─────────────────────────────────────────────────────────────┐
|
|
@@ -900,7 +1306,7 @@ const config: CollegeDBConfig = {
|
|
|
900
1306
|
- **Random**: Random shard selection for load balancing
|
|
901
1307
|
- **Location**: Geographic proximity-based allocation for optimal latency
|
|
902
1308
|
|
|
903
|
-
##
|
|
1309
|
+
## Cloudflare Setup
|
|
904
1310
|
|
|
905
1311
|
### 1. Create D1 Databases
|
|
906
1312
|
|
|
@@ -918,81 +1324,127 @@ wrangler d1 create collegedb-central
|
|
|
918
1324
|
wrangler kv namespace create "KV"
|
|
919
1325
|
```
|
|
920
1326
|
|
|
921
|
-
### 3. Configure wrangler.
|
|
922
|
-
|
|
923
|
-
```toml
|
|
924
|
-
[[d1_databases]]
|
|
925
|
-
binding = "db-east"
|
|
926
|
-
database_name = "collegedb-east"
|
|
927
|
-
database_id = "your-database-id"
|
|
1327
|
+
### 3. Configure wrangler.jsonc
|
|
928
1328
|
|
|
929
|
-
|
|
930
|
-
|
|
931
|
-
|
|
932
|
-
|
|
933
|
-
|
|
934
|
-
|
|
935
|
-
|
|
936
|
-
|
|
937
|
-
|
|
938
|
-
|
|
939
|
-
|
|
940
|
-
|
|
1329
|
+
```jsonc
|
|
1330
|
+
{
|
|
1331
|
+
"$schema": "./node_modules/wrangler/config-schema.json",
|
|
1332
|
+
"name": "collegedb-app",
|
|
1333
|
+
"main": "src/index.ts",
|
|
1334
|
+
"compatibility_date": "2026-04-15",
|
|
1335
|
+
"d1_databases": [
|
|
1336
|
+
{
|
|
1337
|
+
"binding": "db-east",
|
|
1338
|
+
"database_name": "collegedb-east",
|
|
1339
|
+
"database_id": "your-east-database-id"
|
|
1340
|
+
},
|
|
1341
|
+
{
|
|
1342
|
+
"binding": "db-west",
|
|
1343
|
+
"database_name": "collegedb-west",
|
|
1344
|
+
"database_id": "your-west-database-id"
|
|
1345
|
+
}
|
|
1346
|
+
],
|
|
1347
|
+
"kv_namespaces": [
|
|
1348
|
+
{
|
|
1349
|
+
"binding": "KV",
|
|
1350
|
+
"id": "your-kv-namespace-id",
|
|
1351
|
+
"preview_id": "your-kv-preview-id"
|
|
1352
|
+
}
|
|
1353
|
+
],
|
|
1354
|
+
"durable_objects": {
|
|
1355
|
+
"bindings": [
|
|
1356
|
+
{
|
|
1357
|
+
"name": "ShardCoordinator",
|
|
1358
|
+
"class_name": "ShardCoordinator"
|
|
1359
|
+
}
|
|
1360
|
+
]
|
|
1361
|
+
},
|
|
1362
|
+
"migrations": [
|
|
1363
|
+
{
|
|
1364
|
+
"tag": "v1",
|
|
1365
|
+
"new_sqlite_classes": ["ShardCoordinator"]
|
|
1366
|
+
}
|
|
1367
|
+
]
|
|
1368
|
+
}
|
|
941
1369
|
```
|
|
942
1370
|
|
|
943
|
-
#### Complete wrangler.
|
|
1371
|
+
#### Complete wrangler.jsonc with ShardCoordinator
|
|
944
1372
|
|
|
945
|
-
```
|
|
946
|
-
|
|
947
|
-
|
|
948
|
-
|
|
949
|
-
|
|
950
|
-
|
|
951
|
-
[
|
|
952
|
-
|
|
953
|
-
|
|
954
|
-
|
|
955
|
-
|
|
956
|
-
|
|
957
|
-
|
|
958
|
-
|
|
959
|
-
|
|
960
|
-
|
|
961
|
-
|
|
962
|
-
|
|
963
|
-
|
|
964
|
-
|
|
965
|
-
|
|
966
|
-
|
|
967
|
-
|
|
968
|
-
|
|
969
|
-
|
|
970
|
-
|
|
971
|
-
|
|
972
|
-
|
|
973
|
-
|
|
974
|
-
|
|
975
|
-
|
|
976
|
-
|
|
977
|
-
|
|
978
|
-
|
|
979
|
-
|
|
980
|
-
|
|
981
|
-
|
|
982
|
-
|
|
983
|
-
|
|
984
|
-
|
|
985
|
-
|
|
986
|
-
|
|
987
|
-
|
|
988
|
-
|
|
989
|
-
|
|
990
|
-
|
|
991
|
-
|
|
992
|
-
|
|
993
|
-
|
|
994
|
-
|
|
995
|
-
|
|
1373
|
+
```jsonc
|
|
1374
|
+
{
|
|
1375
|
+
"$schema": "./node_modules/wrangler/config-schema.json",
|
|
1376
|
+
"name": "collegedb-app",
|
|
1377
|
+
"main": "src/index.ts",
|
|
1378
|
+
"compatibility_date": "2026-04-15",
|
|
1379
|
+
"d1_databases": [
|
|
1380
|
+
{
|
|
1381
|
+
"binding": "db-east",
|
|
1382
|
+
"database_name": "collegedb-east",
|
|
1383
|
+
"database_id": "your-east-database-id"
|
|
1384
|
+
},
|
|
1385
|
+
{
|
|
1386
|
+
"binding": "db-west",
|
|
1387
|
+
"database_name": "collegedb-west",
|
|
1388
|
+
"database_id": "your-west-database-id"
|
|
1389
|
+
},
|
|
1390
|
+
{
|
|
1391
|
+
"binding": "db-central",
|
|
1392
|
+
"database_name": "collegedb-central",
|
|
1393
|
+
"database_id": "your-central-database-id"
|
|
1394
|
+
}
|
|
1395
|
+
],
|
|
1396
|
+
"kv_namespaces": [
|
|
1397
|
+
{
|
|
1398
|
+
"binding": "KV",
|
|
1399
|
+
"id": "your-kv-namespace-id",
|
|
1400
|
+
"preview_id": "your-kv-preview-id"
|
|
1401
|
+
}
|
|
1402
|
+
],
|
|
1403
|
+
"durable_objects": {
|
|
1404
|
+
"bindings": [
|
|
1405
|
+
{
|
|
1406
|
+
"name": "ShardCoordinator",
|
|
1407
|
+
"class_name": "ShardCoordinator"
|
|
1408
|
+
}
|
|
1409
|
+
]
|
|
1410
|
+
},
|
|
1411
|
+
"migrations": [
|
|
1412
|
+
{
|
|
1413
|
+
"tag": "v1",
|
|
1414
|
+
"new_sqlite_classes": ["ShardCoordinator"]
|
|
1415
|
+
}
|
|
1416
|
+
],
|
|
1417
|
+
"env": {
|
|
1418
|
+
"production": {
|
|
1419
|
+
"d1_databases": [
|
|
1420
|
+
{
|
|
1421
|
+
"binding": "db-east",
|
|
1422
|
+
"database_name": "collegedb-prod-east",
|
|
1423
|
+
"database_id": "your-prod-east-id"
|
|
1424
|
+
},
|
|
1425
|
+
{
|
|
1426
|
+
"binding": "db-west",
|
|
1427
|
+
"database_name": "collegedb-prod-west",
|
|
1428
|
+
"database_id": "your-prod-west-id"
|
|
1429
|
+
}
|
|
1430
|
+
],
|
|
1431
|
+
"kv_namespaces": [
|
|
1432
|
+
{
|
|
1433
|
+
"binding": "KV",
|
|
1434
|
+
"id": "your-prod-kv-namespace-id"
|
|
1435
|
+
}
|
|
1436
|
+
],
|
|
1437
|
+
"durable_objects": {
|
|
1438
|
+
"bindings": [
|
|
1439
|
+
{
|
|
1440
|
+
"name": "ShardCoordinator",
|
|
1441
|
+
"class_name": "ShardCoordinator"
|
|
1442
|
+
}
|
|
1443
|
+
]
|
|
1444
|
+
}
|
|
1445
|
+
}
|
|
1446
|
+
}
|
|
1447
|
+
}
|
|
996
1448
|
```
|
|
997
1449
|
|
|
998
1450
|
### 3.1. Worker Script Setup (Required for ShardCoordinator)
|
|
@@ -1058,7 +1510,7 @@ wrangler deploy
|
|
|
1058
1510
|
wrangler deploy --env production
|
|
1059
1511
|
```
|
|
1060
1512
|
|
|
1061
|
-
##
|
|
1513
|
+
## Monitoring and Maintenance
|
|
1062
1514
|
|
|
1063
1515
|
### Shard Statistics
|
|
1064
1516
|
|
|
@@ -1342,7 +1794,7 @@ export default {
|
|
|
1342
1794
|
};
|
|
1343
1795
|
```
|
|
1344
1796
|
|
|
1345
|
-
##
|
|
1797
|
+
## Performance Analysis
|
|
1346
1798
|
|
|
1347
1799
|
### Scaling Performance Comparison
|
|
1348
1800
|
|
|
@@ -1732,7 +2184,7 @@ initialize({
|
|
|
1732
2184
|
- Cost-sensitive deployments at small scale
|
|
1733
2185
|
- **Single-strategy applications** where reads and writes have identical performance needs
|
|
1734
2186
|
|
|
1735
|
-
##
|
|
2187
|
+
## Advanced Configuration
|
|
1736
2188
|
|
|
1737
2189
|
### Custom Allocation Strategy
|
|
1738
2190
|
|
|
@@ -1762,19 +2214,25 @@ CollegeDB includes an optional **ShardCoordinator** Durable Object that provides
|
|
|
1762
2214
|
|
|
1763
2215
|
#### Durable Object Setup
|
|
1764
2216
|
|
|
1765
|
-
First, configure the Durable Object in your `wrangler.
|
|
2217
|
+
First, configure the Durable Object in your `wrangler.jsonc`:
|
|
1766
2218
|
|
|
1767
|
-
```
|
|
1768
|
-
|
|
1769
|
-
|
|
1770
|
-
|
|
1771
|
-
|
|
1772
|
-
|
|
1773
|
-
|
|
1774
|
-
|
|
1775
|
-
|
|
1776
|
-
|
|
1777
|
-
|
|
2219
|
+
```jsonc
|
|
2220
|
+
{
|
|
2221
|
+
"durable_objects": {
|
|
2222
|
+
"bindings": [
|
|
2223
|
+
{
|
|
2224
|
+
"name": "ShardCoordinator",
|
|
2225
|
+
"class_name": "ShardCoordinator"
|
|
2226
|
+
}
|
|
2227
|
+
]
|
|
2228
|
+
},
|
|
2229
|
+
"migrations": [
|
|
2230
|
+
{
|
|
2231
|
+
"tag": "v1",
|
|
2232
|
+
"new_sqlite_classes": ["ShardCoordinator"]
|
|
2233
|
+
}
|
|
2234
|
+
]
|
|
2235
|
+
}
|
|
1778
2236
|
```
|
|
1779
2237
|
|
|
1780
2238
|
#### Basic Usage with ShardCoordinator
|
|
@@ -2043,7 +2501,7 @@ async function allocateWithFallback(coordinator: DurableObjectNamespace, primary
|
|
|
2043
2501
|
}
|
|
2044
2502
|
```
|
|
2045
2503
|
|
|
2046
|
-
##
|
|
2504
|
+
## Quick Reference
|
|
2047
2505
|
|
|
2048
2506
|
### Strategy Selection Guide
|
|
2049
2507
|
|
|
@@ -2161,7 +2619,7 @@ async function allocateWithFallback(coordinator: DurableObjectNamespace, primary
|
|
|
2161
2619
|
| `me` | Middle East | Dubai |
|
|
2162
2620
|
| `af` | Africa | Johannesburg |
|
|
2163
2621
|
|
|
2164
|
-
##
|
|
2622
|
+
## Contributing
|
|
2165
2623
|
|
|
2166
2624
|
1. Fork the repository
|
|
2167
2625
|
2. Create a feature branch: `git checkout -b feature/amazing-feature`
|
|
@@ -2169,18 +2627,18 @@ async function allocateWithFallback(coordinator: DurableObjectNamespace, primary
|
|
|
2169
2627
|
4. Push to branch: `git push origin feature/amazing-feature`
|
|
2170
2628
|
5. Submit a pull request
|
|
2171
2629
|
|
|
2172
|
-
##
|
|
2630
|
+
## License
|
|
2173
2631
|
|
|
2174
2632
|
This project is licensed under the MIT License - see the [LICENSE](LICENSE) file for details.
|
|
2175
2633
|
|
|
2176
|
-
##
|
|
2634
|
+
## Links
|
|
2177
2635
|
|
|
2178
2636
|
- [Cloudflare D1 Documentation](https://developers.cloudflare.com/d1/)
|
|
2179
2637
|
- [Cloudflare KV Documentation](https://developers.cloudflare.com/kv/)
|
|
2180
2638
|
- [Cloudflare Workers Documentation](https://developers.cloudflare.com/workers/)
|
|
2181
2639
|
- [Durable Objects Documentation](https://developers.cloudflare.com/durable-objects/)
|
|
2182
2640
|
|
|
2183
|
-
##
|
|
2641
|
+
## Support
|
|
2184
2642
|
|
|
2185
2643
|
- 📖 [Documentation](https://earth-app.github.io/CollegeDB)
|
|
2186
2644
|
- 🐛 [Report Issues](https://github.com/earth-app/CollegeDB/issues)
|