@dbos-inc/knex-datasource 3.0.8-preview → 3.0.8-preview.g493d2d1c2b

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.
@@ -12,7 +12,6 @@ interface transaction_completion {
12
12
  workflow_id: string;
13
13
  function_num: number;
14
14
  output: string | null;
15
- error: string | null;
16
15
  }
17
16
 
18
17
  describe('KnexDataSource', () => {
@@ -23,9 +22,9 @@ describe('KnexDataSource', () => {
23
22
  const client = new Client({ ...config.connection, database: 'postgres' });
24
23
  try {
25
24
  await client.connect();
26
- await dropDB(client, 'knex_ds_test', true);
27
- await dropDB(client, 'knex_ds_test_dbos_sys', true);
28
- await dropDB(client, config.connection.database, true);
25
+ await dropDB(client, 'knex_ds_test');
26
+ await dropDB(client, 'knex_ds_test_dbos_sys');
27
+ await dropDB(client, config.connection.database);
29
28
  await ensureDB(client, config.connection.database);
30
29
  } finally {
31
30
  await client.end();
@@ -44,19 +43,13 @@ describe('KnexDataSource', () => {
44
43
  }
45
44
 
46
45
  await KnexDataSource.initializeInternalSchema(config);
47
- });
48
-
49
- afterAll(async () => {
50
- await userDB.end();
51
- });
52
-
53
- beforeEach(async () => {
54
46
  DBOS.setConfig({ name: 'knex-ds-test' });
55
47
  await DBOS.launch();
56
48
  });
57
49
 
58
- afterEach(async () => {
50
+ afterAll(async () => {
59
51
  await DBOS.shutdown();
52
+ await userDB.end();
60
53
  });
61
54
 
62
55
  test('insert dataSource.register function', async () => {
@@ -65,7 +58,7 @@ describe('KnexDataSource', () => {
65
58
  await userDB.query('DELETE FROM greetings WHERE name = $1', [user]);
66
59
  const workflowID = randomUUID();
67
60
 
68
- await expect(DBOS.withNextWorkflowID(workflowID, () => regInsertWorkflowReg(user))).resolves.toMatchObject({
61
+ await expect(DBOS.withNextWorkflowID(workflowID, () => regInsertWorfklowReg(user))).resolves.toEqual({
69
62
  user,
70
63
  greet_count: 1,
71
64
  });
@@ -78,19 +71,7 @@ describe('KnexDataSource', () => {
78
71
  expect(rows[0].workflow_id).toBe(workflowID);
79
72
  expect(rows[0].function_num).toBe(0);
80
73
  expect(rows[0].output).not.toBeNull();
81
- expect(SuperJSON.parse(rows[0].output!)).toMatchObject({ user, greet_count: 1 });
82
- });
83
-
84
- test('rerun insert dataSource.register function', async () => {
85
- const user = 'rerunTest1';
86
-
87
- await userDB.query('DELETE FROM greetings WHERE name = $1', [user]);
88
- const workflowID = randomUUID();
89
-
90
- const result = await DBOS.withNextWorkflowID(workflowID, () => regInsertWorkflowReg(user));
91
- expect(result).toMatchObject({ user, greet_count: 1 });
92
-
93
- await expect(DBOS.withNextWorkflowID(workflowID, () => regInsertWorkflowReg(user))).resolves.toMatchObject(result);
74
+ expect(SuperJSON.parse(rows[0].output!)).toEqual({ user, greet_count: 1 });
94
75
  });
95
76
 
96
77
  test('insert dataSource.runAsTx function', async () => {
@@ -99,7 +80,7 @@ describe('KnexDataSource', () => {
99
80
  await userDB.query('DELETE FROM greetings WHERE name = $1', [user]);
100
81
  const workflowID = randomUUID();
101
82
 
102
- await expect(DBOS.withNextWorkflowID(workflowID, () => regInsertWorkflowRunTx(user))).resolves.toMatchObject({
83
+ await expect(DBOS.withNextWorkflowID(workflowID, () => regInsertWorfklowRunTx(user))).resolves.toEqual({
103
84
  user,
104
85
  greet_count: 1,
105
86
  });
@@ -112,32 +93,9 @@ describe('KnexDataSource', () => {
112
93
  expect(rows[0].workflow_id).toBe(workflowID);
113
94
  expect(rows[0].function_num).toBe(0);
114
95
  expect(rows[0].output).not.toBeNull();
115
- expect(SuperJSON.parse(rows[0].output!)).toMatchObject({ user, greet_count: 1 });
96
+ expect(SuperJSON.parse(rows[0].output!)).toEqual({ user, greet_count: 1 });
116
97
  });
117
98
 
118
- test('rerun insert dataSource.runAsTx function', async () => {
119
- const user = 'rerunTest2';
120
-
121
- await userDB.query('DELETE FROM greetings WHERE name = $1', [user]);
122
- const workflowID = randomUUID();
123
-
124
- const result = await DBOS.withNextWorkflowID(workflowID, () => regInsertWorkflowRunTx(user));
125
- expect(result).toMatchObject({ user, greet_count: 1 });
126
-
127
- await expect(DBOS.withNextWorkflowID(workflowID, () => regInsertWorkflowRunTx(user))).resolves.toMatchObject(
128
- result,
129
- );
130
- });
131
-
132
- async function throws<R>(func: () => Promise<R>): Promise<unknown> {
133
- try {
134
- await func();
135
- fail('Expected function to throw an error');
136
- } catch (error) {
137
- return error;
138
- }
139
- }
140
-
141
99
  test('error dataSource.register function', async () => {
142
100
  const user = 'errorTest1';
143
101
 
@@ -145,42 +103,17 @@ describe('KnexDataSource', () => {
145
103
  await userDB.query('INSERT INTO greetings("name","greet_count") VALUES($1,10);', [user]);
146
104
  const workflowID = randomUUID();
147
105
 
148
- const error = await throws(() => DBOS.withNextWorkflowID(workflowID, () => regErrorWorkflowReg(user)));
149
- expect(error).toBeInstanceOf(Error);
150
- expect((error as Error).message).toMatch(/^test error \d+$/);
151
-
152
- const { rows } = await userDB.query<greetings>('SELECT * FROM greetings WHERE name = $1', [user]);
153
- expect(rows.length).toBe(1);
154
- expect(rows[0].greet_count).toBe(10);
106
+ await expect(DBOS.withNextWorkflowID(workflowID, () => regErrorWorkflowReg(user))).rejects.toThrow('test error');
155
107
 
156
108
  const { rows: txOutput } = await userDB.query<transaction_completion>(
157
109
  'SELECT * FROM dbos.transaction_completion WHERE workflow_id = $1',
158
110
  [workflowID],
159
111
  );
160
- expect(txOutput.length).toBe(1);
161
- expect(txOutput[0].workflow_id).toBe(workflowID);
162
- expect(txOutput[0].function_num).toBe(0);
163
- expect(txOutput[0].output).toBeNull();
164
- expect(txOutput[0].error).not.toBeNull();
165
- const $error = SuperJSON.parse(txOutput[0].error!);
166
- expect($error).toBeInstanceOf(Error);
167
- expect(($error as Error).message).toMatch(/^test error \d+$/);
168
- });
169
-
170
- test('rerun error dataSource.register function', async () => {
171
- const user = 'rerunErrorTest1';
172
-
173
- await userDB.query('DELETE FROM greetings WHERE name = $1', [user]);
174
- await userDB.query('INSERT INTO greetings("name","greet_count") VALUES($1,10);', [user]);
175
- const workflowID = randomUUID();
176
-
177
- const error = await throws(() => DBOS.withNextWorkflowID(workflowID, () => regErrorWorkflowReg(user)));
178
- expect(error).toBeInstanceOf(Error);
179
- expect((error as Error).message).toMatch(/^test error \d+$/);
112
+ expect(txOutput.length).toBe(0);
180
113
 
181
- const error2 = await throws(() => DBOS.withNextWorkflowID(workflowID, () => regErrorWorkflowReg(user)));
182
- expect(error2).toBeInstanceOf(Error);
183
- expect((error2 as Error).message).toMatch((error as Error).message);
114
+ const { rows } = await userDB.query<greetings>('SELECT * FROM greetings WHERE name = $1', [user]);
115
+ expect(rows.length).toBe(1);
116
+ expect(rows[0].greet_count).toBe(10);
184
117
  });
185
118
 
186
119
  test('error dataSource.runAsTx function', async () => {
@@ -190,42 +123,17 @@ describe('KnexDataSource', () => {
190
123
  await userDB.query('INSERT INTO greetings("name","greet_count") VALUES($1,10);', [user]);
191
124
  const workflowID = randomUUID();
192
125
 
193
- const error = await throws(() => DBOS.withNextWorkflowID(workflowID, () => regErrorWorkflowRunTx(user)));
194
- expect(error).toBeInstanceOf(Error);
195
- expect((error as Error).message).toMatch(/^test error \d+$/);
196
-
197
- const { rows } = await userDB.query<greetings>('SELECT * FROM greetings WHERE name = $1', [user]);
198
- expect(rows.length).toBe(1);
199
- expect(rows[0].greet_count).toBe(10);
126
+ await expect(DBOS.withNextWorkflowID(workflowID, () => regErrorWorkflowRunTx(user))).rejects.toThrow('test error');
200
127
 
201
128
  const { rows: txOutput } = await userDB.query<transaction_completion>(
202
129
  'SELECT * FROM dbos.transaction_completion WHERE workflow_id = $1',
203
130
  [workflowID],
204
131
  );
205
- expect(txOutput.length).toBe(1);
206
- expect(txOutput[0].workflow_id).toBe(workflowID);
207
- expect(txOutput[0].function_num).toBe(0);
208
- expect(txOutput[0].output).toBeNull();
209
- expect(txOutput[0].error).not.toBeNull();
210
- const $error = SuperJSON.parse(txOutput[0].error!);
211
- expect($error).toBeInstanceOf(Error);
212
- expect(($error as Error).message).toMatch(/^test error \d+$/);
213
- });
214
-
215
- test('rerun error dataSource.runAsTx function', async () => {
216
- const user = 'rerunErrorTest2';
132
+ expect(txOutput.length).toBe(0);
217
133
 
218
- await userDB.query('DELETE FROM greetings WHERE name = $1', [user]);
219
- await userDB.query('INSERT INTO greetings("name","greet_count") VALUES($1,10);', [user]);
220
- const workflowID = randomUUID();
221
-
222
- const error = await throws(() => DBOS.withNextWorkflowID(workflowID, () => regErrorWorkflowRunTx(user)));
223
- expect(error).toBeInstanceOf(Error);
224
- expect((error as Error).message).toMatch(/^test error \d+$/);
225
-
226
- const error2 = await throws(() => DBOS.withNextWorkflowID(workflowID, () => regErrorWorkflowRunTx(user)));
227
- expect(error2).toBeInstanceOf(Error);
228
- expect((error2 as Error).message).toMatch((error as Error).message);
134
+ const { rows } = await userDB.query<greetings>('SELECT * FROM greetings WHERE name = $1', [user]);
135
+ expect(rows.length).toBe(1);
136
+ expect(rows[0].greet_count).toBe(10);
229
137
  });
230
138
 
231
139
  test('readonly dataSource.register function', async () => {
@@ -235,14 +143,15 @@ describe('KnexDataSource', () => {
235
143
  await userDB.query('INSERT INTO greetings("name","greet_count") VALUES($1,10);', [user]);
236
144
 
237
145
  const workflowID = randomUUID();
238
- await expect(DBOS.withNextWorkflowID(workflowID, () => regReadWorkflowReg(user))).resolves.toMatchObject({
146
+ await expect(DBOS.withNextWorkflowID(workflowID, () => regReadWorkflowReg(user))).resolves.toEqual({
239
147
  user,
240
148
  greet_count: 10,
241
149
  });
242
150
 
243
- const { rows } = await userDB.query('SELECT * FROM dbos.transaction_completion WHERE workflow_id = $1', [
244
- workflowID,
245
- ]);
151
+ const { rows } = await userDB.query<transaction_completion>(
152
+ 'SELECT * FROM dbos.transaction_completion WHERE workflow_id = $1',
153
+ [workflowID],
154
+ );
246
155
  expect(rows.length).toBe(0);
247
156
  });
248
157
 
@@ -253,7 +162,7 @@ describe('KnexDataSource', () => {
253
162
  await userDB.query('INSERT INTO greetings("name","greet_count") VALUES($1,10);', [user]);
254
163
 
255
164
  const workflowID = randomUUID();
256
- await expect(DBOS.withNextWorkflowID(workflowID, () => regReadWorkflowRunTx(user))).resolves.toMatchObject({
165
+ await expect(DBOS.withNextWorkflowID(workflowID, () => regReadWorkflowRunTx(user))).resolves.toEqual({
257
166
  user,
258
167
  greet_count: 10,
259
168
  });
@@ -270,7 +179,7 @@ describe('KnexDataSource', () => {
270
179
  await userDB.query('DELETE FROM greetings WHERE name = $1', [user]);
271
180
 
272
181
  const workflowID = randomUUID();
273
- await expect(DBOS.withNextWorkflowID(workflowID, () => regStaticWorkflow(user))).resolves.toMatchObject([
182
+ await expect(DBOS.withNextWorkflowID(workflowID, () => regStaticWorkflow(user))).resolves.toEqual([
274
183
  { user, greet_count: 1 },
275
184
  { user, greet_count: 1 },
276
185
  ]);
@@ -282,45 +191,11 @@ describe('KnexDataSource', () => {
282
191
  await userDB.query('DELETE FROM greetings WHERE name = $1', [user]);
283
192
 
284
193
  const workflowID = randomUUID();
285
- await expect(DBOS.withNextWorkflowID(workflowID, () => regInstanceWorkflow(user))).resolves.toMatchObject([
194
+ await expect(DBOS.withNextWorkflowID(workflowID, () => regInstanceWorkflow(user))).resolves.toEqual([
286
195
  { user, greet_count: 1 },
287
196
  { user, greet_count: 1 },
288
197
  ]);
289
198
  });
290
-
291
- test('invoke-reg-tx-fun-outside-wf', async () => {
292
- const user = 'outsideWfUser' + Date.now();
293
- const result = await regInsertFunction(user);
294
- expect(result).toMatchObject({ user, greet_count: 1 });
295
-
296
- const txResults = await userDB.query('SELECT * FROM dbos.transaction_completion WHERE output LIKE $1', [
297
- `%${user}%`,
298
- ]);
299
- expect(txResults.rows.length).toBe(0);
300
- });
301
-
302
- test('invoke-reg-tx-static-method-outside-wf', async () => {
303
- const user = 'outsideWfUser' + Date.now();
304
- const result = await StaticClass.insertFunction(user);
305
- expect(result).toMatchObject({ user, greet_count: 1 });
306
-
307
- const txResults = await userDB.query('SELECT * FROM dbos.transaction_completion WHERE output LIKE $1', [
308
- `%${user}%`,
309
- ]);
310
- expect(txResults.rows.length).toBe(0);
311
- });
312
-
313
- test('invoke-reg-tx-inst-method-outside-wf', async () => {
314
- const user = 'outsideWfUser' + Date.now();
315
- const instance = new InstanceClass();
316
- const result = await instance.insertFunction(user);
317
- expect(result).toMatchObject({ user, greet_count: 1 });
318
-
319
- const txResults = await userDB.query('SELECT * FROM dbos.transaction_completion WHERE output LIKE $1', [
320
- `%${user}%`,
321
- ]);
322
- expect(txResults.rows.length).toBe(0);
323
- });
324
199
  });
325
200
 
326
201
  export interface greetings {
@@ -336,22 +211,23 @@ async function insertFunction(user: string) {
336
211
  .returning('greet_count');
337
212
  const row = rows.length > 0 ? rows[0] : undefined;
338
213
 
339
- return { user, greet_count: row?.greet_count, now: Date.now() };
214
+ return { user, greet_count: row?.greet_count };
340
215
  }
341
216
 
342
217
  async function errorFunction(user: string) {
343
- const _result = await insertFunction(user);
344
- throw new Error(`test error ${Date.now()}`);
218
+ const result = await insertFunction(user);
219
+ throw new Error('test error');
220
+ return result;
345
221
  }
346
222
 
347
223
  async function readFunction(user: string) {
348
224
  const row = await KnexDataSource.client<greetings>('greetings').select('greet_count').where('name', user).first();
349
- return { user, greet_count: row?.greet_count, now: Date.now() };
225
+ return { user, greet_count: row?.greet_count };
350
226
  }
351
227
 
352
- const regInsertFunction = dataSource.registerTransaction(insertFunction);
353
- const regErrorFunction = dataSource.registerTransaction(errorFunction);
354
- const regReadFunction = dataSource.registerTransaction(readFunction, { readOnly: true });
228
+ const regInsertFunction = dataSource.registerTransaction(insertFunction, 'insertFunction');
229
+ const regErrorFunction = dataSource.registerTransaction(errorFunction, 'errorFunction');
230
+ const regReadFunction = dataSource.registerTransaction(readFunction, 'readFunction', { readOnly: true });
355
231
 
356
232
  class StaticClass {
357
233
  static async insertFunction(user: string) {
@@ -363,8 +239,8 @@ class StaticClass {
363
239
  }
364
240
  }
365
241
 
366
- StaticClass.insertFunction = dataSource.registerTransaction(StaticClass.insertFunction);
367
- StaticClass.readFunction = dataSource.registerTransaction(StaticClass.readFunction, { readOnly: true });
242
+ StaticClass.insertFunction = dataSource.registerTransaction(StaticClass.insertFunction, 'insertFunction');
243
+ StaticClass.readFunction = dataSource.registerTransaction(StaticClass.readFunction, 'readFunction');
368
244
 
369
245
  class InstanceClass {
370
246
  async insertFunction(user: string) {
@@ -379,11 +255,12 @@ class InstanceClass {
379
255
  InstanceClass.prototype.insertFunction = dataSource.registerTransaction(
380
256
  // eslint-disable-next-line @typescript-eslint/unbound-method
381
257
  InstanceClass.prototype.insertFunction,
258
+ 'insertFunction',
382
259
  );
383
260
  InstanceClass.prototype.readFunction = dataSource.registerTransaction(
384
261
  // eslint-disable-next-line @typescript-eslint/unbound-method
385
262
  InstanceClass.prototype.readFunction,
386
- { readOnly: true },
263
+ 'readFunction',
387
264
  );
388
265
 
389
266
  async function insertWorkflowReg(user: string) {
@@ -423,8 +300,8 @@ async function instanceWorkflow(user: string) {
423
300
  return [result, readResult];
424
301
  }
425
302
 
426
- const regInsertWorkflowReg = DBOS.registerWorkflow(insertWorkflowReg, 'insertWorkflowReg');
427
- const regInsertWorkflowRunTx = DBOS.registerWorkflow(insertWorkflowRunTx, 'insertWorkflowRunTx');
303
+ const regInsertWorfklowReg = DBOS.registerWorkflow(insertWorkflowReg, 'insertWorkflowReg');
304
+ const regInsertWorfklowRunTx = DBOS.registerWorkflow(insertWorkflowRunTx, 'insertWorkflowRunTx');
428
305
  const regErrorWorkflowReg = DBOS.registerWorkflow(errorWorkflowReg, 'errorWorkflowReg');
429
306
  const regErrorWorkflowRunTx = DBOS.registerWorkflow(errorWorkflowRunTx, 'errorWorkflowRunTx');
430
307
  const regReadWorkflowReg = DBOS.registerWorkflow(readWorkflowReg, 'readWorkflowReg');
@@ -7,7 +7,6 @@ export async function ensureDB(client: Client, name: string) {
7
7
  }
8
8
  }
9
9
 
10
- export async function dropDB(client: Client, name: string, force: boolean = false) {
11
- const withForce = force ? ' WITH (FORCE)' : '';
12
- await client.query(`DROP DATABASE IF EXISTS ${name} ${withForce}`);
10
+ export async function dropDB(client: Client, name: string) {
11
+ await client.query(`DROP DATABASE IF EXISTS ${name}`);
13
12
  }