Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(types, product, utils, medusa): Include shared connection for modules #4626

Merged
merged 35 commits into from
Aug 8, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
35 commits
Select commit Hold shift + click to select a range
e464bb2
feat(types, product, utils, medusa): Include shared connection for mo…
adrien2p Jul 27, 2023
a638794
cleanup
adrien2p Jul 27, 2023
6ad462c
update import
adrien2p Jul 27, 2023
872ecf1
fix knex version
adrien2p Jul 27, 2023
87d8403
remove only
adrien2p Jul 27, 2023
6d39b02
Create giant-shirts-remember.md
adrien2p Jul 27, 2023
65a9ddf
fix connection loader
adrien2p Jul 28, 2023
85e177c
cleanup
adrien2p Jul 28, 2023
a597c22
finalise shared connection consumption
adrien2p Jul 28, 2023
f9263a8
Merge branch 'develop' into feat/shared-module-connection
adrien2p Jul 28, 2023
c38877c
fix tests
adrien2p Jul 28, 2023
e36d7f5
Merge branch 'develop' into feat/shared-module-connection
adrien2p Jul 31, 2023
80220f4
Merge branch 'develop' into feat/shared-module-connection
adrien2p Jul 31, 2023
d4b6482
fixes
adrien2p Jul 31, 2023
c4d32a4
Merge branch 'feat/shared-module-connection' of github.com:medusajs/m…
adrien2p Jul 31, 2023
142d4b4
Merge branch 'develop' into feat/shared-module-connection
adrien2p Jul 31, 2023
fb431da
merge conflict
adrien2p Jul 31, 2023
ccecd0e
cleanup + fix product module service create type
adrien2p Jul 31, 2023
8d7fa49
remove changeset to re generate it
adrien2p Jul 31, 2023
1e6d2bb
Create lucky-poets-jog.md
adrien2p Jul 31, 2023
3b87597
Merge branch 'develop' into feat/shared-module-connection
adrien2p Jul 31, 2023
5612b94
Merge branch 'develop' into feat/shared-module-connection
adrien2p Aug 2, 2023
cf07ca0
WIP
adrien2p Aug 2, 2023
441c071
move deps
adrien2p Aug 2, 2023
465244b
merge conflict
adrien2p Aug 7, 2023
f867076
create mikro orm connection loader util
adrien2p Aug 7, 2023
9052691
cleanup loader util
adrien2p Aug 7, 2023
6e28a6e
fix entities
adrien2p Aug 7, 2023
8cf9b70
fix options
adrien2p Aug 7, 2023
5e08077
rename loader
adrien2p Aug 7, 2023
484a3bd
fixes
adrien2p Aug 8, 2023
0d8680c
fix config
adrien2p Aug 8, 2023
7cec3cd
enum
adrien2p Aug 8, 2023
aaf02e1
Merge branch 'develop' into feat/shared-module-connection
adrien2p Aug 8, 2023
d3543de
Merge branch 'develop' into feat/shared-module-connection
adrien2p Aug 8, 2023
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 9 additions & 0 deletions .changeset/lucky-poets-jog.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
---
"@medusajs/medusa": patch
"@medusajs/modules-sdk": patch
"@medusajs/product": patch
"@medusajs/types": patch
"@medusajs/utils": patch
---

