@dbos-inc/node-pg-datasource 3.0.10-preview → 3.0.11-preview.gc9233b8190

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.
@@ -5,14 +5,13 @@ import { dropDB, ensureDB } from './test-helpers';
5
5
  import { randomUUID } from 'crypto';
6
6
  import { SuperJSON } from 'superjson';
7
7
 
8
- const config = { user: 'postgres', database: 'node_pg_ds_test_datasource' };
8
+ const config = { user: 'postgres', database: 'nodepg_ds_test_userdb' };
9
9
  const dataSource = new NodePostgresDataSource('app-db', config);
10
10
 
11
11
  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('NodePostgresDataSource', () => {
@@ -23,9 +22,9 @@ describe('NodePostgresDataSource', () => {
23
22
  const client = new Client({ ...config, database: 'postgres' });
24
23
  try {
25
24
  await client.connect();
26
- await dropDB(client, 'node_pg_ds_test', true);
27
- await dropDB(client, 'node_pg_ds_test_dbos_sys', true);
28
- await dropDB(client, config.database, true);
25
+ await dropDB(client, 'knex_ds_test');
26
+ await dropDB(client, 'knex_ds_test_dbos_sys');
27
+ await dropDB(client, config.database);
29
28
  await ensureDB(client, config.database);
30
29
  } finally {
31
30
  await client.end();
@@ -44,19 +43,13 @@ describe('NodePostgresDataSource', () => {
44
43
  }
45
44
 
46
45
  await NodePostgresDataSource.initializeInternalSchema(config);
47
- });
48
-
49
- afterAll(async () => {
50
- await userDB.end();
51
- });
52
-
53
- beforeEach(async () => {
54
- DBOS.setConfig({ name: 'node-pg-ds-test' });
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('NodePostgresDataSource', () => {
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('NodePostgresDataSource', () => {
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('NodePostgresDataSource', () => {
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('NodePostgresDataSource', () => {
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 });
116
- });
117
-
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
- );
96
+ expect(SuperJSON.parse(rows[0].output!)).toEqual({ user, greet_count: 1 });
130
97
  });
131
98
 
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,16 @@ describe('NodePostgresDataSource', () => {
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+$/);
106
+ await expect(DBOS.withNextWorkflowID(workflowID, () => regErrorWorkflowReg(user))).rejects.toThrow('test error');
107
+
108
+ const { rows: txOutput } = await userDB.query('SELECT * FROM dbos.transaction_completion WHERE workflow_id = $1', [
109
+ workflowID,
110
+ ]);
111
+ expect(txOutput.length).toBe(0);
151
112
 
152
113
  const { rows } = await userDB.query<greetings>('SELECT * FROM greetings WHERE name = $1', [user]);
153
114
  expect(rows.length).toBe(1);
154
115
  expect(rows[0].greet_count).toBe(10);
155
-
156
- const { rows: txOutput } = await userDB.query<transaction_completion>(
157
- 'SELECT * FROM dbos.transaction_completion WHERE workflow_id = $1',
158
- [workflowID],
159
- );
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+$/);
180
-
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);
184
116
  });
185
117
 
186
118
  test('error dataSource.runAsTx function', async () => {
@@ -190,42 +122,17 @@ describe('NodePostgresDataSource', () => {
190
122
  await userDB.query('INSERT INTO greetings("name","greet_count") VALUES($1,10);', [user]);
191
123
  const workflowID = randomUUID();
192
124
 
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);
125
+ await expect(DBOS.withNextWorkflowID(workflowID, () => regErrorWorkflowRunTx(user))).rejects.toThrow('test error');
200
126
 
201
127
  const { rows: txOutput } = await userDB.query<transaction_completion>(
202
128
  'SELECT * FROM dbos.transaction_completion WHERE workflow_id = $1',
203
129
  [workflowID],
204
130
  );
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';
217
-
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+$/);
131
+ expect(txOutput.length).toBe(0);
225
132
 
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);
133
+ const { rows } = await userDB.query<greetings>('SELECT * FROM greetings WHERE name = $1', [user]);
134
+ expect(rows.length).toBe(1);
135
+ expect(rows[0].greet_count).toBe(10);
229
136
  });
230
137
 
231
138
  test('readonly dataSource.register function', async () => {
@@ -235,14 +142,15 @@ describe('NodePostgresDataSource', () => {
235
142
  await userDB.query('INSERT INTO greetings("name","greet_count") VALUES($1,10);', [user]);
236
143
 
237
144
  const workflowID = randomUUID();
238
- await expect(DBOS.withNextWorkflowID(workflowID, () => regReadWorkflowReg(user))).resolves.toMatchObject({
145
+ await expect(DBOS.withNextWorkflowID(workflowID, () => regReadWorkflowReg(user))).resolves.toEqual({
239
146
  user,
240
147
  greet_count: 10,
241
148
  });
242
149
 
243
- const { rows } = await userDB.query('SELECT * FROM dbos.transaction_completion WHERE workflow_id = $1', [
244
- workflowID,
245
- ]);
150
+ const { rows } = await userDB.query<transaction_completion>(
151
+ 'SELECT * FROM dbos.transaction_completion WHERE workflow_id = $1',
152
+ [workflowID],
153
+ );
246
154
  expect(rows.length).toBe(0);
247
155
  });
248
156
 
@@ -253,14 +161,15 @@ describe('NodePostgresDataSource', () => {
253
161
  await userDB.query('INSERT INTO greetings("name","greet_count") VALUES($1,10);', [user]);
254
162
 
255
163
  const workflowID = randomUUID();
256
- await expect(DBOS.withNextWorkflowID(workflowID, () => regReadWorkflowRunTx(user))).resolves.toMatchObject({
164
+ await expect(DBOS.withNextWorkflowID(workflowID, () => regReadWorkflowRunTx(user))).resolves.toEqual({
257
165
  user,
258
166
  greet_count: 10,
259
167
  });
260
168
 
261
- const { rows } = await userDB.query('SELECT * FROM dbos.transaction_completion WHERE workflow_id = $1', [
262
- workflowID,
263
- ]);
169
+ const { rows } = await userDB.query<transaction_completion>(
170
+ 'SELECT * FROM dbos.transaction_completion WHERE workflow_id = $1',
171
+ [workflowID],
172
+ );
264
173
  expect(rows.length).toBe(0);
265
174
  });
266
175
 
@@ -270,7 +179,7 @@ describe('NodePostgresDataSource', () => {
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('NodePostgresDataSource', () => {
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 {
@@ -330,36 +205,39 @@ export interface greetings {
330
205
 
331
206
  async function insertFunction(user: string) {
332
207
  const { rows } = await NodePostgresDataSource.client.query<Pick<greetings, 'greet_count'>>(
333
- `INSERT INTO greetings(name, greet_count)
334
- VALUES($1, 1)
335
- ON CONFLICT(name)
336
- DO UPDATE SET greet_count = greetings.greet_count + 1
337
- RETURNING greet_count`,
208
+ `
209
+ INSERT INTO greetings(name, greet_count)
210
+ VALUES($1, 1)
211
+ ON CONFLICT(name)
212
+ DO UPDATE SET greet_count = greetings.greet_count + 1
213
+ RETURNING greet_count`,
338
214
  [user],
339
215
  );
340
216
  const row = rows.length > 0 ? rows[0] : undefined;
341
- return { user, greet_count: row?.greet_count, now: Date.now() };
217
+ return { user, greet_count: row?.greet_count };
342
218
  }
343
219
 
344
220
  async function errorFunction(user: string) {
345
- const _result = await insertFunction(user);
346
- throw new Error(`test error ${Date.now()}`);
221
+ const result = await insertFunction(user);
222
+ throw new Error('test error');
223
+ return result;
347
224
  }
348
225
 
349
226
  async function readFunction(user: string) {
350
227
  const { rows } = await NodePostgresDataSource.client.query<Pick<greetings, 'greet_count'>>(
351
- `SELECT greet_count
352
- FROM greetings
353
- WHERE name = $1`,
228
+ `
229
+ SELECT greet_count
230
+ FROM greetings
231
+ WHERE name = $1`,
354
232
  [user],
355
233
  );
356
234
  const row = rows.length > 0 ? rows[0] : undefined;
357
- return { user, greet_count: row?.greet_count, now: Date.now() };
235
+ return { user, greet_count: row?.greet_count };
358
236
  }
359
237
 
360
- const regInsertFunction = dataSource.registerTransaction(insertFunction);
361
- const regErrorFunction = dataSource.registerTransaction(errorFunction);
362
- const regReadFunction = dataSource.registerTransaction(readFunction, { readOnly: true });
238
+ const regInsertFunction = dataSource.registerTransaction(insertFunction, 'insertFunction');
239
+ const regErrorFunction = dataSource.registerTransaction(errorFunction, 'errorFunction');
240
+ const regReadFunction = dataSource.registerTransaction(readFunction, 'readFunction', { readOnly: true });
363
241
 
364
242
  class StaticClass {
365
243
  static async insertFunction(user: string) {
@@ -371,8 +249,8 @@ class StaticClass {
371
249
  }
372
250
  }
373
251
 
374
- StaticClass.insertFunction = dataSource.registerTransaction(StaticClass.insertFunction);
375
- StaticClass.readFunction = dataSource.registerTransaction(StaticClass.readFunction, { readOnly: true });
252
+ StaticClass.insertFunction = dataSource.registerTransaction(StaticClass.insertFunction, 'insertFunction');
253
+ StaticClass.readFunction = dataSource.registerTransaction(StaticClass.readFunction, 'readFunction');
376
254
 
377
255
  class InstanceClass {
378
256
  async insertFunction(user: string) {
@@ -387,11 +265,12 @@ class InstanceClass {
387
265
  InstanceClass.prototype.insertFunction = dataSource.registerTransaction(
388
266
  // eslint-disable-next-line @typescript-eslint/unbound-method
389
267
  InstanceClass.prototype.insertFunction,
268
+ 'insertFunction',
390
269
  );
391
270
  InstanceClass.prototype.readFunction = dataSource.registerTransaction(
392
271
  // eslint-disable-next-line @typescript-eslint/unbound-method
393
272
  InstanceClass.prototype.readFunction,
394
- { readOnly: true },
273
+ 'readFunction',
395
274
  );
396
275
 
397
276
  async function insertWorkflowReg(user: string) {
@@ -431,8 +310,8 @@ async function instanceWorkflow(user: string) {
431
310
  return [result, readResult];
432
311
  }
433
312
 
434
- const regInsertWorkflowReg = DBOS.registerWorkflow(insertWorkflowReg, 'insertWorkflowReg');
435
- const regInsertWorkflowRunTx = DBOS.registerWorkflow(insertWorkflowRunTx, 'insertWorkflowRunTx');
313
+ const regInsertWorfklowReg = DBOS.registerWorkflow(insertWorkflowReg, 'insertWorkflowReg');
314
+ const regInsertWorfklowRunTx = DBOS.registerWorkflow(insertWorkflowRunTx, 'insertWorkflowRunTx');
436
315
  const regErrorWorkflowReg = DBOS.registerWorkflow(errorWorkflowReg, 'errorWorkflowReg');
437
316
  const regErrorWorkflowRunTx = DBOS.registerWorkflow(errorWorkflowRunTx, 'errorWorkflowRunTx');
438
317
  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
  }