feat(utils, module-sdk, medusa): Extract pg connection utils to utils package (#4961)

This commit is contained in:
Adrien de Peretti
2023-09-11 12:10:40 +02:00
committed by GitHub
parent fbae7f9654
commit 6273b4b160
10 changed files with 85 additions and 76 deletions

View File

@@ -0,0 +1,8 @@
---
"@medusajs/medusa": patch
"@medusajs/modules-sdk": patch
"@medusajs/types": patch
"@medusajs/utils": patch
---
feat(utils, module-sdk, medusa, types): Extract pg connection utils to utils package

View File

@@ -74,7 +74,6 @@
"ioredis-mock": "8.4.0",
"iso8601-duration": "^1.3.0",
"jsonwebtoken": "^9.0.0",
"knex": "2.4.2",
"lodash": "^4.17.21",
"medusa-core-utils": "^1.2.0",
"medusa-telemetry": "^0.0.17",

View File

@@ -1,8 +1,6 @@
import { asValue, AwilixContainer } from "awilix"
import { ConfigModule } from "../types/global"
import { ContainerRegistrationKeys } from "@medusajs/utils"
import { ClientConfig } from "pg"
import knex from "knex"
import { ContainerRegistrationKeys, ModulesSdkUtils } from "@medusajs/utils"
type Options = {
configModule: ConfigModule
@@ -10,44 +8,32 @@ type Options = {
}
export default async ({ container, configModule }: Options): Promise<void> => {
const connectionString = configModule.projectConfig.database_url
const database = configModule.projectConfig.database_database
const extra: any = configModule.projectConfig.database_extra || {}
const schema = configModule.projectConfig.database_schema || "public"
if (container.hasRegistration(ContainerRegistrationKeys.PG_CONNECTION)) {
return
}
// Share a knex connection to be consumed by the shared modules
if (!container.hasRegistration(ContainerRegistrationKeys.PG_CONNECTION)) {
const config: ClientConfig = {
connectionString,
database,
ssl: extra?.ssl ?? false,
idle_in_transaction_session_timeout:
extra.idle_in_transaction_session_timeout ?? undefined, // prevent null to be passed
}
const connectionString = configModule.projectConfig.database_url
const extra: any = configModule.projectConfig.database_extra || {}
const schema = configModule.projectConfig.database_schema || "public"
const idleTimeoutMillis = extra.idleTimeoutMillis ?? undefined // prevent null to be passed
const poolMax = extra.max
// TODO: see later if it is possible to use the same connection with multiple pool config using this shared connection across the modules
// const pgConnection = await new Client(config).connect() // or any other method to create your connection here
delete extra.max
delete extra.idleTimeoutMillis
const pgConnection = knex<any, any>({
client: "pg",
searchPath: schema,
connection: {
connectionString: connectionString,
database,
ssl: extra?.ssl ?? false,
idle_in_transaction_session_timeout:
extra.idle_in_transaction_session_timeout ?? undefined, // prevent null to be passed
},
pool: {
min: 0,
max: extra.max,
idleTimeoutMillis: extra.idleTimeoutMillis ?? undefined, // prevent null to be passed
},
})
const pgConnection = ModulesSdkUtils.createPgConnection({
clientUrl: connectionString,
schema,
driverOptions: extra,
pool: {
max: poolMax,
idleTimeoutMillis,
},
})
container.register(
ContainerRegistrationKeys.PG_CONNECTION,
asValue(pgConnection)
)
}
container.register(
ContainerRegistrationKeys.PG_CONNECTION,
asValue(pgConnection)
)
}

View File

@@ -10,8 +10,8 @@ import {
} from "@medusajs/types"
import {
ContainerRegistrationKeys,
ModulesSdkUtils,
isObject,
ModulesSdkUtils,
} from "@medusajs/utils"
import { MODULE_PACKAGE_NAMES, Modules } from "./definitions"
import { MedusaModule } from "./medusa-module"
@@ -19,21 +19,12 @@ import { RemoteLink } from "./remote-link"
import { RemoteQuery } from "./remote-query"
export type MedusaModuleConfig = (Partial<ModuleConfig> | Modules)[]
export type SharedResources = {
database?: ModuleServiceInitializeOptions["database"] & {
pool?: {
name?: string
afterCreate?: Function
min?: number
max?: number
refreshIdle?: boolean
idleTimeoutMillis?: number
reapIntervalMillis?: number
returnToHead?: boolean
priorityRange?: number
log?: (message: string, logLevel: string) => void
}
}
type SharedResources = {
database?: ModuleServiceInitializeOptions["database"]
}
const isModuleConfig = (obj: any): obj is ModuleConfig => {
return isObject(obj)
}
export async function MedusaApp({
@@ -77,25 +68,16 @@ export async function MedusaApp({
sharedResourcesConfig as ModuleServiceInitializeOptions,
true
)!
const { pool } = sharedResourcesConfig?.database ?? {}
if (dbData?.clientUrl) {
const { knex } = await import("knex")
const dbConnection = knex({
client: "pg",
searchPath: dbData.schema || "public",
connection: {
connectionString: dbData.clientUrl,
ssl: (dbData.driverOptions?.connection as any).ssl! ?? false,
},
pool: {
// https://knexjs.org/guide/#pool
...(pool ?? {}),
min: pool?.min ?? 0,
},
})
injectedDependencies[ContainerRegistrationKeys.PG_CONNECTION] = dbConnection
if (
dbData.clientUrl &&
!injectedDependencies[ContainerRegistrationKeys.PG_CONNECTION]
) {
injectedDependencies[ContainerRegistrationKeys.PG_CONNECTION] =
ModulesSdkUtils.createPgConnection({
...(sharedResourcesConfig?.database ?? {}),
...dbData,
})
}
const allModules: Record<string, LoadedModule | LoadedModule[]> = {}
@@ -106,7 +88,7 @@ export async function MedusaApp({
let path: string
let declaration: any = {}
if (isObject(mod)) {
if (isModuleConfig(mod)) {
if (!mod.module) {
throw new Error(
`Module ${JSON.stringify(mod)} is missing module name.`
@@ -141,7 +123,7 @@ export async function MedusaApp({
declaration,
undefined,
injectedDependencies,
isObject(mod) ? mod.definition : undefined
isModuleConfig(mod) ? mod.definition : undefined
)) as LoadedModule
if (allModules[key] && !Array.isArray(allModules[key])) {

View File

@@ -202,6 +202,7 @@ export interface ModuleServiceInitializeOptions {
database?: string
driverOptions?: Record<string, unknown>
debug?: boolean
pool?: Record<string, unknown>
}
}

View File

@@ -32,6 +32,7 @@
"@mikro-orm/migrations": "5.7.12",
"@mikro-orm/postgresql": "5.7.12",
"awilix": "^8.0.1",
"knex": "2.4.2",
"ulid": "^2.3.0"
},
"scripts": {

View File

@@ -36,5 +36,6 @@ export async function mikroOrmCreateConnection(
migrations: {
path: pathToMigrations,
},
pool: database.pool as any,
})
}

View File

@@ -0,0 +1,30 @@
import knex from "knex"
import { ModuleServiceInitializeOptions } from "@medusajs/types"
type Options = ModuleServiceInitializeOptions["database"]
/**
* Create a new knex (pg in the future) connection which can be reused and shared
* @param options
*/
export function createPgConnection(options: Options) {
const { pool, schema = "public", clientUrl, driverOptions } = options
const ssl = options.driverOptions?.ssl ?? false
return knex<any, any>({
client: "pg",
searchPath: schema,
connection: {
connectionString: clientUrl,
ssl,
idle_in_transaction_session_timeout:
(driverOptions?.idle_in_transaction_session_timeout as number) ??
undefined, // prevent null to be passed
},
pool: {
// https://knexjs.org/guide/#pool
...(pool ?? {}),
min: (pool?.min as number) ?? 0,
},
})
}

View File

@@ -3,3 +3,4 @@ export * from "./decorators"
export * from "./build-query"
export * from "./retrieve-entity"
export * from "./loaders/mikro-orm-connection-loader"
export * from "./create-pg-connection"

View File

@@ -6461,7 +6461,6 @@ __metadata:
iso8601-duration: ^1.3.0
jest: ^25.5.4
jsonwebtoken: ^9.0.0
knex: 2.4.2
lodash: ^4.17.21
medusa-core-utils: ^1.2.0
medusa-interfaces: ^1.3.7
@@ -6734,6 +6733,7 @@ __metadata:
cross-env: ^5.2.1
express: ^4.18.2
jest: ^29.6.3
knex: 2.4.2
rimraf: ^5.0.1
ts-jest: ^29.1.1
typescript: ^5.1.6