Skip to content

Commit 5ec2894

Browse files
committed
feat(transaction-manager): the transactions are now capable of returning results
1 parent dbd1f0f commit 5ec2894

File tree

6 files changed

+51
-16
lines changed

6 files changed

+51
-16
lines changed

config/tsconfig/base.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
"$schema": "https://json.schemastore.org/tsconfig",
33
"display": "Base",
44
"compilerOptions": {
5+
"allowUnreachableCode": false,
56
"composite": false,
67
"declaration": true,
78
"declarationMap": true,

lib/postgres/src/__tests__/pg-transaction-manager.test.ts

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -67,6 +67,36 @@ describe('PgTransactionManager', () => {
6767
await expectEntries(db, [{ id: firstId }, { id: secondId }]);
6868
});
6969

70+
test('returns result from transaction', async () => {
71+
const firstId = Uuid.generate();
72+
const secondId = Uuid.generate();
73+
74+
const result = await manager.startTransaction(async (transaction) => {
75+
await transaction.context
76+
.insert(testTable)
77+
.values([{ id: firstId }, { id: secondId }]);
78+
79+
return true;
80+
});
81+
82+
expect(result).toBe(true);
83+
});
84+
85+
test('returns undefined when transaction is rolled back', async () => {
86+
const firstId = Uuid.generate();
87+
const secondId = Uuid.generate();
88+
89+
const result = await manager.startTransaction(async (transaction) => {
90+
await transaction.context
91+
.insert(testTable)
92+
.values([{ id: firstId }, { id: secondId }]);
93+
94+
await transaction.rollback();
95+
});
96+
97+
expect(result).toBeUndefined();
98+
});
99+
70100
test('transaction is not committed when rolled back', async () => {
71101
const firstId = Uuid.generate();
72102
const secondId = Uuid.generate();

lib/postgres/src/nestjs/drizzle-orm.module.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -123,5 +123,5 @@ export class DrizzleOrmModule {
123123
};
124124
}
125125

126-
private static OPTIONS_PROVIDER_TOKEN = Symbol('OPTIONS_PROVIDER_TOKEN');
126+
private static OPTIONS_PROVIDER_TOKEN = Symbol('__optionsProviderToken__');
127127
}

lib/postgres/src/nestjs/pg-client.module.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -132,5 +132,5 @@ export class PgClientModule
132132
};
133133
}
134134

135-
private static OPTIONS_PROVIDER_TOKEN = Symbol('OPTIONS_PROVIDER_TOKEN');
135+
private static OPTIONS_PROVIDER_TOKEN = Symbol('__optionsProviderToken__');
136136
}

lib/postgres/src/pg-transaction-manager.ts

Lines changed: 17 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -12,35 +12,39 @@ export class PgTransactionManager extends TransactionManager {
1212
super();
1313
}
1414

15-
public startTransaction(
16-
callback: (transaction: PgTransaction) => Promise<void>
17-
): Promise<void> {
18-
return PgTransactionManager.createTransaction(this.db, callback);
15+
public startTransaction<Result>(
16+
callback: (transaction: PgTransaction) => Promise<Result>
17+
) {
18+
return PgTransactionManager.createTransaction<Result>(this.db, callback);
1919
}
2020

21-
public savePoint(
21+
public savePoint<Result>(
2222
transaction: PgTransaction,
23-
callback: (nestedTransaction: PgTransaction) => Promise<void>
24-
): Promise<void> {
25-
return PgTransactionManager.createTransaction(
23+
callback: (nestedTransaction: PgTransaction) => Promise<Result>
24+
) {
25+
return PgTransactionManager.createTransaction<Result>(
2626
transaction.context,
2727
callback
2828
);
2929
}
3030

3131
private static store = new AsyncLocalStorage<NodePgDatabaseTransaction>();
3232

33-
private static async createTransaction(
33+
private static async createTransaction<Result>(
3434
pgDriver: NodePgDatabase | NodePgDatabaseTransaction,
35-
callback: (transaction: PgTransaction) => Promise<void>
36-
): Promise<void> {
35+
callback: (transaction: PgTransaction) => Promise<Result>
36+
) {
3737
try {
38-
await pgDriver.transaction((context) => {
38+
const res = await pgDriver.transaction<Result>((context) => {
3939
const transaction = new PgTransaction(this.store);
4040
return this.store.run(context, () => callback(transaction));
4141
});
42+
return res;
4243
} catch (error) {
43-
if (error instanceof TransactionRollbackError) return;
44+
// Needed to cast because unreachable code after a `rollback` is not detected by the TypeScript compiler,
45+
// even though the `ReturnType` of the `rollback` is `never`
46+
// This is a workaround to make it work for now until it's fixed.
47+
if (error instanceof TransactionRollbackError) return undefined as Result;
4448
const err = error instanceof Error ? error : new Error('Unknown error');
4549
throw new InvalidOperationException(err.message, error);
4650
}

lib/postgres/src/pg-transaction.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ export class PgTransaction implements Transaction {
1818
return context;
1919
}
2020

21-
public rollback(): Promise<void> {
21+
public rollback(): Promise<never> {
2222
return Promise.resolve(this.context.rollback());
2323
}
2424
}

0 commit comments

Comments
 (0)