[WIP] feat(types, product, utils, medusa): Include shared connection for modules
2 changes: 2 additions & 0 deletions packages/medusa/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,7 @@
"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.16",
Expand All @@ -86,6 +87,7 @@
"passport-http-bearer": "^1.0.1",
"passport-jwt": "^4.0.1",
"passport-local": "^1.0.0",
"pg": "^8.11.2",
"qs": "^6.11.2",
"randomatic": "^3.1.1",
"redis": "^3.0.2",
Expand Down
13 changes: 9 additions & 4 deletions packages/medusa/src/loaders/database.ts
Original file line number Diff line number Diff line change
Expand Up @@ -40,12 +40,17 @@ export default async ({
}: Options): Promise<DataSource> => {
const entities = container.resolve("db_entities")

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"

dataSource = new DataSource({
type: "postgres",
url: configModule.projectConfig.database_url,
database: configModule.projectConfig.database_database,
extra: configModule.projectConfig.database_extra || {},
schema: configModule.projectConfig.database_schema,
url: connectionString,
database: database,
extra,
schema,
entities,
migrations: customOptions?.migrations,
logging:
Expand Down
15 changes: 12 additions & 3 deletions packages/medusa/src/loaders/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,8 @@ import subscribersLoader from "./subscribers"

import { moduleLoader, registerModules } from "@medusajs/modules-sdk"
import { createMedusaContainer } from "medusa-core-utils"
import pgConnectionLoader from "./pg-connection"
import { ContainerRegistrationKeys } from "@medusajs/utils"

type Options = {
directory: string
Expand All @@ -44,7 +46,10 @@ export default async ({
const configModule = loadConfig(rootDirectory)

const container = createMedusaContainer()
container.register("configModule", asValue(configModule))
container.register(
ContainerRegistrationKeys.CONFIG_MODULE,
asValue(configModule)
)

// Add additional information to context of request
expressApp.use((req: Request, res: Response, next: NextFunction) => {
Expand All @@ -59,7 +64,7 @@ export default async ({
track("FEATURE_FLAGS_LOADED")

container.register({
logger: asValue(Logger),
[ContainerRegistrationKeys.LOGGER]: asValue(Logger),
featureFlagRouter: asValue(featureFlagRouter),
})

Expand Down Expand Up @@ -87,6 +92,8 @@ export default async ({
const stratAct = Logger.success(stratActivity, "Strategies initialized") || {}
track("STRATEGIES_INIT_COMPLETED", { duration: stratAct.duration })

await pgConnectionLoader({ container, configModule })

const modulesActivity = Logger.activity(`Initializing modules${EOL}`)
track("MODULES_INIT_STARTED")
await moduleLoader({
Expand All @@ -112,7 +119,9 @@ export default async ({
const rAct = Logger.success(repoActivity, "Repositories initialized") || {}
track("REPOSITORIES_INIT_COMPLETED", { duration: rAct.duration })

container.register({ manager: asValue(dataSource.manager) })
container.register({
[ContainerRegistrationKeys.MANAGER]: asValue(dataSource.manager),
})

const servicesActivity = Logger.activity(`Initializing services${EOL}`)
track("SERVICES_INIT_STARTED")
Expand Down
53 changes: 53 additions & 0 deletions packages/medusa/src/loaders/pg-connection.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
import { asValue, AwilixContainer } from "awilix"
import { ConfigModule } from "../types/global"
import { ContainerRegistrationKeys } from "@medusajs/utils"
import { ClientConfig } from "pg"
import knex from "knex"

type Options = {
configModule: ConfigModule
container: AwilixContainer
}

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"

// 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
}

// 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

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
},
})

container.register(
ContainerRegistrationKeys.PG_CONNECTION,
asValue(pgConnection)
)
}
}
35 changes: 22 additions & 13 deletions packages/modules-sdk/src/definitions.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,15 +13,27 @@ export enum Modules {
}

export enum ModuleRegistrationName {
EVENT_BUS = "eventBusModuleService"
EVENT_BUS = "eventBusModuleService",
STOCK_LOCATION = "stockLocationService",
INVENTORY = "inventoryService",
CACHE = "cacheService",
PRODUCT = "productModuleService",
}

export const MODULE_PACKAGE_NAMES = {
[Modules.PRODUCT]: "@medusajs/product",
[Modules.EVENT_BUS]: "@medusajs/event-bus-local",
[Modules.STOCK_LOCATION]: "@medusajs/stock-location",
[Modules.INVENTORY]: "@medusajs/inventory",
[Modules.CACHE]: "@medusajs/cache-inmemory",
}

export const ModulesDefinition: { [key: string | Modules]: ModuleDefinition } =
{
[Modules.EVENT_BUS]: {
key: Modules.EVENT_BUS,
registrationName: ModuleRegistrationName.EVENT_BUS,
defaultPackage: "@medusajs/event-bus-local",
defaultPackage: MODULE_PACKAGE_NAMES[Modules.EVENT_BUS],
label: "EventBusModuleService",
canOverride: true,
isRequired: true,
Expand All @@ -33,7 +45,7 @@ export const ModulesDefinition: { [key: string | Modules]: ModuleDefinition } =
},
[Modules.STOCK_LOCATION]: {
key: Modules.STOCK_LOCATION,
registrationName: "stockLocationService",
registrationName: ModuleRegistrationName.STOCK_LOCATION,
defaultPackage: false,
label: "StockLocationService",
isRequired: false,
Expand All @@ -47,7 +59,7 @@ export const ModulesDefinition: { [key: string | Modules]: ModuleDefinition } =
},
[Modules.INVENTORY]: {
key: Modules.INVENTORY,
registrationName: "inventoryService",
registrationName: ModuleRegistrationName.INVENTORY,
defaultPackage: false,
label: "InventoryService",
isRequired: false,
Expand All @@ -61,8 +73,8 @@ export const ModulesDefinition: { [key: string | Modules]: ModuleDefinition } =
},
[Modules.CACHE]: {
key: Modules.CACHE,
registrationName: "cacheService",
defaultPackage: "@medusajs/cache-inmemory",
registrationName: ModuleRegistrationName.CACHE,
defaultPackage: MODULE_PACKAGE_NAMES[Modules.CACHE],
label: "CacheService",
isRequired: true,
canOverride: true,
Expand All @@ -73,24 +85,21 @@ export const ModulesDefinition: { [key: string | Modules]: ModuleDefinition } =
},
[Modules.PRODUCT]: {
key: Modules.PRODUCT,
registrationName: "productModuleService",
registrationName: ModuleRegistrationName.PRODUCT,
defaultPackage: false,
label: "ProductModuleService",
isRequired: false,
canOverride: true,
isQueryable: true,
dependencies: [ModuleRegistrationName.EVENT_BUS],
dependencies: [ModuleRegistrationName.EVENT_BUS, "logger"],
defaultModuleDeclaration: {
scope: MODULE_SCOPE.EXTERNAL,
scope: MODULE_SCOPE.INTERNAL,
resources: MODULE_RESOURCE_TYPE.SHARED,
},
},
}

export const MODULE_DEFINITIONS: ModuleDefinition[] =
Object.values(ModulesDefinition)

export const MODULE_PACKAGE_NAMES = {
[Modules.PRODUCT]: "@medusajs/product",
}

export default MODULE_DEFINITIONS
12 changes: 10 additions & 2 deletions packages/modules-sdk/src/loaders/utils/load-internal.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,10 @@ import {
ModuleExports,
ModuleResolution,
} from "@medusajs/types"
import { createMedusaContainer } from "@medusajs/utils"
import {
ContainerRegistrationKeys,
createMedusaContainer,
} from "@medusajs/utils"
import { asFunction, asValue } from "awilix"

export async function loadInternalModule(
Expand Down Expand Up @@ -73,7 +76,12 @@ export async function loadInternalModule(

const dependencies = resolution?.dependencies ?? []
if (resources === MODULE_RESOURCE_TYPE.SHARED) {
dependencies.push("manager", "configModule")
dependencies.push(
ContainerRegistrationKeys.MANAGER,
ContainerRegistrationKeys.CONFIG_MODULE,
ContainerRegistrationKeys.LOGGER,
ContainerRegistrationKeys.PG_CONNECTION
)
}

for (const dependency of dependencies) {
Expand Down
43 changes: 38 additions & 5 deletions packages/product/integration-tests/__fixtures__/module.ts
Original file line number Diff line number Diff line change
@@ -1,16 +1,49 @@
import { Context } from "@medusajs/types"
import { DALUtils } from "@medusajs/utils"

class CustomRepository extends DALUtils.MikroOrmBaseRepository {
constructor({ manager }) {
// @ts-ignore
super(...arguments)
}
}

CustomRepository.prototype.find = jest.fn().mockImplementation(async () => [])
CustomRepository.prototype.findAndCount = jest
.fn()
.mockImplementation(async () => [])
find = jest.fn().mockImplementation(async () => [])
findAndCount = jest.fn().mockImplementation(async () => [])
create = jest.fn()
update = jest.fn()
delete = jest.fn()
softDelete = jest.fn()
restore = jest.fn()

async transaction<TManager = unknown>(
task: (transactionManager: TManager) => Promise<any>,
options: {
isolationLevel?: string
enableNestedTransactions?: boolean
transaction?: TManager
} = {}
): Promise<any> {
return super.transaction(task, options)
}

getActiveManager<TManager = unknown>({
transactionManager,
manager,
}: Context = {}): TManager {
return super.getActiveManager({ transactionManager, manager })
}

getFreshManager<TManager = unknown>(): TManager {
return super.getFreshManager()
}

async serialize<TOutput extends object | object[]>(
data: any,
options?: any
): Promise<TOutput> {
return super.serialize(data, options)
}
}

export class ProductRepository extends CustomRepository {}
export class ProductTagRepository extends CustomRepository {}
Expand Down
Loading