-
Notifications
You must be signed in to change notification settings - Fork 3.7k
Expand file tree
/
Copy pathbeginTransaction.ts
More file actions
71 lines (61 loc) · 2.18 KB
/
beginTransaction.ts
File metadata and controls
71 lines (61 loc) · 2.18 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
import type { BeginTransaction } from 'payload'
import { v4 as uuid } from 'uuid'
import type { DrizzleAdapter, DrizzleTransaction } from '../types.js'
export const beginTransaction: BeginTransaction = async function beginTransaction(
this: DrizzleAdapter,
options: DrizzleAdapter['transactionOptions'],
) {
let id
try {
id = uuid()
let reject: () => Promise<void>
let resolve: () => Promise<void>
let transaction: DrizzleTransaction
let transactionReady: () => void
let transactionFailed: (err: unknown) => void
// Await initialization here
// Prevent race conditions where the adapter may be
// re-initializing, and `this.drizzle` is potentially undefined
await this.initializing
// Drizzle only exposes a transactions API that is sufficient if you
// can directly pass around the `tx` argument. But our operations are spread
// over many files and we don't want to pass the `tx` around like that,
// so instead, we "lift" up the `resolve` and `reject` methods
// and will call them in our respective transaction methods
const done = this.drizzle
.transaction(async (tx) => {
transaction = tx
await new Promise<void>((res, rej) => {
resolve = () => {
res()
return done
}
reject = () => {
// eslint-disable-next-line @typescript-eslint/prefer-promise-reject-errors
rej()
return done
}
transactionReady()
})
}, options || this.transactionOptions)
.catch((err) => {
// Connection failed before callback ran - reject instead of hanging forever
transactionFailed(err)
})
// Need to wait until the transaction is ready
// before binding its `resolve` and `reject` methods below
await new Promise<void>((res, rej) => {
transactionReady = res
transactionFailed = rej
})
this.sessions[id] = {
db: transaction,
reject,
resolve,
}
} catch (err) {
this.payload.logger.error({ err, msg: `Error: cannot begin transaction: ${err.message}` })
throw new Error(`Error: cannot begin transaction: ${err.message}`)
}
return id
}