Skip to content

Commit

Permalink
fix(db-postgres): too many clients already, cannot read properties 't…
Browse files Browse the repository at this point in the history
…ransaction' of undefined (#6338)
  • Loading branch information
jmikrut authored May 13, 2024
1 parent 0d98b4b commit 47cd5f4
Show file tree
Hide file tree
Showing 5 changed files with 34 additions and 9 deletions.
21 changes: 12 additions & 9 deletions packages/db-postgres/src/connect.ts
Original file line number Diff line number Diff line change
Expand Up @@ -61,11 +61,12 @@ export const connect: Connect = async function connect(
}

try {
this.pool = new pg.Pool(this.poolOptions)
await connectWithReconnect({ adapter: this, payload: this.payload })
if (!this.pool) {
this.pool = new pg.Pool(this.poolOptions)
await connectWithReconnect({ adapter: this, payload: this.payload })
}

const logger = this.logger || false

this.drizzle = drizzle(this.pool, { logger, schema: this.schema })

if (!hotReload) {
Expand All @@ -82,16 +83,18 @@ export const connect: Connect = async function connect(
}
} catch (err) {
this.payload.logger.error(`Error: cannot connect to Postgres. Details: ${err.message}`, err)
if (typeof this.rejectInitializing === 'function') this.rejectInitializing()
process.exit(1)
}

// Only push schema if not in production
if (
process.env.NODE_ENV === 'production' ||
process.env.PAYLOAD_MIGRATING === 'true' ||
this.push === false
)
return
process.env.NODE_ENV !== 'production' &&
process.env.PAYLOAD_MIGRATING !== 'true' &&
this.push !== false
) {
await pushDevSchema(this)
}

await pushDevSchema(this)
if (typeof this.resolveInitializing === 'function') this.resolveInitializing()
}
4 changes: 4 additions & 0 deletions packages/db-postgres/src/destroy.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,4 +10,8 @@ export const destroy: Destroy = async function destroy(this: PostgresAdapter) {
this.relations = {}
this.fieldConstraints = {}
this.drizzle = undefined
this.initializing = new Promise((res, rej) => {
this.resolveInitializing = res
this.rejectInitializing = rej
})
}
10 changes: 10 additions & 0 deletions packages/db-postgres/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -49,13 +49,21 @@ export function postgresAdapter(args: Args): DatabaseAdapterObj<PostgresAdapter>

function adapter({ payload }: { payload: Payload }) {
const migrationDir = findMigrationDir(args.migrationDir)
let resolveInitializing
let rejectInitializing

const initializing = new Promise<void>((res, rej) => {
resolveInitializing = res
rejectInitializing = rej
})

return createDatabaseAdapter<PostgresAdapter>({
name: 'postgres',
drizzle: undefined,
enums: {},
fieldConstraints: {},
idType: postgresIDType,
initializing,
localesSuffix: args.localesSuffix || '_locales',
logger: args.logger,
pgSchema: undefined,
Expand Down Expand Up @@ -101,6 +109,8 @@ export function postgresAdapter(args: Args): DatabaseAdapterObj<PostgresAdapter>
migrationDir,
payload,
queryDrafts,
rejectInitializing,
resolveInitializing,
rollbackTransaction,
updateGlobal,
updateGlobalVersion,
Expand Down
5 changes: 5 additions & 0 deletions packages/db-postgres/src/transactions/beginTransaction.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,11 @@ export const beginTransaction: BeginTransaction = async function beginTransactio

let transactionReady: () => 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,
Expand Down
3 changes: 3 additions & 0 deletions packages/db-postgres/src/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -69,14 +69,17 @@ export type PostgresAdapter = BaseDatabaseAdapter & {
*/
fieldConstraints: Record<string, Record<string, string>>
idType: Args['idType']
initializing: Promise<void>
localesSuffix?: string
logger: DrizzleConfig['logger']
pgSchema?: { table: PgTableFn } | PgSchema
pool: Pool
poolOptions: Args['pool']
push: boolean
rejectInitializing: () => void
relations: Record<string, GenericRelation>
relationshipsSuffix?: string
resolveInitializing: () => void
schema: Record<string, GenericEnum | GenericRelation | GenericTable>
schemaName?: Args['schemaName']
sessions: {
Expand Down

0 comments on commit 47cd5f4

Please sign in to comment.