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
+8
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
-1
View File
@@ -74,7 +74,6 @@
"ioredis-mock": "8.4.0", "ioredis-mock": "8.4.0",
"iso8601-duration": "^1.3.0", "iso8601-duration": "^1.3.0",
"jsonwebtoken": "^9.0.0", "jsonwebtoken": "^9.0.0",
"knex": "2.4.2",
"lodash": "^4.17.21", "lodash": "^4.17.21",
"medusa-core-utils": "^1.2.0", "medusa-core-utils": "^1.2.0",
"medusa-telemetry": "^0.0.17", "medusa-telemetry": "^0.0.17",
+24 -38
View File
@@ -1,8 +1,6 @@
import { asValue, AwilixContainer } from "awilix" import { asValue, AwilixContainer } from "awilix"
import { ConfigModule } from "../types/global" import { ConfigModule } from "../types/global"
import { ContainerRegistrationKeys } from "@medusajs/utils" import { ContainerRegistrationKeys, ModulesSdkUtils } from "@medusajs/utils"
import { ClientConfig } from "pg"
import knex from "knex"
type Options = { type Options = {
configModule: ConfigModule configModule: ConfigModule
@@ -10,44 +8,32 @@ type Options = {
} }
export default async ({ container, configModule }: Options): Promise<void> => { export default async ({ container, configModule }: Options): Promise<void> => {
const connectionString = configModule.projectConfig.database_url if (container.hasRegistration(ContainerRegistrationKeys.PG_CONNECTION)) {
const database = configModule.projectConfig.database_database return
const extra: any = configModule.projectConfig.database_extra || {} }
const schema = configModule.projectConfig.database_schema || "public"
// Share a knex connection to be consumed by the shared modules // Share a knex connection to be consumed by the shared modules
if (!container.hasRegistration(ContainerRegistrationKeys.PG_CONNECTION)) { const connectionString = configModule.projectConfig.database_url
const config: ClientConfig = { const extra: any = configModule.projectConfig.database_extra || {}
connectionString, const schema = configModule.projectConfig.database_schema || "public"
database, const idleTimeoutMillis = extra.idleTimeoutMillis ?? undefined // prevent null to be passed
ssl: extra?.ssl ?? false, const poolMax = extra.max
idle_in_transaction_session_timeout:
extra.idle_in_transaction_session_timeout ?? undefined, // prevent null to be passed
}
// TODO: see later if it is possible to use the same connection with multiple pool config using this shared connection across the modules delete extra.max
// const pgConnection = await new Client(config).connect() // or any other method to create your connection here delete extra.idleTimeoutMillis
const pgConnection = knex<any, any>({ const pgConnection = ModulesSdkUtils.createPgConnection({
client: "pg", clientUrl: connectionString,
searchPath: schema, schema,
connection: { driverOptions: extra,
connectionString: connectionString, pool: {
database, max: poolMax,
ssl: extra?.ssl ?? false, idleTimeoutMillis,
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
},
})
container.register( container.register(
ContainerRegistrationKeys.PG_CONNECTION, ContainerRegistrationKeys.PG_CONNECTION,
asValue(pgConnection) asValue(pgConnection)
) )
}
} }
+18 -36
View File
@@ -10,8 +10,8 @@ import {
} from "@medusajs/types" } from "@medusajs/types"
import { import {
ContainerRegistrationKeys, ContainerRegistrationKeys,
ModulesSdkUtils,
isObject, isObject,
ModulesSdkUtils,
} from "@medusajs/utils" } from "@medusajs/utils"
import { MODULE_PACKAGE_NAMES, Modules } from "./definitions" import { MODULE_PACKAGE_NAMES, Modules } from "./definitions"
import { MedusaModule } from "./medusa-module" import { MedusaModule } from "./medusa-module"
@@ -19,21 +19,12 @@ import { RemoteLink } from "./remote-link"
import { RemoteQuery } from "./remote-query" import { RemoteQuery } from "./remote-query"
export type MedusaModuleConfig = (Partial<ModuleConfig> | Modules)[] export type MedusaModuleConfig = (Partial<ModuleConfig> | Modules)[]
export type SharedResources = { type SharedResources = {
database?: ModuleServiceInitializeOptions["database"] & { database?: ModuleServiceInitializeOptions["database"]
pool?: { }
name?: string
afterCreate?: Function const isModuleConfig = (obj: any): obj is ModuleConfig => {
min?: number return isObject(obj)
max?: number
refreshIdle?: boolean
idleTimeoutMillis?: number
reapIntervalMillis?: number
returnToHead?: boolean
priorityRange?: number
log?: (message: string, logLevel: string) => void
}
}
} }
export async function MedusaApp({ export async function MedusaApp({
@@ -77,25 +68,16 @@ export async function MedusaApp({
sharedResourcesConfig as ModuleServiceInitializeOptions, sharedResourcesConfig as ModuleServiceInitializeOptions,
true true
)! )!
const { pool } = sharedResourcesConfig?.database ?? {}
if (dbData?.clientUrl) { if (
const { knex } = await import("knex") dbData.clientUrl &&
const dbConnection = knex({ !injectedDependencies[ContainerRegistrationKeys.PG_CONNECTION]
client: "pg", ) {
searchPath: dbData.schema || "public", injectedDependencies[ContainerRegistrationKeys.PG_CONNECTION] =
connection: { ModulesSdkUtils.createPgConnection({
connectionString: dbData.clientUrl, ...(sharedResourcesConfig?.database ?? {}),
ssl: (dbData.driverOptions?.connection as any).ssl! ?? false, ...dbData,
}, })
pool: {
// https://knexjs.org/guide/#pool
...(pool ?? {}),
min: pool?.min ?? 0,
},
})
injectedDependencies[ContainerRegistrationKeys.PG_CONNECTION] = dbConnection
} }
const allModules: Record<string, LoadedModule | LoadedModule[]> = {} const allModules: Record<string, LoadedModule | LoadedModule[]> = {}
@@ -106,7 +88,7 @@ export async function MedusaApp({
let path: string let path: string
let declaration: any = {} let declaration: any = {}
if (isObject(mod)) { if (isModuleConfig(mod)) {
if (!mod.module) { if (!mod.module) {
throw new Error( throw new Error(
`Module ${JSON.stringify(mod)} is missing module name.` `Module ${JSON.stringify(mod)} is missing module name.`
@@ -141,7 +123,7 @@ export async function MedusaApp({
declaration, declaration,
undefined, undefined,
injectedDependencies, injectedDependencies,
isObject(mod) ? mod.definition : undefined isModuleConfig(mod) ? mod.definition : undefined
)) as LoadedModule )) as LoadedModule
if (allModules[key] && !Array.isArray(allModules[key])) { if (allModules[key] && !Array.isArray(allModules[key])) {
+1
View File
@@ -202,6 +202,7 @@ export interface ModuleServiceInitializeOptions {
database?: string database?: string
driverOptions?: Record<string, unknown> driverOptions?: Record<string, unknown>
debug?: boolean debug?: boolean
pool?: Record<string, unknown>
} }
} }
+1
View File
@@ -32,6 +32,7 @@
"@mikro-orm/migrations": "5.7.12", "@mikro-orm/migrations": "5.7.12",
"@mikro-orm/postgresql": "5.7.12", "@mikro-orm/postgresql": "5.7.12",
"awilix": "^8.0.1", "awilix": "^8.0.1",
"knex": "2.4.2",
"ulid": "^2.3.0" "ulid": "^2.3.0"
}, },
"scripts": { "scripts": {
@@ -36,5 +36,6 @@ export async function mikroOrmCreateConnection(
migrations: { migrations: {
path: pathToMigrations, path: pathToMigrations,
}, },
pool: database.pool as any,
}) })
} }
@@ -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,
},
})
}
+1
View File
@@ -3,3 +3,4 @@ export * from "./decorators"
export * from "./build-query" export * from "./build-query"
export * from "./retrieve-entity" export * from "./retrieve-entity"
export * from "./loaders/mikro-orm-connection-loader" export * from "./loaders/mikro-orm-connection-loader"
export * from "./create-pg-connection"
+1 -1
View File
@@ -6461,7 +6461,6 @@ __metadata:
iso8601-duration: ^1.3.0 iso8601-duration: ^1.3.0
jest: ^25.5.4 jest: ^25.5.4
jsonwebtoken: ^9.0.0 jsonwebtoken: ^9.0.0
knex: 2.4.2
lodash: ^4.17.21 lodash: ^4.17.21
medusa-core-utils: ^1.2.0 medusa-core-utils: ^1.2.0
medusa-interfaces: ^1.3.7 medusa-interfaces: ^1.3.7
@@ -6734,6 +6733,7 @@ __metadata:
cross-env: ^5.2.1 cross-env: ^5.2.1
express: ^4.18.2 express: ^4.18.2
jest: ^29.6.3 jest: ^29.6.3
knex: 2.4.2
rimraf: ^5.0.1 rimraf: ^5.0.1
ts-jest: ^29.1.1 ts-jest: ^29.1.1
typescript: ^5.1.6 typescript: ^5.1.6