@absurd-sqlite/bun-worker 0.2.2-alpha.1 → 0.3.0-alpha.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/bun.lock +3 -34
- package/dist/index.d.ts +2 -2
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +514 -5061
- package/dist/sqlite.d.ts +4 -12
- package/dist/sqlite.d.ts.map +1 -1
- package/package.json +2 -3
- package/src/index.ts +8 -7
- package/src/sqlite.ts +122 -134
- package/test/basic.test.ts +53 -1
- package/test/events.test.ts +2 -2
- package/test/hooks.test.ts +1 -1
- package/test/idempotent.test.ts +1 -1
- package/test/index.test.ts +3 -3
- package/test/retry.test.ts +1 -1
- package/test/setup.ts +3 -7
- package/test/sqlite.test.ts +8 -6
- package/test/step.test.ts +1 -1
- package/test/worker.test.ts +1 -1
package/dist/sqlite.d.ts
CHANGED
|
@@ -1,15 +1,7 @@
|
|
|
1
1
|
import { Database } from "bun:sqlite";
|
|
2
|
-
import type {
|
|
3
|
-
import
|
|
4
|
-
export declare class BunSqliteConnection
|
|
5
|
-
|
|
6
|
-
private readonly maxRetries;
|
|
7
|
-
private readonly baseRetryDelayMs;
|
|
8
|
-
constructor(db: Database);
|
|
9
|
-
query<R extends object = Record<string, any>>(sql: string, params?: SQLiteRestBindParams): Promise<{
|
|
10
|
-
rows: R[];
|
|
11
|
-
}>;
|
|
12
|
-
exec(sql: string, params?: SQLiteRestBindParams): Promise<void>;
|
|
13
|
-
private runWithRetry;
|
|
2
|
+
import type { SQLiteConnectionOptions } from "@absurd-sqlite/sdk";
|
|
3
|
+
import { SQLiteConnection } from "@absurd-sqlite/sdk";
|
|
4
|
+
export declare class BunSqliteConnection extends SQLiteConnection {
|
|
5
|
+
constructor(db: Database, options?: SQLiteConnectionOptions);
|
|
14
6
|
}
|
|
15
7
|
//# sourceMappingURL=sqlite.d.ts.map
|
package/dist/sqlite.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"sqlite.d.ts","sourceRoot":"","sources":["../src/sqlite.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAC;AAEtC,OAAO,KAAK,
|
|
1
|
+
{"version":3,"file":"sqlite.d.ts","sourceRoot":"","sources":["../src/sqlite.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAC;AAEtC,OAAO,KAAK,EAGV,uBAAuB,EAIxB,MAAM,oBAAoB,CAAC;AAC5B,OAAO,EAAE,gBAAgB,EAAE,MAAM,oBAAoB,CAAC;AAEtD,qBAAa,mBAAoB,SAAQ,gBAAgB;gBAC3C,EAAE,EAAE,QAAQ,EAAE,OAAO,GAAE,uBAA4B;CAIhE"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@absurd-sqlite/bun-worker",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.3.0-alpha.0",
|
|
4
4
|
"description": "Bun worker utilities for Absurd-SQLite",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "dist/index.js",
|
|
@@ -39,11 +39,10 @@
|
|
|
39
39
|
"homepage": "https://github.com/b4fun/absurd-sqlite#readme",
|
|
40
40
|
"dependencies": {
|
|
41
41
|
"@absurd-sqlite/sdk": "next",
|
|
42
|
-
"absurd-sdk": "~0.0.7",
|
|
43
42
|
"cac": "^6.7.14"
|
|
44
43
|
},
|
|
45
44
|
"devDependencies": {
|
|
46
|
-
"bun-types": "^1.3.
|
|
45
|
+
"bun-types": "^1.3.6",
|
|
47
46
|
"typescript": "^5.9.3"
|
|
48
47
|
},
|
|
49
48
|
"engines": {
|
package/src/index.ts
CHANGED
|
@@ -1,12 +1,15 @@
|
|
|
1
|
-
import { Absurd, type WorkerOptions } from "absurd-sdk";
|
|
2
1
|
import { Database } from "bun:sqlite";
|
|
3
|
-
import
|
|
2
|
+
import {
|
|
3
|
+
Absurd,
|
|
4
|
+
type AbsurdClient,
|
|
5
|
+
type WorkerOptions,
|
|
6
|
+
} from "@absurd-sqlite/sdk";
|
|
4
7
|
import { cac } from "cac";
|
|
5
8
|
|
|
6
9
|
import { BunSqliteConnection } from "./sqlite";
|
|
7
10
|
|
|
8
11
|
export type { AbsurdClient } from "@absurd-sqlite/sdk";
|
|
9
|
-
export type { WorkerOptions } from "absurd-sdk";
|
|
12
|
+
export type { WorkerOptions } from "@absurd-sqlite/sdk";
|
|
10
13
|
|
|
11
14
|
export {
|
|
12
15
|
downloadExtension,
|
|
@@ -101,12 +104,10 @@ export default async function run(setupFunction: SetupFunction): Promise<void> {
|
|
|
101
104
|
}
|
|
102
105
|
|
|
103
106
|
const db = new Database(dbPath);
|
|
104
|
-
|
|
105
|
-
extensionPath
|
|
106
|
-
);
|
|
107
|
+
db.loadExtension(extensionPath);
|
|
107
108
|
|
|
108
109
|
const conn = new BunSqliteConnection(db);
|
|
109
|
-
const absurd = new Absurd(
|
|
110
|
+
const absurd = new Absurd(conn);
|
|
110
111
|
|
|
111
112
|
await setupFunction(absurd);
|
|
112
113
|
|
package/src/sqlite.ts
CHANGED
|
@@ -1,112 +1,138 @@
|
|
|
1
1
|
import { Database } from "bun:sqlite";
|
|
2
2
|
|
|
3
|
-
import type { Queryable } from "@absurd-sqlite/sdk";
|
|
4
3
|
import type {
|
|
5
|
-
SQLiteBindParams,
|
|
6
4
|
SQLiteBindValue,
|
|
7
|
-
|
|
5
|
+
SQLiteColumnDefinition,
|
|
6
|
+
SQLiteConnectionOptions,
|
|
7
|
+
SQLiteDatabase,
|
|
8
|
+
SQLiteStatement,
|
|
9
|
+
SQLiteValueCodec,
|
|
8
10
|
} from "@absurd-sqlite/sdk";
|
|
11
|
+
import { SQLiteConnection } from "@absurd-sqlite/sdk";
|
|
9
12
|
|
|
10
|
-
export class BunSqliteConnection
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
13
|
+
export class BunSqliteConnection extends SQLiteConnection {
|
|
14
|
+
constructor(db: Database, options: SQLiteConnectionOptions = {}) {
|
|
15
|
+
const valueCodec = buildValueCodec(options.valueCodec);
|
|
16
|
+
super(new BunSqliteDatabase(db), { ...options, valueCodec });
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
class BunSqliteDatabase implements SQLiteDatabase {
|
|
21
|
+
constructor(private readonly db: Database) {}
|
|
14
22
|
|
|
15
|
-
|
|
16
|
-
|
|
23
|
+
prepare<Result extends object = Record<string, any>>(
|
|
24
|
+
sql: string
|
|
25
|
+
): SQLiteStatement<Result> {
|
|
26
|
+
const statement = this.db.prepare(sql);
|
|
27
|
+
return new BunSqliteStatement(statement, isReadonlyQuery(sql));
|
|
17
28
|
}
|
|
18
29
|
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
): Promise<{ rows: R[] }> {
|
|
23
|
-
const { sql: sqliteQuery, paramOrder } = rewritePostgresQuery(sql);
|
|
24
|
-
const sqliteParams = rewritePostgresParams(
|
|
25
|
-
normalizeParams(params),
|
|
26
|
-
paramOrder
|
|
27
|
-
);
|
|
30
|
+
close(): void {
|
|
31
|
+
this.db.close();
|
|
32
|
+
}
|
|
28
33
|
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
decodeRowValues(row as Record<string, unknown>)
|
|
33
|
-
)
|
|
34
|
+
loadExtension(path: string): void {
|
|
35
|
+
(this.db as unknown as { loadExtension(path: string): void }).loadExtension(
|
|
36
|
+
path
|
|
34
37
|
);
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
class BunSqliteStatement<Result extends object = Record<string, any>>
|
|
42
|
+
implements SQLiteStatement<Result>
|
|
43
|
+
{
|
|
44
|
+
readonly readonly: boolean;
|
|
35
45
|
|
|
36
|
-
|
|
46
|
+
constructor(
|
|
47
|
+
private readonly stmt: ReturnType<Database["prepare"]>,
|
|
48
|
+
readonlyFlag: boolean
|
|
49
|
+
) {
|
|
50
|
+
this.readonly = readonlyFlag;
|
|
37
51
|
}
|
|
38
52
|
|
|
39
|
-
|
|
40
|
-
const
|
|
41
|
-
const
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
53
|
+
columns(): SQLiteColumnDefinition[] {
|
|
54
|
+
const columnNames = this.stmt.columnNames ?? [];
|
|
55
|
+
const declaredTypes = this.stmt.declaredTypes ?? [];
|
|
56
|
+
return columnNames.map((name, index) => ({
|
|
57
|
+
name,
|
|
58
|
+
column: null,
|
|
59
|
+
table: null,
|
|
60
|
+
database: null,
|
|
61
|
+
type: normalizeColumnType(declaredTypes[index] ?? null),
|
|
62
|
+
}));
|
|
63
|
+
}
|
|
45
64
|
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
return operation();
|
|
55
|
-
} catch (err) {
|
|
56
|
-
if (!isRetryableSQLiteError(err) || attempt >= this.maxRetries) {
|
|
57
|
-
throw err;
|
|
58
|
-
}
|
|
59
|
-
attempt++;
|
|
60
|
-
await delay(this.baseRetryDelayMs * attempt);
|
|
61
|
-
}
|
|
62
|
-
}
|
|
65
|
+
all(...args: any[]): Result[] {
|
|
66
|
+
const normalizedArgs = normalizeStatementArgs(args);
|
|
67
|
+
return this.stmt.all(...normalizedArgs) as Result[];
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
run(...args: any[]): unknown {
|
|
71
|
+
const normalizedArgs = normalizeStatementArgs(args);
|
|
72
|
+
return this.stmt.run(...normalizedArgs);
|
|
63
73
|
}
|
|
64
74
|
}
|
|
65
75
|
|
|
66
|
-
function
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
return "?";
|
|
75
|
-
})
|
|
76
|
-
.replace(/absurd\.(\w+)/g, "absurd_$1");
|
|
77
|
-
|
|
78
|
-
return { sql, paramOrder };
|
|
76
|
+
function buildValueCodec(
|
|
77
|
+
overrides?: SQLiteValueCodec
|
|
78
|
+
): SQLiteValueCodec {
|
|
79
|
+
return {
|
|
80
|
+
encodeParam: overrides?.encodeParam ?? encodeColumnValue,
|
|
81
|
+
decodeColumn: overrides?.decodeColumn ?? decodeColumnValue,
|
|
82
|
+
decodeRow: overrides?.decodeRow ?? decodeRowValues,
|
|
83
|
+
};
|
|
79
84
|
}
|
|
80
85
|
|
|
81
|
-
function
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
86
|
+
function normalizeStatementArgs(args: any[]): any[] {
|
|
87
|
+
if (args.length !== 1) {
|
|
88
|
+
return args;
|
|
89
|
+
}
|
|
90
|
+
const params = args[0];
|
|
91
|
+
if (!params || typeof params !== "object" || Array.isArray(params)) {
|
|
92
|
+
return args;
|
|
87
93
|
}
|
|
94
|
+
const normalized: Record<string, unknown> = {};
|
|
95
|
+
for (const [key, value] of Object.entries(params)) {
|
|
96
|
+
normalized[normalizeParamKey(key)] = value;
|
|
97
|
+
}
|
|
98
|
+
return [normalized];
|
|
99
|
+
}
|
|
88
100
|
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
return
|
|
92
|
-
}
|
|
101
|
+
function normalizeParamKey(key: string): string {
|
|
102
|
+
if (key.startsWith("$") || key.startsWith(":") || key.startsWith("@")) {
|
|
103
|
+
return key;
|
|
104
|
+
}
|
|
105
|
+
return `:${key}`;
|
|
93
106
|
}
|
|
94
107
|
|
|
95
|
-
function decodeRowValues<R extends object = any>(
|
|
96
|
-
row: Record<string, unknown
|
|
97
|
-
|
|
108
|
+
function decodeRowValues<R extends object = any>(args: {
|
|
109
|
+
row: Record<string, unknown>;
|
|
110
|
+
columns?: SQLiteColumnDefinition[];
|
|
111
|
+
decodeColumn?: (args: {
|
|
112
|
+
value: unknown;
|
|
113
|
+
columnName: string;
|
|
114
|
+
columnType: string | null;
|
|
115
|
+
}) => unknown;
|
|
116
|
+
}): R {
|
|
98
117
|
const decodedRow: any = {};
|
|
99
|
-
for (const [columnName, rawValue] of Object.entries(row)) {
|
|
100
|
-
decodedRow[columnName] = decodeColumnValue(
|
|
118
|
+
for (const [columnName, rawValue] of Object.entries(args.row)) {
|
|
119
|
+
decodedRow[columnName] = decodeColumnValue({
|
|
120
|
+
value: rawValue,
|
|
121
|
+
columnName,
|
|
122
|
+
columnType: null,
|
|
123
|
+
});
|
|
101
124
|
}
|
|
102
125
|
|
|
103
126
|
return decodedRow as R;
|
|
104
127
|
}
|
|
105
128
|
|
|
106
|
-
function decodeColumnValue<V = any>(
|
|
107
|
-
value: unknown | V
|
|
108
|
-
columnName: string
|
|
109
|
-
|
|
129
|
+
function decodeColumnValue<V = any>(args: {
|
|
130
|
+
value: unknown | V;
|
|
131
|
+
columnName: string;
|
|
132
|
+
columnType: string | null;
|
|
133
|
+
verbose?: (...args: any[]) => void;
|
|
134
|
+
}): V | null {
|
|
135
|
+
const { value, columnName } = args;
|
|
110
136
|
if (value === null || value === undefined) {
|
|
111
137
|
return null;
|
|
112
138
|
}
|
|
@@ -128,8 +154,7 @@ function decodeColumnValue<V = any>(
|
|
|
128
154
|
}
|
|
129
155
|
|
|
130
156
|
if (value instanceof Uint8Array || value instanceof ArrayBuffer) {
|
|
131
|
-
const bytes =
|
|
132
|
-
value instanceof Uint8Array ? value : new Uint8Array(value);
|
|
157
|
+
const bytes = value instanceof Uint8Array ? value : new Uint8Array(value);
|
|
133
158
|
const decoded = new TextDecoder().decode(bytes);
|
|
134
159
|
return tryDecodeJson(decoded) ?? (value as V);
|
|
135
160
|
}
|
|
@@ -145,7 +170,7 @@ function tryDecodeJson<V = any>(value: string): V | null {
|
|
|
145
170
|
}
|
|
146
171
|
}
|
|
147
172
|
|
|
148
|
-
function encodeColumnValue(value:
|
|
173
|
+
function encodeColumnValue(value: SQLiteBindValue): SQLiteBindValue {
|
|
149
174
|
if (value instanceof Date) {
|
|
150
175
|
return value.toISOString();
|
|
151
176
|
}
|
|
@@ -159,60 +184,23 @@ function isTimestampColumn(columnName: string): boolean {
|
|
|
159
184
|
return columnName.endsWith("_at");
|
|
160
185
|
}
|
|
161
186
|
|
|
162
|
-
function
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
const inner = params[0];
|
|
171
|
-
if (Array.isArray(inner)) {
|
|
172
|
-
return inner;
|
|
173
|
-
}
|
|
174
|
-
return Object.values(inner);
|
|
175
|
-
}
|
|
176
|
-
|
|
177
|
-
return params as SQLiteBindValue[];
|
|
178
|
-
}
|
|
179
|
-
|
|
180
|
-
function isBindParams(value: unknown): value is SQLiteBindParams {
|
|
181
|
-
if (Array.isArray(value)) {
|
|
182
|
-
return true;
|
|
183
|
-
}
|
|
184
|
-
if (!value || typeof value !== "object") {
|
|
185
|
-
return false;
|
|
186
|
-
}
|
|
187
|
-
const tag = Object.prototype.toString.call(value);
|
|
188
|
-
return tag === "[object Object]";
|
|
187
|
+
function isReadonlyQuery(sql: string): boolean {
|
|
188
|
+
const trimmed = sql.trim().toLowerCase();
|
|
189
|
+
return (
|
|
190
|
+
trimmed.startsWith("select") ||
|
|
191
|
+
trimmed.startsWith("with") ||
|
|
192
|
+
trimmed.startsWith("pragma") ||
|
|
193
|
+
trimmed.startsWith("explain")
|
|
194
|
+
);
|
|
189
195
|
}
|
|
190
196
|
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
function isRetryableSQLiteError(err: unknown): boolean {
|
|
195
|
-
if (!err || typeof err !== "object") {
|
|
196
|
-
return false;
|
|
197
|
-
}
|
|
198
|
-
|
|
199
|
-
const code = (err as any).code;
|
|
200
|
-
if (typeof code === "string") {
|
|
201
|
-
for (const retryableCode of sqliteRetryableErrorCodes) {
|
|
202
|
-
if (code.startsWith(retryableCode)) {
|
|
203
|
-
return true;
|
|
204
|
-
}
|
|
205
|
-
}
|
|
197
|
+
function normalizeColumnType(value: string | null): string | null {
|
|
198
|
+
if (!value) {
|
|
199
|
+
return null;
|
|
206
200
|
}
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
return true;
|
|
201
|
+
const lowered = value.toLowerCase();
|
|
202
|
+
if (lowered === "null") {
|
|
203
|
+
return null;
|
|
211
204
|
}
|
|
212
|
-
|
|
213
|
-
return false;
|
|
214
|
-
}
|
|
215
|
-
|
|
216
|
-
function delay(ms: number): Promise<void> {
|
|
217
|
-
return new Promise((resolve) => setTimeout(resolve, ms));
|
|
205
|
+
return lowered;
|
|
218
206
|
}
|
package/test/basic.test.ts
CHANGED
|
@@ -4,9 +4,10 @@ import {
|
|
|
4
4
|
expect,
|
|
5
5
|
beforeAll,
|
|
6
6
|
afterEach,
|
|
7
|
+
jest,
|
|
7
8
|
} from "bun:test";
|
|
8
9
|
import assert from "node:assert/strict";
|
|
9
|
-
import type { Absurd } from "absurd-sdk";
|
|
10
|
+
import type { Absurd } from "@absurd-sqlite/sdk";
|
|
10
11
|
import { createTestAbsurd, randomName, type TestContext } from "./setup";
|
|
11
12
|
import { EventEmitter, once } from "events";
|
|
12
13
|
import { waitFor } from "./wait-for";
|
|
@@ -501,5 +502,56 @@ describe("Basic SDK Operations", () => {
|
|
|
501
502
|
);
|
|
502
503
|
});
|
|
503
504
|
});
|
|
505
|
+
|
|
506
|
+
test("heartbeat keeps task alive past original claim timeout", async () => {
|
|
507
|
+
const claimTimeout = 1;
|
|
508
|
+
const extension = 10;
|
|
509
|
+
const longWorkMs = claimTimeout * 2000 + 100;
|
|
510
|
+
let heartbeatFired = false;
|
|
511
|
+
|
|
512
|
+
absurd.registerTask(
|
|
513
|
+
{ name: "heartbeat-long-task" },
|
|
514
|
+
async (_params, taskCtx) => {
|
|
515
|
+
await taskCtx.heartbeat(extension);
|
|
516
|
+
heartbeatFired = true;
|
|
517
|
+
await ctx.sleep(longWorkMs);
|
|
518
|
+
return { ok: true };
|
|
519
|
+
},
|
|
520
|
+
);
|
|
521
|
+
|
|
522
|
+
const { taskID } = await absurd.spawn("heartbeat-long-task", {});
|
|
523
|
+
|
|
524
|
+
const exitSpy = jest
|
|
525
|
+
.spyOn(process, "exit")
|
|
526
|
+
.mockImplementation(() => undefined as never);
|
|
527
|
+
|
|
528
|
+
const worker = await absurd.startWorker({
|
|
529
|
+
claimTimeout,
|
|
530
|
+
concurrency: 1,
|
|
531
|
+
pollInterval: 0.01,
|
|
532
|
+
fatalOnLeaseTimeout: true,
|
|
533
|
+
});
|
|
534
|
+
|
|
535
|
+
try {
|
|
536
|
+
await waitFor(() => expect(heartbeatFired).toBe(true), {
|
|
537
|
+
timeout: 500,
|
|
538
|
+
});
|
|
539
|
+
|
|
540
|
+
await waitFor(async () => {
|
|
541
|
+
const task = await ctx.getTask(taskID);
|
|
542
|
+
expect(task?.state).toBe("completed");
|
|
543
|
+
}, {
|
|
544
|
+
timeout: longWorkMs + 2000,
|
|
545
|
+
});
|
|
546
|
+
|
|
547
|
+
const runs = await ctx.getRuns(taskID);
|
|
548
|
+
expect(runs).toHaveLength(1);
|
|
549
|
+
expect(runs[0]?.state).toBe("completed");
|
|
550
|
+
expect(exitSpy).not.toHaveBeenCalled();
|
|
551
|
+
} finally {
|
|
552
|
+
await worker.close();
|
|
553
|
+
exitSpy.mockRestore();
|
|
554
|
+
}
|
|
555
|
+
});
|
|
504
556
|
});
|
|
505
557
|
});
|
package/test/events.test.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { describe, test, expect, beforeAll, afterEach } from "bun:test";
|
|
2
|
-
import type { Absurd } from "absurd-sdk";
|
|
2
|
+
import type { Absurd } from "@absurd-sqlite/sdk";
|
|
3
3
|
import { createTestAbsurd, randomName, type TestContext } from "./setup";
|
|
4
|
-
import { TimeoutError } from "absurd-sdk";
|
|
4
|
+
import { TimeoutError } from "@absurd-sqlite/sdk";
|
|
5
5
|
|
|
6
6
|
describe("Event system", () => {
|
|
7
7
|
let ctx: TestContext;
|
package/test/hooks.test.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { describe, test, expect, beforeAll, afterEach } from "bun:test";
|
|
2
2
|
import { AsyncLocalStorage } from "node:async_hooks";
|
|
3
|
-
import type { Absurd, SpawnOptions } from "absurd-sdk";
|
|
3
|
+
import type { Absurd, SpawnOptions } from "@absurd-sqlite/sdk";
|
|
4
4
|
import { createTestAbsurd, randomName, type TestContext } from "./setup";
|
|
5
5
|
|
|
6
6
|
describe("Hooks", () => {
|
package/test/idempotent.test.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { describe, test, expect, beforeAll, afterEach } from "bun:test";
|
|
2
|
-
import type { Absurd } from "absurd-sdk";
|
|
2
|
+
import type { Absurd } from "@absurd-sqlite/sdk";
|
|
3
3
|
import { createTestAbsurd, randomName, type TestContext } from "./setup";
|
|
4
4
|
|
|
5
5
|
describe("Idempotent Task Spawning", () => {
|
package/test/index.test.ts
CHANGED
|
@@ -3,7 +3,7 @@ import { mkdtempSync, rmSync } from "node:fs";
|
|
|
3
3
|
import { tmpdir } from "node:os";
|
|
4
4
|
import { join } from "node:path";
|
|
5
5
|
import { afterEach, describe, expect, it } from "bun:test";
|
|
6
|
-
import { Absurd } from "absurd-sdk";
|
|
6
|
+
import { Absurd } from "@absurd-sqlite/sdk";
|
|
7
7
|
|
|
8
8
|
import { BunSqliteConnection } from "../src/sqlite";
|
|
9
9
|
import { loadExtension } from "./setup";
|
|
@@ -29,7 +29,7 @@ describe("Absurd", () => {
|
|
|
29
29
|
it("creates and lists queues using the sqlite extension", async () => {
|
|
30
30
|
const db = createDatabaseWithMigrations();
|
|
31
31
|
const conn = new BunSqliteConnection(db);
|
|
32
|
-
const absurd = new Absurd(
|
|
32
|
+
const absurd = new Absurd(conn);
|
|
33
33
|
|
|
34
34
|
await absurd.createQueue("alpha");
|
|
35
35
|
await absurd.createQueue("beta");
|
|
@@ -52,7 +52,7 @@ describe("Absurd", () => {
|
|
|
52
52
|
it("closes workers without affecting the sqlite database", async () => {
|
|
53
53
|
const db = createDatabaseWithMigrations();
|
|
54
54
|
const conn = new BunSqliteConnection(db);
|
|
55
|
-
const absurd = new Absurd(
|
|
55
|
+
const absurd = new Absurd(conn);
|
|
56
56
|
|
|
57
57
|
await absurd.close();
|
|
58
58
|
|
package/test/retry.test.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { describe, test, expect, beforeAll, afterEach } from "bun:test";
|
|
2
|
-
import type { Absurd } from "absurd-sdk";
|
|
2
|
+
import type { Absurd } from "@absurd-sqlite/sdk";
|
|
3
3
|
import { createTestAbsurd, randomName, type TestContext } from "./setup";
|
|
4
4
|
|
|
5
5
|
describe("Retry and cancellation", () => {
|
package/test/setup.ts
CHANGED
|
@@ -8,7 +8,7 @@ import {
|
|
|
8
8
|
Absurd,
|
|
9
9
|
type AbsurdHooks,
|
|
10
10
|
type JsonValue,
|
|
11
|
-
} from "absurd-sdk";
|
|
11
|
+
} from "@absurd-sqlite/sdk";
|
|
12
12
|
|
|
13
13
|
import { BunSqliteConnection } from "../src/sqlite";
|
|
14
14
|
|
|
@@ -263,10 +263,7 @@ export async function createTestAbsurd(
|
|
|
263
263
|
queueName: string = "default"
|
|
264
264
|
): Promise<TestContext> {
|
|
265
265
|
const fixture = createFixture();
|
|
266
|
-
const absurd = new Absurd({
|
|
267
|
-
db: fixture.conn,
|
|
268
|
-
queueName,
|
|
269
|
-
});
|
|
266
|
+
const absurd = new Absurd(fixture.conn, { queueName });
|
|
270
267
|
|
|
271
268
|
await absurd.createQueue(queueName);
|
|
272
269
|
|
|
@@ -335,8 +332,7 @@ export async function createTestAbsurd(
|
|
|
335
332
|
expectCancelledError: (promise: Promise<unknown>) =>
|
|
336
333
|
expectCancelledError(promise),
|
|
337
334
|
createClient: (options) => {
|
|
338
|
-
const client = new Absurd({
|
|
339
|
-
db: fixture.conn,
|
|
335
|
+
const client = new Absurd(fixture.conn, {
|
|
340
336
|
queueName: options?.queueName ?? queueName,
|
|
341
337
|
hooks: options?.hooks,
|
|
342
338
|
});
|
package/test/sqlite.test.ts
CHANGED
|
@@ -26,12 +26,14 @@ describe("BunSqliteConnection", () => {
|
|
|
26
26
|
db.close();
|
|
27
27
|
});
|
|
28
28
|
|
|
29
|
-
it("
|
|
29
|
+
it("throws when query is used for non-reader statements", async () => {
|
|
30
30
|
const db = new Database(":memory:");
|
|
31
31
|
const conn = new BunSqliteConnection(db);
|
|
32
32
|
|
|
33
|
-
|
|
34
|
-
|
|
33
|
+
await expect(conn.query("CREATE TABLE t (id)")).rejects.toThrow(
|
|
34
|
+
"only statements that return data"
|
|
35
|
+
);
|
|
36
|
+
await conn.exec("CREATE TABLE t (id)");
|
|
35
37
|
|
|
36
38
|
await conn.exec("INSERT INTO t (id) VALUES ($1)", [1]);
|
|
37
39
|
const { rows: inserted } = await conn.query<{ id: number }>(
|
|
@@ -146,14 +148,14 @@ describe("BunSqliteConnection", () => {
|
|
|
146
148
|
}),
|
|
147
149
|
};
|
|
148
150
|
|
|
149
|
-
const
|
|
150
|
-
const db = {
|
|
151
|
+
const prepareSpy = jest.fn().mockReturnValue(statement as any);
|
|
152
|
+
const db = { prepare: prepareSpy } as unknown as Database;
|
|
151
153
|
const conn = new BunSqliteConnection(db);
|
|
152
154
|
|
|
153
155
|
await expect(
|
|
154
156
|
conn.exec("UPDATE locked_table SET value = $1 WHERE id = $2", [1, 1])
|
|
155
157
|
).resolves.toBeUndefined();
|
|
156
158
|
expect(statement.run).toHaveBeenCalledTimes(2);
|
|
157
|
-
expect(
|
|
159
|
+
expect(prepareSpy).toHaveBeenCalledTimes(1);
|
|
158
160
|
});
|
|
159
161
|
});
|
package/test/step.test.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { describe, test, expect, beforeAll, afterEach, jest } from "bun:test";
|
|
2
|
-
import type { Absurd } from "absurd-sdk";
|
|
2
|
+
import type { Absurd } from "@absurd-sqlite/sdk";
|
|
3
3
|
import { createTestAbsurd, randomName, type TestContext } from "./setup";
|
|
4
4
|
|
|
5
5
|
describe("Step functionality", () => {
|
package/test/worker.test.ts
CHANGED
|
@@ -2,7 +2,7 @@ import { describe, it, expect, beforeAll, afterEach, jest } from "bun:test";
|
|
|
2
2
|
import { EventEmitter, once } from "events";
|
|
3
3
|
import type { TestContext } from "./setup";
|
|
4
4
|
import { createTestAbsurd, randomName } from "./setup";
|
|
5
|
-
import type { Absurd } from "absurd-sdk";
|
|
5
|
+
import type { Absurd } from "@absurd-sqlite/sdk";
|
|
6
6
|
import { waitFor } from "./wait-for";
|
|
7
7
|
|
|
8
8
|
describe("Worker", () => {
|