@lenso/limits 0.0.0-stage → 0.2.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.
@@ -0,0 +1,426 @@
1
+ import type { BunSQLiteDatabase } from "drizzle-orm/bun-sqlite";
2
+ import { type CounterKind, type LimitStore, type Lease } from "./contracts";
3
+ export declare const counters: import("drizzle-orm/sqlite-core").SQLiteTableWithColumns<{
4
+ name: "lenso_limit_counters";
5
+ schema: undefined;
6
+ columns: {
7
+ scope: import("drizzle-orm/sqlite-core").SQLiteColumn<{
8
+ name: "scope";
9
+ tableName: "lenso_limit_counters";
10
+ dataType: "string";
11
+ columnType: "SQLiteText";
12
+ data: string;
13
+ driverParam: string;
14
+ notNull: true;
15
+ hasDefault: false;
16
+ isPrimaryKey: false;
17
+ isAutoincrement: false;
18
+ hasRuntimeDefault: false;
19
+ enumValues: [string, ...string[]];
20
+ baseColumn: never;
21
+ identity: undefined;
22
+ generated: undefined;
23
+ }, {}, {
24
+ length: number | undefined;
25
+ }>;
26
+ kind: import("drizzle-orm/sqlite-core").SQLiteColumn<{
27
+ name: "kind";
28
+ tableName: "lenso_limit_counters";
29
+ dataType: "string";
30
+ columnType: "SQLiteText";
31
+ data: CounterKind;
32
+ driverParam: string;
33
+ notNull: true;
34
+ hasDefault: false;
35
+ isPrimaryKey: false;
36
+ isAutoincrement: false;
37
+ hasRuntimeDefault: false;
38
+ enumValues: [string, ...string[]];
39
+ baseColumn: never;
40
+ identity: undefined;
41
+ generated: undefined;
42
+ }, {}, {
43
+ length: number | undefined;
44
+ $type: CounterKind;
45
+ }>;
46
+ capacity: import("drizzle-orm/sqlite-core").SQLiteColumn<{
47
+ name: "capacity";
48
+ tableName: "lenso_limit_counters";
49
+ dataType: "number";
50
+ columnType: "SQLiteInteger";
51
+ data: number;
52
+ driverParam: number;
53
+ notNull: true;
54
+ hasDefault: false;
55
+ isPrimaryKey: false;
56
+ isAutoincrement: false;
57
+ hasRuntimeDefault: false;
58
+ enumValues: undefined;
59
+ baseColumn: never;
60
+ identity: undefined;
61
+ generated: undefined;
62
+ }, {}, {}>;
63
+ periodMs: import("drizzle-orm/sqlite-core").SQLiteColumn<{
64
+ name: "period_ms";
65
+ tableName: "lenso_limit_counters";
66
+ dataType: "number";
67
+ columnType: "SQLiteInteger";
68
+ data: number;
69
+ driverParam: number;
70
+ notNull: true;
71
+ hasDefault: false;
72
+ isPrimaryKey: false;
73
+ isAutoincrement: false;
74
+ hasRuntimeDefault: false;
75
+ enumValues: undefined;
76
+ baseColumn: never;
77
+ identity: undefined;
78
+ generated: undefined;
79
+ }, {}, {}>;
80
+ windowStart: import("drizzle-orm/sqlite-core").SQLiteColumn<{
81
+ name: "window_start";
82
+ tableName: "lenso_limit_counters";
83
+ dataType: "number";
84
+ columnType: "SQLiteInteger";
85
+ data: number;
86
+ driverParam: number;
87
+ notNull: true;
88
+ hasDefault: false;
89
+ isPrimaryKey: false;
90
+ isAutoincrement: false;
91
+ hasRuntimeDefault: false;
92
+ enumValues: undefined;
93
+ baseColumn: never;
94
+ identity: undefined;
95
+ generated: undefined;
96
+ }, {}, {}>;
97
+ used: import("drizzle-orm/sqlite-core").SQLiteColumn<{
98
+ name: "used";
99
+ tableName: "lenso_limit_counters";
100
+ dataType: "number";
101
+ columnType: "SQLiteInteger";
102
+ data: number;
103
+ driverParam: number;
104
+ notNull: true;
105
+ hasDefault: false;
106
+ isPrimaryKey: false;
107
+ isAutoincrement: false;
108
+ hasRuntimeDefault: false;
109
+ enumValues: undefined;
110
+ baseColumn: never;
111
+ identity: undefined;
112
+ generated: undefined;
113
+ }, {}, {}>;
114
+ lastNow: import("drizzle-orm/sqlite-core").SQLiteColumn<{
115
+ name: "last_now";
116
+ tableName: "lenso_limit_counters";
117
+ dataType: "number";
118
+ columnType: "SQLiteInteger";
119
+ data: number;
120
+ driverParam: number;
121
+ notNull: true;
122
+ hasDefault: false;
123
+ isPrimaryKey: false;
124
+ isAutoincrement: false;
125
+ hasRuntimeDefault: false;
126
+ enumValues: undefined;
127
+ baseColumn: never;
128
+ identity: undefined;
129
+ generated: undefined;
130
+ }, {}, {}>;
131
+ };
132
+ dialect: 'sqlite';
133
+ }>;
134
+ export declare const concurrencyBuckets: import("drizzle-orm/sqlite-core").SQLiteTableWithColumns<{
135
+ name: "lenso_limit_concurrency";
136
+ schema: undefined;
137
+ columns: {
138
+ scope: import("drizzle-orm/sqlite-core").SQLiteColumn<{
139
+ name: "scope";
140
+ tableName: "lenso_limit_concurrency";
141
+ dataType: "string";
142
+ columnType: "SQLiteText";
143
+ data: string;
144
+ driverParam: string;
145
+ notNull: true;
146
+ hasDefault: false;
147
+ isPrimaryKey: true;
148
+ isAutoincrement: false;
149
+ hasRuntimeDefault: false;
150
+ enumValues: [string, ...string[]];
151
+ baseColumn: never;
152
+ identity: undefined;
153
+ generated: undefined;
154
+ }, {}, {
155
+ length: number | undefined;
156
+ }>;
157
+ capacity: import("drizzle-orm/sqlite-core").SQLiteColumn<{
158
+ name: "capacity";
159
+ tableName: "lenso_limit_concurrency";
160
+ dataType: "number";
161
+ columnType: "SQLiteInteger";
162
+ data: number;
163
+ driverParam: number;
164
+ notNull: true;
165
+ hasDefault: false;
166
+ isPrimaryKey: false;
167
+ isAutoincrement: false;
168
+ hasRuntimeDefault: false;
169
+ enumValues: undefined;
170
+ baseColumn: never;
171
+ identity: undefined;
172
+ generated: undefined;
173
+ }, {}, {}>;
174
+ lastNow: import("drizzle-orm/sqlite-core").SQLiteColumn<{
175
+ name: "last_now";
176
+ tableName: "lenso_limit_concurrency";
177
+ dataType: "number";
178
+ columnType: "SQLiteInteger";
179
+ data: number;
180
+ driverParam: number;
181
+ notNull: true;
182
+ hasDefault: false;
183
+ isPrimaryKey: false;
184
+ isAutoincrement: false;
185
+ hasRuntimeDefault: false;
186
+ enumValues: undefined;
187
+ baseColumn: never;
188
+ identity: undefined;
189
+ generated: undefined;
190
+ }, {}, {}>;
191
+ leases: import("drizzle-orm/sqlite-core").SQLiteColumn<{
192
+ name: "leases";
193
+ tableName: "lenso_limit_concurrency";
194
+ dataType: "json";
195
+ columnType: "SQLiteTextJson";
196
+ data: Lease[];
197
+ driverParam: string;
198
+ notNull: true;
199
+ hasDefault: false;
200
+ isPrimaryKey: false;
201
+ isAutoincrement: false;
202
+ hasRuntimeDefault: false;
203
+ enumValues: undefined;
204
+ baseColumn: never;
205
+ identity: undefined;
206
+ generated: undefined;
207
+ }, {}, {
208
+ $type: Lease[];
209
+ }>;
210
+ };
211
+ dialect: 'sqlite';
212
+ }>;
213
+ export declare const limitSchema: {
214
+ counters: import("drizzle-orm/sqlite-core").SQLiteTableWithColumns<{
215
+ name: "lenso_limit_counters";
216
+ schema: undefined;
217
+ columns: {
218
+ scope: import("drizzle-orm/sqlite-core").SQLiteColumn<{
219
+ name: "scope";
220
+ tableName: "lenso_limit_counters";
221
+ dataType: "string";
222
+ columnType: "SQLiteText";
223
+ data: string;
224
+ driverParam: string;
225
+ notNull: true;
226
+ hasDefault: false;
227
+ isPrimaryKey: false;
228
+ isAutoincrement: false;
229
+ hasRuntimeDefault: false;
230
+ enumValues: [string, ...string[]];
231
+ baseColumn: never;
232
+ identity: undefined;
233
+ generated: undefined;
234
+ }, {}, {
235
+ length: number | undefined;
236
+ }>;
237
+ kind: import("drizzle-orm/sqlite-core").SQLiteColumn<{
238
+ name: "kind";
239
+ tableName: "lenso_limit_counters";
240
+ dataType: "string";
241
+ columnType: "SQLiteText";
242
+ data: CounterKind;
243
+ driverParam: string;
244
+ notNull: true;
245
+ hasDefault: false;
246
+ isPrimaryKey: false;
247
+ isAutoincrement: false;
248
+ hasRuntimeDefault: false;
249
+ enumValues: [string, ...string[]];
250
+ baseColumn: never;
251
+ identity: undefined;
252
+ generated: undefined;
253
+ }, {}, {
254
+ length: number | undefined;
255
+ $type: CounterKind;
256
+ }>;
257
+ capacity: import("drizzle-orm/sqlite-core").SQLiteColumn<{
258
+ name: "capacity";
259
+ tableName: "lenso_limit_counters";
260
+ dataType: "number";
261
+ columnType: "SQLiteInteger";
262
+ data: number;
263
+ driverParam: number;
264
+ notNull: true;
265
+ hasDefault: false;
266
+ isPrimaryKey: false;
267
+ isAutoincrement: false;
268
+ hasRuntimeDefault: false;
269
+ enumValues: undefined;
270
+ baseColumn: never;
271
+ identity: undefined;
272
+ generated: undefined;
273
+ }, {}, {}>;
274
+ periodMs: import("drizzle-orm/sqlite-core").SQLiteColumn<{
275
+ name: "period_ms";
276
+ tableName: "lenso_limit_counters";
277
+ dataType: "number";
278
+ columnType: "SQLiteInteger";
279
+ data: number;
280
+ driverParam: number;
281
+ notNull: true;
282
+ hasDefault: false;
283
+ isPrimaryKey: false;
284
+ isAutoincrement: false;
285
+ hasRuntimeDefault: false;
286
+ enumValues: undefined;
287
+ baseColumn: never;
288
+ identity: undefined;
289
+ generated: undefined;
290
+ }, {}, {}>;
291
+ windowStart: import("drizzle-orm/sqlite-core").SQLiteColumn<{
292
+ name: "window_start";
293
+ tableName: "lenso_limit_counters";
294
+ dataType: "number";
295
+ columnType: "SQLiteInteger";
296
+ data: number;
297
+ driverParam: number;
298
+ notNull: true;
299
+ hasDefault: false;
300
+ isPrimaryKey: false;
301
+ isAutoincrement: false;
302
+ hasRuntimeDefault: false;
303
+ enumValues: undefined;
304
+ baseColumn: never;
305
+ identity: undefined;
306
+ generated: undefined;
307
+ }, {}, {}>;
308
+ used: import("drizzle-orm/sqlite-core").SQLiteColumn<{
309
+ name: "used";
310
+ tableName: "lenso_limit_counters";
311
+ dataType: "number";
312
+ columnType: "SQLiteInteger";
313
+ data: number;
314
+ driverParam: number;
315
+ notNull: true;
316
+ hasDefault: false;
317
+ isPrimaryKey: false;
318
+ isAutoincrement: false;
319
+ hasRuntimeDefault: false;
320
+ enumValues: undefined;
321
+ baseColumn: never;
322
+ identity: undefined;
323
+ generated: undefined;
324
+ }, {}, {}>;
325
+ lastNow: import("drizzle-orm/sqlite-core").SQLiteColumn<{
326
+ name: "last_now";
327
+ tableName: "lenso_limit_counters";
328
+ dataType: "number";
329
+ columnType: "SQLiteInteger";
330
+ data: number;
331
+ driverParam: number;
332
+ notNull: true;
333
+ hasDefault: false;
334
+ isPrimaryKey: false;
335
+ isAutoincrement: false;
336
+ hasRuntimeDefault: false;
337
+ enumValues: undefined;
338
+ baseColumn: never;
339
+ identity: undefined;
340
+ generated: undefined;
341
+ }, {}, {}>;
342
+ };
343
+ dialect: 'sqlite';
344
+ }>;
345
+ concurrencyBuckets: import("drizzle-orm/sqlite-core").SQLiteTableWithColumns<{
346
+ name: "lenso_limit_concurrency";
347
+ schema: undefined;
348
+ columns: {
349
+ scope: import("drizzle-orm/sqlite-core").SQLiteColumn<{
350
+ name: "scope";
351
+ tableName: "lenso_limit_concurrency";
352
+ dataType: "string";
353
+ columnType: "SQLiteText";
354
+ data: string;
355
+ driverParam: string;
356
+ notNull: true;
357
+ hasDefault: false;
358
+ isPrimaryKey: true;
359
+ isAutoincrement: false;
360
+ hasRuntimeDefault: false;
361
+ enumValues: [string, ...string[]];
362
+ baseColumn: never;
363
+ identity: undefined;
364
+ generated: undefined;
365
+ }, {}, {
366
+ length: number | undefined;
367
+ }>;
368
+ capacity: import("drizzle-orm/sqlite-core").SQLiteColumn<{
369
+ name: "capacity";
370
+ tableName: "lenso_limit_concurrency";
371
+ dataType: "number";
372
+ columnType: "SQLiteInteger";
373
+ data: number;
374
+ driverParam: number;
375
+ notNull: true;
376
+ hasDefault: false;
377
+ isPrimaryKey: false;
378
+ isAutoincrement: false;
379
+ hasRuntimeDefault: false;
380
+ enumValues: undefined;
381
+ baseColumn: never;
382
+ identity: undefined;
383
+ generated: undefined;
384
+ }, {}, {}>;
385
+ lastNow: import("drizzle-orm/sqlite-core").SQLiteColumn<{
386
+ name: "last_now";
387
+ tableName: "lenso_limit_concurrency";
388
+ dataType: "number";
389
+ columnType: "SQLiteInteger";
390
+ data: number;
391
+ driverParam: number;
392
+ notNull: true;
393
+ hasDefault: false;
394
+ isPrimaryKey: false;
395
+ isAutoincrement: false;
396
+ hasRuntimeDefault: false;
397
+ enumValues: undefined;
398
+ baseColumn: never;
399
+ identity: undefined;
400
+ generated: undefined;
401
+ }, {}, {}>;
402
+ leases: import("drizzle-orm/sqlite-core").SQLiteColumn<{
403
+ name: "leases";
404
+ tableName: "lenso_limit_concurrency";
405
+ dataType: "json";
406
+ columnType: "SQLiteTextJson";
407
+ data: Lease[];
408
+ driverParam: string;
409
+ notNull: true;
410
+ hasDefault: false;
411
+ isPrimaryKey: false;
412
+ isAutoincrement: false;
413
+ hasRuntimeDefault: false;
414
+ enumValues: undefined;
415
+ baseColumn: never;
416
+ identity: undefined;
417
+ generated: undefined;
418
+ }, {}, {
419
+ $type: Lease[];
420
+ }>;
421
+ };
422
+ dialect: 'sqlite';
423
+ }>;
424
+ };
425
+ /** Bun SQLite only. The caller owns the database, busy handling, and explicit migrations. */
426
+ export declare function createSqliteLimitStore<TSchema extends Record<string, unknown>>(db: BunSQLiteDatabase<TSchema>): LimitStore;
package/dist/sqlite.js ADDED
@@ -0,0 +1,107 @@
1
+ import {
2
+ maxDurationMs,
3
+ positiveInteger,
4
+ scopeKey,
5
+ validateConsume,
6
+ validateAcquire,
7
+ validateToken,
8
+ validateKind,
9
+ consumeState,
10
+ liveState,
11
+ acquireState,
12
+ renewState
13
+ } from "./index-bz4qnpx8.js";
14
+
15
+ // src/sqlite.ts
16
+ import { and, eq, sql } from "drizzle-orm";
17
+ import { check, integer, primaryKey, sqliteTable, text } from "drizzle-orm/sqlite-core";
18
+ var counters = sqliteTable("lenso_limit_counters", {
19
+ scope: text("scope").notNull(),
20
+ kind: text("kind").$type().notNull(),
21
+ capacity: integer("capacity").notNull(),
22
+ periodMs: integer("period_ms").notNull(),
23
+ windowStart: integer("window_start").notNull(),
24
+ used: integer("used").notNull(),
25
+ lastNow: integer("last_now").notNull()
26
+ }, (table) => [
27
+ primaryKey({ columns: [table.scope, table.kind], name: "lenso_limit_counters_pk" }),
28
+ check("lenso_limit_counter_kind", sql`${table.kind} IN ('rate', 'quota')`),
29
+ check("lenso_limit_counter_capacity", sql`${table.capacity} BETWEEN 1 AND 2147483647`),
30
+ check("lenso_limit_counter_period", sql`${table.periodMs} BETWEEN 1 AND 31622400000`),
31
+ check("lenso_limit_counter_used", sql`${table.used} BETWEEN 0 AND ${table.capacity}`),
32
+ check("lenso_limit_counter_clock", sql`${table.windowStart} >= 0 AND ${table.lastNow} >= 0`)
33
+ ]);
34
+ var concurrencyBuckets = sqliteTable("lenso_limit_concurrency", {
35
+ scope: text("scope").primaryKey().notNull(),
36
+ capacity: integer("capacity").notNull(),
37
+ lastNow: integer("last_now").notNull(),
38
+ leases: text("leases", { mode: "json" }).$type().notNull()
39
+ }, (table) => [
40
+ check("lenso_limit_lease_capacity", sql`${table.capacity} BETWEEN 1 AND 2147483647`),
41
+ check("lenso_limit_lease_clock", sql`${table.lastNow} >= 0`)
42
+ ]);
43
+ var limitSchema = { counters, concurrencyBuckets };
44
+ var sqliteNow = sql`CAST(round((julianday('now') - 2440587.5) * 86400000) AS INTEGER)`;
45
+ function createSqliteLimitStore(db) {
46
+ return {
47
+ async consume(kind, input) {
48
+ validateKind(kind);
49
+ validateConsume(input);
50
+ const key = scopeKey(input.scope);
51
+ return db.transaction((tx) => {
52
+ const now = tx.values(sql`SELECT ${sqliteNow}`)[0][0];
53
+ const previous = tx.select().from(counters).where(and(eq(counters.scope, key), eq(counters.kind, kind))).get();
54
+ const { state, result } = consumeState(previous, input, now);
55
+ tx.insert(counters).values({ scope: key, kind, ...state }).onConflictDoUpdate({ target: [counters.scope, counters.kind], set: state }).run();
56
+ return result;
57
+ }, { behavior: "immediate" });
58
+ },
59
+ async acquire(input, token) {
60
+ validateAcquire(input);
61
+ validateToken(token);
62
+ const key = scopeKey(input.scope);
63
+ return db.transaction((tx) => {
64
+ const now = tx.values(sql`SELECT ${sqliteNow}`)[0][0];
65
+ const previous = tx.select().from(concurrencyBuckets).where(eq(concurrencyBuckets.scope, key)).get();
66
+ const state = liveState(previous, input.capacity, now);
67
+ const result = acquireState(state, input, token);
68
+ tx.insert(concurrencyBuckets).values({ scope: key, ...state }).onConflictDoUpdate({ target: concurrencyBuckets.scope, set: state }).run();
69
+ return result;
70
+ }, { behavior: "immediate" });
71
+ },
72
+ async renew(scope, token, ttlMs) {
73
+ const key = scopeKey(scope);
74
+ validateToken(token);
75
+ positiveInteger(ttlMs, maxDurationMs);
76
+ return db.transaction((tx) => {
77
+ const now = tx.values(sql`SELECT ${sqliteNow}`)[0][0];
78
+ const previous = tx.select().from(concurrencyBuckets).where(eq(concurrencyBuckets.scope, key)).get();
79
+ if (!previous)
80
+ return null;
81
+ const state = liveState(previous, previous.capacity, now);
82
+ const lease = renewState(state, scope, token, ttlMs);
83
+ tx.update(concurrencyBuckets).set(state).where(eq(concurrencyBuckets.scope, key)).run();
84
+ return lease;
85
+ }, { behavior: "immediate" });
86
+ },
87
+ async release(scope, token) {
88
+ const key = scopeKey(scope);
89
+ validateToken(token);
90
+ db.transaction((tx) => {
91
+ const now = tx.values(sql`SELECT ${sqliteNow}`)[0][0];
92
+ const previous = tx.select().from(concurrencyBuckets).where(eq(concurrencyBuckets.scope, key)).get();
93
+ if (!previous)
94
+ return;
95
+ const state = liveState(previous, previous.capacity, now);
96
+ state.leases = state.leases.filter((lease) => lease.token !== token);
97
+ tx.update(concurrencyBuckets).set(state).where(eq(concurrencyBuckets.scope, key)).run();
98
+ }, { behavior: "immediate" });
99
+ }
100
+ };
101
+ }
102
+ export {
103
+ concurrencyBuckets,
104
+ counters,
105
+ createSqliteLimitStore,
106
+ limitSchema
107
+ };
@@ -0,0 +1,25 @@
1
+ import { type Acquisition, type AcquireInput, type ConsumeInput, type Decision, type Lease, type LimitScope } from "./contracts";
2
+ export interface CounterState {
3
+ capacity: number;
4
+ periodMs: number;
5
+ windowStart: number;
6
+ used: number;
7
+ lastNow: number;
8
+ }
9
+ export interface LeaseState {
10
+ capacity: number;
11
+ lastNow: number;
12
+ leases: Lease[];
13
+ }
14
+ export declare function clockTime(now: number, previous?: number): number;
15
+ export declare function consumeState(previous: CounterState | undefined, input: ConsumeInput, clock: number): {
16
+ state: CounterState;
17
+ result: Decision;
18
+ };
19
+ /** Describe a committed counter outcome; SQL adapters perform admission inside the backend. */
20
+ export declare function counterDecision(state: CounterState, quantity: number, allowed: boolean): Decision;
21
+ export declare function liveState(previous: LeaseState | undefined, capacity: number, clock: number): LeaseState;
22
+ export declare function acquireState(state: LeaseState, input: AcquireInput, token: string): Acquisition;
23
+ /** State includes the new lease when allowed, otherwise it contains only current holders. */
24
+ export declare function leaseDecision(state: LeaseState, quantity: number, allowed: boolean): Decision;
25
+ export declare function renewState(state: LeaseState, scope: LimitScope, token: string, ttlMs: number): Lease | null;
@@ -0,0 +1,34 @@
1
+ CREATE TABLE lenso_d1_limit_counters (
2
+ scope TEXT NOT NULL,
3
+ kind TEXT NOT NULL,
4
+ capacity INTEGER NOT NULL,
5
+ period_ms INTEGER NOT NULL,
6
+ window_start INTEGER NOT NULL,
7
+ used INTEGER NOT NULL,
8
+ last_now INTEGER NOT NULL,
9
+ PRIMARY KEY (scope, kind),
10
+ CONSTRAINT lenso_d1_counter_kind CHECK (kind IN ('rate', 'quota')),
11
+ CONSTRAINT lenso_d1_counter_capacity CHECK (capacity BETWEEN 1 AND 2147483647),
12
+ CONSTRAINT lenso_d1_counter_period CHECK (period_ms BETWEEN 1 AND 31622400000),
13
+ CONSTRAINT lenso_d1_counter_used CHECK (used BETWEEN 0 AND capacity),
14
+ CONSTRAINT lenso_d1_counter_clock CHECK (window_start >= 0 AND last_now >= 0)
15
+ );
16
+
17
+ CREATE TABLE lenso_d1_limit_concurrency (
18
+ scope TEXT PRIMARY KEY NOT NULL,
19
+ capacity INTEGER NOT NULL,
20
+ last_now INTEGER NOT NULL,
21
+ CONSTRAINT lenso_d1_lease_capacity CHECK (capacity BETWEEN 1 AND 2147483647),
22
+ CONSTRAINT lenso_d1_lease_clock CHECK (last_now >= 0)
23
+ );
24
+
25
+ CREATE TABLE lenso_d1_limit_leases (
26
+ scope TEXT NOT NULL REFERENCES lenso_d1_limit_concurrency(scope),
27
+ token TEXT NOT NULL,
28
+ quantity INTEGER NOT NULL,
29
+ expires_at INTEGER NOT NULL,
30
+ PRIMARY KEY (scope, token),
31
+ CONSTRAINT lenso_d1_lease_quantity CHECK (quantity BETWEEN 1 AND 2147483647),
32
+ CONSTRAINT lenso_d1_lease_expiry_check CHECK (expires_at >= 0)
33
+ );
34
+ CREATE INDEX lenso_d1_lease_expiry ON lenso_d1_limit_leases(scope, expires_at);
@@ -0,0 +1,23 @@
1
+ CREATE TABLE lenso_limit_counters (
2
+ scope TEXT NOT NULL,
3
+ kind TEXT NOT NULL CHECK (kind IN ('rate', 'quota')),
4
+ capacity BIGINT NOT NULL,
5
+ period_ms BIGINT NOT NULL,
6
+ window_start BIGINT NOT NULL,
7
+ used BIGINT NOT NULL,
8
+ last_now BIGINT NOT NULL,
9
+ PRIMARY KEY (scope, kind),
10
+ CONSTRAINT lenso_limit_counter_capacity CHECK (capacity BETWEEN 1 AND 2147483647),
11
+ CONSTRAINT lenso_limit_counter_period CHECK (period_ms BETWEEN 1 AND 31622400000),
12
+ CONSTRAINT lenso_limit_counter_used CHECK (used BETWEEN 0 AND capacity),
13
+ CONSTRAINT lenso_limit_counter_clock CHECK (window_start >= 0 AND last_now >= 0)
14
+ );
15
+
16
+ CREATE TABLE lenso_limit_concurrency (
17
+ scope TEXT PRIMARY KEY NOT NULL,
18
+ capacity BIGINT NOT NULL,
19
+ last_now BIGINT NOT NULL,
20
+ leases JSONB NOT NULL,
21
+ CONSTRAINT lenso_limit_lease_capacity CHECK (capacity BETWEEN 1 AND 2147483647),
22
+ CONSTRAINT lenso_limit_lease_clock CHECK (last_now >= 0)
23
+ );
@@ -0,0 +1,23 @@
1
+ CREATE TABLE lenso_limit_counters (
2
+ scope TEXT NOT NULL,
3
+ kind TEXT NOT NULL CHECK (kind IN ('rate', 'quota')),
4
+ capacity INTEGER NOT NULL,
5
+ period_ms INTEGER NOT NULL,
6
+ window_start INTEGER NOT NULL,
7
+ used INTEGER NOT NULL,
8
+ last_now INTEGER NOT NULL,
9
+ PRIMARY KEY (scope, kind),
10
+ CONSTRAINT lenso_limit_counter_capacity CHECK (capacity BETWEEN 1 AND 2147483647),
11
+ CONSTRAINT lenso_limit_counter_period CHECK (period_ms BETWEEN 1 AND 31622400000),
12
+ CONSTRAINT lenso_limit_counter_used CHECK (used BETWEEN 0 AND capacity),
13
+ CONSTRAINT lenso_limit_counter_clock CHECK (window_start >= 0 AND last_now >= 0)
14
+ );
15
+
16
+ CREATE TABLE lenso_limit_concurrency (
17
+ scope TEXT PRIMARY KEY NOT NULL,
18
+ capacity INTEGER NOT NULL,
19
+ last_now INTEGER NOT NULL,
20
+ leases TEXT NOT NULL,
21
+ CONSTRAINT lenso_limit_lease_capacity CHECK (capacity BETWEEN 1 AND 2147483647),
22
+ CONSTRAINT lenso_limit_lease_clock CHECK (last_now >= 0)
23
+ );