feat(locking): Locking module (#9524)
**What** - Locking Module to manage concurrency - Default `in-memory` provider
This commit is contained in:
@@ -1,36 +1,37 @@
|
||||
import { Knex } from "@mikro-orm/knex"
|
||||
import { RemoteLink } from "@medusajs/modules-sdk"
|
||||
import { AwilixContainer, ResolveOptions } from "awilix"
|
||||
import { Modules, ContainerRegistrationKeys } from "@medusajs/utils"
|
||||
import {
|
||||
Logger,
|
||||
ConfigModule,
|
||||
ModuleImplementations,
|
||||
RemoteQueryFunction,
|
||||
IApiKeyModuleService,
|
||||
IAuthModuleService,
|
||||
ICacheService,
|
||||
ICartModuleService,
|
||||
ICurrencyModuleService,
|
||||
ICustomerModuleService,
|
||||
IEventBusModuleService,
|
||||
IFileModuleService,
|
||||
IFulfillmentModuleService,
|
||||
IInventoryService,
|
||||
ILockingModule,
|
||||
INotificationModuleService,
|
||||
IOrderModuleService,
|
||||
IPaymentModuleService,
|
||||
IPricingModuleService,
|
||||
IProductModuleService,
|
||||
IPromotionModuleService,
|
||||
IRegionModuleService,
|
||||
ISalesChannelModuleService,
|
||||
ITaxModuleService,
|
||||
IFulfillmentModuleService,
|
||||
IStockLocationService,
|
||||
IStoreModuleService,
|
||||
ITaxModuleService,
|
||||
IUserModuleService,
|
||||
IWorkflowEngineService,
|
||||
IRegionModuleService,
|
||||
IOrderModuleService,
|
||||
IApiKeyModuleService,
|
||||
IStoreModuleService,
|
||||
ICurrencyModuleService,
|
||||
IFileModuleService,
|
||||
INotificationModuleService,
|
||||
Logger,
|
||||
ModuleImplementations,
|
||||
RemoteQueryFunction,
|
||||
} from "@medusajs/types"
|
||||
import { ContainerRegistrationKeys, Modules } from "@medusajs/utils"
|
||||
import { Knex } from "@mikro-orm/knex"
|
||||
import { AwilixContainer, ResolveOptions } from "awilix"
|
||||
|
||||
declare module "@medusajs/types" {
|
||||
export interface ModuleImplementations {
|
||||
@@ -63,6 +64,7 @@ declare module "@medusajs/types" {
|
||||
[Modules.CURRENCY]: ICurrencyModuleService
|
||||
[Modules.FILE]: IFileModuleService
|
||||
[Modules.NOTIFICATION]: INotificationModuleService
|
||||
[Modules.LOCKING]: ILockingModule
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -16,7 +16,7 @@ export const ModulesDefinition: {
|
||||
label: upperCaseFirst(Modules.EVENT_BUS),
|
||||
isRequired: true,
|
||||
isQueryable: false,
|
||||
dependencies: ["logger"],
|
||||
dependencies: [ContainerRegistrationKeys.LOGGER],
|
||||
defaultModuleDeclaration: {
|
||||
scope: MODULE_SCOPE.INTERNAL,
|
||||
resources: MODULE_RESOURCE_TYPE.SHARED,
|
||||
@@ -63,7 +63,7 @@ export const ModulesDefinition: {
|
||||
label: upperCaseFirst(Modules.PRODUCT),
|
||||
isRequired: false,
|
||||
isQueryable: true,
|
||||
dependencies: [Modules.EVENT_BUS, "logger"],
|
||||
dependencies: [Modules.EVENT_BUS, ContainerRegistrationKeys.LOGGER],
|
||||
defaultModuleDeclaration: {
|
||||
scope: MODULE_SCOPE.INTERNAL,
|
||||
resources: MODULE_RESOURCE_TYPE.SHARED,
|
||||
@@ -75,7 +75,7 @@ export const ModulesDefinition: {
|
||||
label: upperCaseFirst(Modules.PRICING),
|
||||
isRequired: false,
|
||||
isQueryable: true,
|
||||
dependencies: [Modules.EVENT_BUS, "logger"],
|
||||
dependencies: [Modules.EVENT_BUS, ContainerRegistrationKeys.LOGGER],
|
||||
defaultModuleDeclaration: {
|
||||
scope: MODULE_SCOPE.INTERNAL,
|
||||
resources: MODULE_RESOURCE_TYPE.SHARED,
|
||||
@@ -87,7 +87,7 @@ export const ModulesDefinition: {
|
||||
label: upperCaseFirst(Modules.PROMOTION),
|
||||
isRequired: false,
|
||||
isQueryable: true,
|
||||
dependencies: ["logger"],
|
||||
dependencies: [ContainerRegistrationKeys.LOGGER],
|
||||
defaultModuleDeclaration: {
|
||||
scope: MODULE_SCOPE.INTERNAL,
|
||||
resources: MODULE_RESOURCE_TYPE.SHARED,
|
||||
@@ -99,7 +99,7 @@ export const ModulesDefinition: {
|
||||
label: upperCaseFirst(Modules.AUTH),
|
||||
isRequired: false,
|
||||
isQueryable: true,
|
||||
dependencies: ["logger"],
|
||||
dependencies: [ContainerRegistrationKeys.LOGGER],
|
||||
defaultModuleDeclaration: {
|
||||
scope: MODULE_SCOPE.INTERNAL,
|
||||
resources: MODULE_RESOURCE_TYPE.SHARED,
|
||||
@@ -111,7 +111,7 @@ export const ModulesDefinition: {
|
||||
label: upperCaseFirst(Modules.WORKFLOW_ENGINE),
|
||||
isRequired: false,
|
||||
isQueryable: true,
|
||||
dependencies: ["logger"],
|
||||
dependencies: [ContainerRegistrationKeys.LOGGER],
|
||||
__passSharedContainer: true,
|
||||
defaultModuleDeclaration: {
|
||||
scope: MODULE_SCOPE.INTERNAL,
|
||||
@@ -124,7 +124,7 @@ export const ModulesDefinition: {
|
||||
label: upperCaseFirst(Modules.SALES_CHANNEL),
|
||||
isRequired: false,
|
||||
isQueryable: true,
|
||||
dependencies: ["logger"],
|
||||
dependencies: [ContainerRegistrationKeys.LOGGER],
|
||||
defaultModuleDeclaration: {
|
||||
scope: MODULE_SCOPE.INTERNAL,
|
||||
resources: MODULE_RESOURCE_TYPE.SHARED,
|
||||
@@ -136,7 +136,7 @@ export const ModulesDefinition: {
|
||||
label: upperCaseFirst(Modules.FULFILLMENT),
|
||||
isRequired: false,
|
||||
isQueryable: true,
|
||||
dependencies: ["logger", Modules.EVENT_BUS],
|
||||
dependencies: [ContainerRegistrationKeys.LOGGER, Modules.EVENT_BUS],
|
||||
defaultModuleDeclaration: {
|
||||
scope: MODULE_SCOPE.INTERNAL,
|
||||
resources: MODULE_RESOURCE_TYPE.SHARED,
|
||||
@@ -148,7 +148,7 @@ export const ModulesDefinition: {
|
||||
label: upperCaseFirst(Modules.CART),
|
||||
isRequired: false,
|
||||
isQueryable: true,
|
||||
dependencies: ["logger"],
|
||||
dependencies: [ContainerRegistrationKeys.LOGGER],
|
||||
defaultModuleDeclaration: {
|
||||
scope: MODULE_SCOPE.INTERNAL,
|
||||
resources: MODULE_RESOURCE_TYPE.SHARED,
|
||||
@@ -160,7 +160,7 @@ export const ModulesDefinition: {
|
||||
label: upperCaseFirst(Modules.CUSTOMER),
|
||||
isRequired: false,
|
||||
isQueryable: true,
|
||||
dependencies: ["logger"],
|
||||
dependencies: [ContainerRegistrationKeys.LOGGER],
|
||||
defaultModuleDeclaration: {
|
||||
scope: MODULE_SCOPE.INTERNAL,
|
||||
resources: MODULE_RESOURCE_TYPE.SHARED,
|
||||
@@ -172,7 +172,7 @@ export const ModulesDefinition: {
|
||||
label: upperCaseFirst(Modules.PAYMENT),
|
||||
isRequired: false,
|
||||
isQueryable: true,
|
||||
dependencies: ["logger"],
|
||||
dependencies: [ContainerRegistrationKeys.LOGGER],
|
||||
defaultModuleDeclaration: {
|
||||
scope: MODULE_SCOPE.INTERNAL,
|
||||
resources: MODULE_RESOURCE_TYPE.SHARED,
|
||||
@@ -184,7 +184,7 @@ export const ModulesDefinition: {
|
||||
label: upperCaseFirst(Modules.USER),
|
||||
isRequired: false,
|
||||
isQueryable: true,
|
||||
dependencies: [Modules.EVENT_BUS, "logger"],
|
||||
dependencies: [Modules.EVENT_BUS, ContainerRegistrationKeys.LOGGER],
|
||||
defaultModuleDeclaration: {
|
||||
scope: MODULE_SCOPE.INTERNAL,
|
||||
resources: MODULE_RESOURCE_TYPE.SHARED,
|
||||
@@ -196,7 +196,7 @@ export const ModulesDefinition: {
|
||||
label: upperCaseFirst(Modules.REGION),
|
||||
isRequired: false,
|
||||
isQueryable: true,
|
||||
dependencies: ["logger"],
|
||||
dependencies: [ContainerRegistrationKeys.LOGGER],
|
||||
defaultModuleDeclaration: {
|
||||
scope: MODULE_SCOPE.INTERNAL,
|
||||
resources: MODULE_RESOURCE_TYPE.SHARED,
|
||||
@@ -208,7 +208,7 @@ export const ModulesDefinition: {
|
||||
label: upperCaseFirst(Modules.ORDER),
|
||||
isRequired: false,
|
||||
isQueryable: true,
|
||||
dependencies: ["logger", Modules.EVENT_BUS],
|
||||
dependencies: [ContainerRegistrationKeys.LOGGER, Modules.EVENT_BUS],
|
||||
defaultModuleDeclaration: {
|
||||
scope: MODULE_SCOPE.INTERNAL,
|
||||
resources: MODULE_RESOURCE_TYPE.SHARED,
|
||||
@@ -220,7 +220,7 @@ export const ModulesDefinition: {
|
||||
label: upperCaseFirst(Modules.TAX),
|
||||
isRequired: false,
|
||||
isQueryable: true,
|
||||
dependencies: ["logger", Modules.EVENT_BUS],
|
||||
dependencies: [ContainerRegistrationKeys.LOGGER, Modules.EVENT_BUS],
|
||||
defaultModuleDeclaration: {
|
||||
scope: MODULE_SCOPE.INTERNAL,
|
||||
resources: MODULE_RESOURCE_TYPE.SHARED,
|
||||
@@ -232,7 +232,7 @@ export const ModulesDefinition: {
|
||||
label: upperCaseFirst(Modules.API_KEY),
|
||||
isRequired: false,
|
||||
isQueryable: true,
|
||||
dependencies: ["logger"],
|
||||
dependencies: [ContainerRegistrationKeys.LOGGER],
|
||||
defaultModuleDeclaration: {
|
||||
scope: MODULE_SCOPE.INTERNAL,
|
||||
resources: MODULE_RESOURCE_TYPE.SHARED,
|
||||
@@ -244,7 +244,7 @@ export const ModulesDefinition: {
|
||||
label: upperCaseFirst(Modules.STORE),
|
||||
isRequired: false,
|
||||
isQueryable: true,
|
||||
dependencies: ["logger"],
|
||||
dependencies: [ContainerRegistrationKeys.LOGGER],
|
||||
defaultModuleDeclaration: {
|
||||
scope: MODULE_SCOPE.INTERNAL,
|
||||
resources: MODULE_RESOURCE_TYPE.SHARED,
|
||||
@@ -256,7 +256,7 @@ export const ModulesDefinition: {
|
||||
label: upperCaseFirst(Modules.CURRENCY),
|
||||
isRequired: false,
|
||||
isQueryable: true,
|
||||
dependencies: ["logger"],
|
||||
dependencies: [ContainerRegistrationKeys.LOGGER],
|
||||
defaultModuleDeclaration: {
|
||||
scope: MODULE_SCOPE.INTERNAL,
|
||||
resources: MODULE_RESOURCE_TYPE.SHARED,
|
||||
@@ -268,7 +268,7 @@ export const ModulesDefinition: {
|
||||
label: upperCaseFirst(Modules.FILE),
|
||||
isRequired: false,
|
||||
isQueryable: true,
|
||||
dependencies: ["logger"],
|
||||
dependencies: [ContainerRegistrationKeys.LOGGER],
|
||||
defaultModuleDeclaration: {
|
||||
scope: MODULE_SCOPE.INTERNAL,
|
||||
resources: MODULE_RESOURCE_TYPE.SHARED,
|
||||
@@ -280,7 +280,7 @@ export const ModulesDefinition: {
|
||||
label: upperCaseFirst(Modules.NOTIFICATION),
|
||||
isRequired: false,
|
||||
isQueryable: true,
|
||||
dependencies: [Modules.EVENT_BUS, "logger"],
|
||||
dependencies: [Modules.EVENT_BUS, ContainerRegistrationKeys.LOGGER],
|
||||
defaultModuleDeclaration: {
|
||||
scope: MODULE_SCOPE.INTERNAL,
|
||||
resources: MODULE_RESOURCE_TYPE.SHARED,
|
||||
@@ -294,7 +294,7 @@ export const ModulesDefinition: {
|
||||
isQueryable: false,
|
||||
dependencies: [
|
||||
Modules.EVENT_BUS,
|
||||
"logger",
|
||||
ContainerRegistrationKeys.LOGGER,
|
||||
ContainerRegistrationKeys.REMOTE_QUERY,
|
||||
ContainerRegistrationKeys.QUERY,
|
||||
],
|
||||
@@ -303,6 +303,18 @@ export const ModulesDefinition: {
|
||||
resources: MODULE_RESOURCE_TYPE.SHARED,
|
||||
},
|
||||
},
|
||||
[Modules.LOCKING]: {
|
||||
key: Modules.LOCKING,
|
||||
defaultPackage: false,
|
||||
label: upperCaseFirst(Modules.LOCKING),
|
||||
isRequired: false,
|
||||
isQueryable: false,
|
||||
dependencies: [ContainerRegistrationKeys.LOGGER],
|
||||
defaultModuleDeclaration: {
|
||||
scope: MODULE_SCOPE.INTERNAL,
|
||||
resources: MODULE_RESOURCE_TYPE.SHARED,
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
export const MODULE_DEFINITIONS: ModuleDefinition[] =
|
||||
|
||||
@@ -84,7 +84,7 @@ export async function loadModules(args: {
|
||||
sharedResourcesConfig,
|
||||
migrationOnly = false,
|
||||
loaderOnly = false,
|
||||
workerMode = "server" as ModuleBootstrapOptions["workerMode"],
|
||||
workerMode = "shared" as ModuleBootstrapOptions["workerMode"],
|
||||
} = args
|
||||
|
||||
const allModules = {} as any
|
||||
@@ -307,7 +307,7 @@ async function MedusaApp_({
|
||||
injectedDependencies = {},
|
||||
migrationOnly = false,
|
||||
loaderOnly = false,
|
||||
workerMode = "server",
|
||||
workerMode = "shared",
|
||||
}: MedusaAppOptions & {
|
||||
migrationOnly?: boolean
|
||||
} = {}): Promise<MedusaAppOutput> {
|
||||
|
||||
@@ -20,6 +20,7 @@ export * from "./index-data"
|
||||
export * from "./inventory"
|
||||
export * from "./joiner"
|
||||
export * from "./link-modules"
|
||||
export * from "./locking"
|
||||
export * from "./logger"
|
||||
export * from "./modules-sdk"
|
||||
export * from "./notification"
|
||||
|
||||
@@ -0,0 +1,69 @@
|
||||
import { Context } from "../shared-context"
|
||||
|
||||
export interface ILockingProvider {
|
||||
execute<T>(
|
||||
keys: string | string[],
|
||||
job: () => Promise<T>,
|
||||
args?: {
|
||||
timeout?: number
|
||||
},
|
||||
sharedContext?: Context
|
||||
): Promise<T>
|
||||
acquire(
|
||||
keys: string | string[],
|
||||
args?: {
|
||||
ownerId?: string | null
|
||||
expire?: number
|
||||
},
|
||||
sharedContext?: Context
|
||||
): Promise<void>
|
||||
release(
|
||||
keys: string | string[],
|
||||
args?: {
|
||||
ownerId?: string | null
|
||||
},
|
||||
sharedContext?: Context
|
||||
): Promise<boolean>
|
||||
releaseAll(
|
||||
args?: {
|
||||
ownerId?: string | null
|
||||
},
|
||||
sharedContext?: Context
|
||||
): Promise<void>
|
||||
}
|
||||
|
||||
export interface ILockingModule {
|
||||
execute<T>(
|
||||
keys: string | string[],
|
||||
job: () => Promise<T>,
|
||||
args?: {
|
||||
timeout?: number
|
||||
provider?: string
|
||||
},
|
||||
sharedContext?: Context
|
||||
): Promise<T>
|
||||
acquire(
|
||||
keys: string | string[],
|
||||
args?: {
|
||||
ownerId?: string | null
|
||||
expire?: number
|
||||
provider?: string
|
||||
},
|
||||
sharedContext?: Context
|
||||
): Promise<void>
|
||||
release(
|
||||
keys: string | string[],
|
||||
args?: {
|
||||
ownerId?: string | null
|
||||
provider?: string
|
||||
},
|
||||
sharedContext?: Context
|
||||
): Promise<boolean>
|
||||
releaseAll(
|
||||
args?: {
|
||||
ownerId?: string | null
|
||||
provider?: string
|
||||
},
|
||||
sharedContext?: Context
|
||||
): Promise<void>
|
||||
}
|
||||
@@ -8,4 +8,5 @@ export type ModuleProvider = {
|
||||
resolve: string | ModuleProviderExports
|
||||
id: string
|
||||
options?: Record<string, unknown>
|
||||
is_default?: boolean
|
||||
}
|
||||
|
||||
@@ -24,6 +24,7 @@ export const Modules = {
|
||||
FILE: "file",
|
||||
NOTIFICATION: "notification",
|
||||
INDEX: "index",
|
||||
LOCKING: "locking",
|
||||
} as const
|
||||
|
||||
export const MODULE_PACKAGE_NAMES = {
|
||||
@@ -52,6 +53,7 @@ export const MODULE_PACKAGE_NAMES = {
|
||||
[Modules.FILE]: "@medusajs/medusa/file",
|
||||
[Modules.NOTIFICATION]: "@medusajs/medusa/notification",
|
||||
[Modules.INDEX]: "@medusajs/medusa/index-module",
|
||||
[Modules.LOCKING]: "@medusajs/medusa/locking",
|
||||
}
|
||||
|
||||
export const REVERSED_MODULE_PACKAGE_NAMES = Object.entries(
|
||||
|
||||
@@ -9,7 +9,7 @@ import {
|
||||
PerformedActions,
|
||||
UpsertWithReplaceConfig,
|
||||
} from "@medusajs/types"
|
||||
import type { EntitySchema, EntityClass } from "@mikro-orm/core"
|
||||
import type { EntityClass, EntitySchema } from "@mikro-orm/core"
|
||||
import {
|
||||
doNotForceTransaction,
|
||||
isDefined,
|
||||
|
||||
Reference in New Issue
Block a user