Skip to content

Commit c8b375a

Browse files
feat(locking): Locking module (#9524)
**What** - Locking Module to manage concurrency - Default `in-memory` provider
1 parent 5c9e289 commit c8b375a

File tree

28 files changed

+806
-39
lines changed

28 files changed

+806
-39
lines changed

.changeset/little-books-reply.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,7 @@
6060
"@medusajs/admin-vite-plugin": patch
6161
"@medusajs/framework": patch
6262
"@medusajs/index": patch
63+
"@medusajs/locking": patch
6364
---
6465

6566
chore: Preview release changeset

.eslintignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ packages/*
2323
!packages/cache-inmemory
2424
!packages/create-medusa-app
2525
!packages/product
26+
!packages/locking
2627
!packages/orchestration
2728
!packages/workflows-sdk
2829
!packages/core-flows

.eslintrc.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -128,6 +128,7 @@ module.exports = {
128128
"./packages/modules/workflow-engine-redis/tsconfig.spec.json",
129129
"./packages/modules/link-modules/tsconfig.spec.json",
130130
"./packages/modules/user/tsconfig.spec.json",
131+
"./packages/modules/locking/tsconfig.spec.json",
131132

132133
"./packages/modules/providers/file-local/tsconfig.spec.json",
133134
"./packages/modules/providers/file-s3/tsconfig.spec.json",

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ www/**/.yarn/*
2020
.idea
2121
.turbo
2222
build/**
23+
dist/**
2324
**/dist
2425
**/stats
2526
.favorites.json

packages/core/framework/src/types/container.ts

Lines changed: 17 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1,36 +1,37 @@
1-
import { Knex } from "@mikro-orm/knex"
21
import { RemoteLink } from "@medusajs/modules-sdk"
3-
import { AwilixContainer, ResolveOptions } from "awilix"
4-
import { Modules, ContainerRegistrationKeys } from "@medusajs/utils"
52
import {
6-
Logger,
73
ConfigModule,
8-
ModuleImplementations,
9-
RemoteQueryFunction,
4+
IApiKeyModuleService,
105
IAuthModuleService,
116
ICacheService,
127
ICartModuleService,
8+
ICurrencyModuleService,
139
ICustomerModuleService,
1410
IEventBusModuleService,
11+
IFileModuleService,
12+
IFulfillmentModuleService,
1513
IInventoryService,
14+
ILockingModule,
15+
INotificationModuleService,
16+
IOrderModuleService,
1617
IPaymentModuleService,
1718
IPricingModuleService,
1819
IProductModuleService,
1920
IPromotionModuleService,
21+
IRegionModuleService,
2022
ISalesChannelModuleService,
21-
ITaxModuleService,
22-
IFulfillmentModuleService,
2323
IStockLocationService,
24+
IStoreModuleService,
25+
ITaxModuleService,
2426
IUserModuleService,
2527
IWorkflowEngineService,
26-
IRegionModuleService,
27-
IOrderModuleService,
28-
IApiKeyModuleService,
29-
IStoreModuleService,
30-
ICurrencyModuleService,
31-
IFileModuleService,
32-
INotificationModuleService,
28+
Logger,
29+
ModuleImplementations,
30+
RemoteQueryFunction,
3331
} from "@medusajs/types"
32+
import { ContainerRegistrationKeys, Modules } from "@medusajs/utils"
33+
import { Knex } from "@mikro-orm/knex"
34+
import { AwilixContainer, ResolveOptions } from "awilix"
3435

3536
declare module "@medusajs/types" {
3637
export interface ModuleImplementations {
@@ -63,6 +64,7 @@ declare module "@medusajs/types" {
6364
[Modules.CURRENCY]: ICurrencyModuleService
6465
[Modules.FILE]: IFileModuleService
6566
[Modules.NOTIFICATION]: INotificationModuleService
67+
[Modules.LOCKING]: ILockingModule
6668
}
6769
}
6870

packages/core/modules-sdk/src/definitions.ts

Lines changed: 33 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ export const ModulesDefinition: {
1616
label: upperCaseFirst(Modules.EVENT_BUS),
1717
isRequired: true,
1818
isQueryable: false,
19-
dependencies: ["logger"],
19+
dependencies: [ContainerRegistrationKeys.LOGGER],
2020
defaultModuleDeclaration: {
2121
scope: MODULE_SCOPE.INTERNAL,
2222
resources: MODULE_RESOURCE_TYPE.SHARED,
@@ -63,7 +63,7 @@ export const ModulesDefinition: {
6363
label: upperCaseFirst(Modules.PRODUCT),
6464
isRequired: false,
6565
isQueryable: true,
66-
dependencies: [Modules.EVENT_BUS, "logger"],
66+
dependencies: [Modules.EVENT_BUS, ContainerRegistrationKeys.LOGGER],
6767
defaultModuleDeclaration: {
6868
scope: MODULE_SCOPE.INTERNAL,
6969
resources: MODULE_RESOURCE_TYPE.SHARED,
@@ -75,7 +75,7 @@ export const ModulesDefinition: {
7575
label: upperCaseFirst(Modules.PRICING),
7676
isRequired: false,
7777
isQueryable: true,
78-
dependencies: [Modules.EVENT_BUS, "logger"],
78+
dependencies: [Modules.EVENT_BUS, ContainerRegistrationKeys.LOGGER],
7979
defaultModuleDeclaration: {
8080
scope: MODULE_SCOPE.INTERNAL,
8181
resources: MODULE_RESOURCE_TYPE.SHARED,
@@ -87,7 +87,7 @@ export const ModulesDefinition: {
8787
label: upperCaseFirst(Modules.PROMOTION),
8888
isRequired: false,
8989
isQueryable: true,
90-
dependencies: ["logger"],
90+
dependencies: [ContainerRegistrationKeys.LOGGER],
9191
defaultModuleDeclaration: {
9292
scope: MODULE_SCOPE.INTERNAL,
9393
resources: MODULE_RESOURCE_TYPE.SHARED,
@@ -99,7 +99,7 @@ export const ModulesDefinition: {
9999
label: upperCaseFirst(Modules.AUTH),
100100
isRequired: false,
101101
isQueryable: true,
102-
dependencies: ["logger"],
102+
dependencies: [ContainerRegistrationKeys.LOGGER],
103103
defaultModuleDeclaration: {
104104
scope: MODULE_SCOPE.INTERNAL,
105105
resources: MODULE_RESOURCE_TYPE.SHARED,
@@ -111,7 +111,7 @@ export const ModulesDefinition: {
111111
label: upperCaseFirst(Modules.WORKFLOW_ENGINE),
112112
isRequired: false,
113113
isQueryable: true,
114-
dependencies: ["logger"],
114+
dependencies: [ContainerRegistrationKeys.LOGGER],
115115
__passSharedContainer: true,
116116
defaultModuleDeclaration: {
117117
scope: MODULE_SCOPE.INTERNAL,
@@ -124,7 +124,7 @@ export const ModulesDefinition: {
124124
label: upperCaseFirst(Modules.SALES_CHANNEL),
125125
isRequired: false,
126126
isQueryable: true,
127-
dependencies: ["logger"],
127+
dependencies: [ContainerRegistrationKeys.LOGGER],
128128
defaultModuleDeclaration: {
129129
scope: MODULE_SCOPE.INTERNAL,
130130
resources: MODULE_RESOURCE_TYPE.SHARED,
@@ -136,7 +136,7 @@ export const ModulesDefinition: {
136136
label: upperCaseFirst(Modules.FULFILLMENT),
137137
isRequired: false,
138138
isQueryable: true,
139-
dependencies: ["logger", Modules.EVENT_BUS],
139+
dependencies: [ContainerRegistrationKeys.LOGGER, Modules.EVENT_BUS],
140140
defaultModuleDeclaration: {
141141
scope: MODULE_SCOPE.INTERNAL,
142142
resources: MODULE_RESOURCE_TYPE.SHARED,
@@ -148,7 +148,7 @@ export const ModulesDefinition: {
148148
label: upperCaseFirst(Modules.CART),
149149
isRequired: false,
150150
isQueryable: true,
151-
dependencies: ["logger"],
151+
dependencies: [ContainerRegistrationKeys.LOGGER],
152152
defaultModuleDeclaration: {
153153
scope: MODULE_SCOPE.INTERNAL,
154154
resources: MODULE_RESOURCE_TYPE.SHARED,
@@ -160,7 +160,7 @@ export const ModulesDefinition: {
160160
label: upperCaseFirst(Modules.CUSTOMER),
161161
isRequired: false,
162162
isQueryable: true,
163-
dependencies: ["logger"],
163+
dependencies: [ContainerRegistrationKeys.LOGGER],
164164
defaultModuleDeclaration: {
165165
scope: MODULE_SCOPE.INTERNAL,
166166
resources: MODULE_RESOURCE_TYPE.SHARED,
@@ -172,7 +172,7 @@ export const ModulesDefinition: {
172172
label: upperCaseFirst(Modules.PAYMENT),
173173
isRequired: false,
174174
isQueryable: true,
175-
dependencies: ["logger"],
175+
dependencies: [ContainerRegistrationKeys.LOGGER],
176176
defaultModuleDeclaration: {
177177
scope: MODULE_SCOPE.INTERNAL,
178178
resources: MODULE_RESOURCE_TYPE.SHARED,
@@ -184,7 +184,7 @@ export const ModulesDefinition: {
184184
label: upperCaseFirst(Modules.USER),
185185
isRequired: false,
186186
isQueryable: true,
187-
dependencies: [Modules.EVENT_BUS, "logger"],
187+
dependencies: [Modules.EVENT_BUS, ContainerRegistrationKeys.LOGGER],
188188
defaultModuleDeclaration: {
189189
scope: MODULE_SCOPE.INTERNAL,
190190
resources: MODULE_RESOURCE_TYPE.SHARED,
@@ -196,7 +196,7 @@ export const ModulesDefinition: {
196196
label: upperCaseFirst(Modules.REGION),
197197
isRequired: false,
198198
isQueryable: true,
199-
dependencies: ["logger"],
199+
dependencies: [ContainerRegistrationKeys.LOGGER],
200200
defaultModuleDeclaration: {
201201
scope: MODULE_SCOPE.INTERNAL,
202202
resources: MODULE_RESOURCE_TYPE.SHARED,
@@ -208,7 +208,7 @@ export const ModulesDefinition: {
208208
label: upperCaseFirst(Modules.ORDER),
209209
isRequired: false,
210210
isQueryable: true,
211-
dependencies: ["logger", Modules.EVENT_BUS],
211+
dependencies: [ContainerRegistrationKeys.LOGGER, Modules.EVENT_BUS],
212212
defaultModuleDeclaration: {
213213
scope: MODULE_SCOPE.INTERNAL,
214214
resources: MODULE_RESOURCE_TYPE.SHARED,
@@ -220,7 +220,7 @@ export const ModulesDefinition: {
220220
label: upperCaseFirst(Modules.TAX),
221221
isRequired: false,
222222
isQueryable: true,
223-
dependencies: ["logger", Modules.EVENT_BUS],
223+
dependencies: [ContainerRegistrationKeys.LOGGER, Modules.EVENT_BUS],
224224
defaultModuleDeclaration: {
225225
scope: MODULE_SCOPE.INTERNAL,
226226
resources: MODULE_RESOURCE_TYPE.SHARED,
@@ -232,7 +232,7 @@ export const ModulesDefinition: {
232232
label: upperCaseFirst(Modules.API_KEY),
233233
isRequired: false,
234234
isQueryable: true,
235-
dependencies: ["logger"],
235+
dependencies: [ContainerRegistrationKeys.LOGGER],
236236
defaultModuleDeclaration: {
237237
scope: MODULE_SCOPE.INTERNAL,
238238
resources: MODULE_RESOURCE_TYPE.SHARED,
@@ -244,7 +244,7 @@ export const ModulesDefinition: {
244244
label: upperCaseFirst(Modules.STORE),
245245
isRequired: false,
246246
isQueryable: true,
247-
dependencies: ["logger"],
247+
dependencies: [ContainerRegistrationKeys.LOGGER],
248248
defaultModuleDeclaration: {
249249
scope: MODULE_SCOPE.INTERNAL,
250250
resources: MODULE_RESOURCE_TYPE.SHARED,
@@ -256,7 +256,7 @@ export const ModulesDefinition: {
256256
label: upperCaseFirst(Modules.CURRENCY),
257257
isRequired: false,
258258
isQueryable: true,
259-
dependencies: ["logger"],
259+
dependencies: [ContainerRegistrationKeys.LOGGER],
260260
defaultModuleDeclaration: {
261261
scope: MODULE_SCOPE.INTERNAL,
262262
resources: MODULE_RESOURCE_TYPE.SHARED,
@@ -268,7 +268,7 @@ export const ModulesDefinition: {
268268
label: upperCaseFirst(Modules.FILE),
269269
isRequired: false,
270270
isQueryable: true,
271-
dependencies: ["logger"],
271+
dependencies: [ContainerRegistrationKeys.LOGGER],
272272
defaultModuleDeclaration: {
273273
scope: MODULE_SCOPE.INTERNAL,
274274
resources: MODULE_RESOURCE_TYPE.SHARED,
@@ -280,7 +280,7 @@ export const ModulesDefinition: {
280280
label: upperCaseFirst(Modules.NOTIFICATION),
281281
isRequired: false,
282282
isQueryable: true,
283-
dependencies: [Modules.EVENT_BUS, "logger"],
283+
dependencies: [Modules.EVENT_BUS, ContainerRegistrationKeys.LOGGER],
284284
defaultModuleDeclaration: {
285285
scope: MODULE_SCOPE.INTERNAL,
286286
resources: MODULE_RESOURCE_TYPE.SHARED,
@@ -294,7 +294,7 @@ export const ModulesDefinition: {
294294
isQueryable: false,
295295
dependencies: [
296296
Modules.EVENT_BUS,
297-
"logger",
297+
ContainerRegistrationKeys.LOGGER,
298298
ContainerRegistrationKeys.REMOTE_QUERY,
299299
ContainerRegistrationKeys.QUERY,
300300
],
@@ -303,6 +303,18 @@ export const ModulesDefinition: {
303303
resources: MODULE_RESOURCE_TYPE.SHARED,
304304
},
305305
},
306+
[Modules.LOCKING]: {
307+
key: Modules.LOCKING,
308+
defaultPackage: false,
309+
label: upperCaseFirst(Modules.LOCKING),
310+
isRequired: false,
311+
isQueryable: false,
312+
dependencies: [ContainerRegistrationKeys.LOGGER],
313+
defaultModuleDeclaration: {
314+
scope: MODULE_SCOPE.INTERNAL,
315+
resources: MODULE_RESOURCE_TYPE.SHARED,
316+
},
317+
},
306318
}
307319

308320
export const MODULE_DEFINITIONS: ModuleDefinition[] =

packages/core/modules-sdk/src/medusa-app.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -84,7 +84,7 @@ export async function loadModules(args: {
8484
sharedResourcesConfig,
8585
migrationOnly = false,
8686
loaderOnly = false,
87-
workerMode = "server" as ModuleBootstrapOptions["workerMode"],
87+
workerMode = "shared" as ModuleBootstrapOptions["workerMode"],
8888
} = args
8989

9090
const allModules = {} as any
@@ -307,7 +307,7 @@ async function MedusaApp_({
307307
injectedDependencies = {},
308308
migrationOnly = false,
309309
loaderOnly = false,
310-
workerMode = "server",
310+
workerMode = "shared",
311311
}: MedusaAppOptions & {
312312
migrationOnly?: boolean
313313
} = {}): Promise<MedusaAppOutput> {

packages/core/types/src/index.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ export * from "./index-data"
2020
export * from "./inventory"
2121
export * from "./joiner"
2222
export * from "./link-modules"
23+
export * from "./locking"
2324
export * from "./logger"
2425
export * from "./modules-sdk"
2526
export * from "./notification"
Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,69 @@
1+
import { Context } from "../shared-context"
2+
3+
export interface ILockingProvider {
4+
execute<T>(
5+
keys: string | string[],
6+
job: () => Promise<T>,
7+
args?: {
8+
timeout?: number
9+
},
10+
sharedContext?: Context
11+
): Promise<T>
12+
acquire(
13+
keys: string | string[],
14+
args?: {
15+
ownerId?: string | null
16+
expire?: number
17+
},
18+
sharedContext?: Context
19+
): Promise<void>
20+
release(
21+
keys: string | string[],
22+
args?: {
23+
ownerId?: string | null
24+
},
25+
sharedContext?: Context
26+
): Promise<boolean>
27+
releaseAll(
28+
args?: {
29+
ownerId?: string | null
30+
},
31+
sharedContext?: Context
32+
): Promise<void>
33+
}
34+
35+
export interface ILockingModule {
36+
execute<T>(
37+
keys: string | string[],
38+
job: () => Promise<T>,
39+
args?: {
40+
timeout?: number
41+
provider?: string
42+
},
43+
sharedContext?: Context
44+
): Promise<T>
45+
acquire(
46+
keys: string | string[],
47+
args?: {
48+
ownerId?: string | null
49+
expire?: number
50+
provider?: string
51+
},
52+
sharedContext?: Context
53+
): Promise<void>
54+
release(
55+
keys: string | string[],
56+
args?: {
57+
ownerId?: string | null
58+
provider?: string
59+
},
60+
sharedContext?: Context
61+
): Promise<boolean>
62+
releaseAll(
63+
args?: {
64+
ownerId?: string | null
65+
provider?: string
66+
},
67+
sharedContext?: Context
68+
): Promise<void>
69+
}

0 commit comments

Comments
 (0)