chore(): Emit events in batch and index process event ids in batch (#12097)
**What** First iteration to prevent events from overwhelming the systems. - Group emitted event ids when possible instead of creating a message per id which leads to reduced amount of events to process massively in cases of import for example - Update the index engine to process event data in batches of 100 - Update event handling by the index engine to be able to upsert by batch as well - Fix index engine build config for intermediate listeners inferrence
This commit is contained in:
1 parent
b05807bfc1
commit
74381addc3
21 files changed
+449
-364
No files matched your search
@@ -0,0 +1,12 @@
|
|||||||
|
---
|
||||||
|
"@medusajs/fulfillment": patch
|
||||||
|
"@medusajs/index": patch
|
||||||
|
"@medusajs/inventory": patch
|
||||||
|
"@medusajs/link-modules": patch
|
||||||
|
"@medusajs/pricing": patch
|
||||||
|
"@medusajs/user": patch
|
||||||
|
"@medusajs/types": patch
|
||||||
|
"@medusajs/utils": patch
|
||||||
|
---
|
||||||
|
|
||||||
|
chore(): Emit events in batch and index process event ids in batch
|
||||||
@@ -37,7 +37,7 @@ export type Event<TData = unknown> = {
|
|||||||
*/
|
*/
|
||||||
metadata?: EventMetadata
|
metadata?: EventMetadata
|
||||||
/**
|
/**
|
||||||
* The data payload that subscribers receive. For example, the ID of the created user.
|
* The data payload that subscribers receive. For example, the ID or IDs of the created user. (e.g. { id: "123" } or { ids: ["123", "456"] })
|
||||||
*/
|
*/
|
||||||
data: TData
|
data: TData
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -44,7 +44,8 @@ export function buildModuleResourceEventName({
|
|||||||
action: string
|
action: string
|
||||||
}): string {
|
}): string {
|
||||||
const kebabCaseName = lowerCaseFirst(kebabCase(objectName))
|
const kebabCaseName = lowerCaseFirst(kebabCase(objectName))
|
||||||
return `${prefix ? `${prefix}.` : ""}${kebabCaseName}.${action}`
|
const conventionalePrefix = prefix && lowerCaseFirst(kebabCase(prefix))
|
||||||
|
return `${prefix ? `${conventionalePrefix}.` : ""}${kebabCaseName}.${action}`
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -60,16 +60,16 @@ export function moduleEventBuilderFactory({
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
data.forEach((dataItem) => {
|
|
||||||
messages.push({
|
messages.push({
|
||||||
source,
|
source,
|
||||||
action,
|
action,
|
||||||
context: sharedContext,
|
context: sharedContext,
|
||||||
data: { id: dataItem.id },
|
data: {
|
||||||
|
id: data.length === 1 ? data[0].id : data.map((item) => item.id),
|
||||||
|
},
|
||||||
eventName: eventName!,
|
eventName: eventName!,
|
||||||
object,
|
object,
|
||||||
})
|
})
|
||||||
})
|
|
||||||
|
|
||||||
aggregator.saveRawMessageData(messages)
|
aggregator.saveRawMessageData(messages)
|
||||||
}
|
}
|
||||||
|
|||||||
+56
-20
@@ -218,7 +218,9 @@ moduleIntegrationTestRunner<IFulfillmentModuleService>({
|
|||||||
eventName: FulfillmentEvents.FULFILLMENT_SET_CREATED,
|
eventName: FulfillmentEvents.FULFILLMENT_SET_CREATED,
|
||||||
action: "created",
|
action: "created",
|
||||||
object: "fulfillment_set",
|
object: "fulfillment_set",
|
||||||
data: { id: fulfillmentSets[i].id },
|
data: {
|
||||||
|
id: expect.arrayContaining([fulfillmentSets[i].id]),
|
||||||
|
},
|
||||||
}),
|
}),
|
||||||
]),
|
]),
|
||||||
{
|
{
|
||||||
@@ -335,13 +337,19 @@ moduleIntegrationTestRunner<IFulfillmentModuleService>({
|
|||||||
eventName: FulfillmentEvents.FULFILLMENT_SET_CREATED,
|
eventName: FulfillmentEvents.FULFILLMENT_SET_CREATED,
|
||||||
action: "created",
|
action: "created",
|
||||||
object: "fulfillment_set",
|
object: "fulfillment_set",
|
||||||
data: { id: fulfillmentSets[i].id },
|
data: {
|
||||||
|
id: expect.arrayContaining([fulfillmentSets[i].id]),
|
||||||
|
},
|
||||||
}),
|
}),
|
||||||
buildExpectedEventMessageShape({
|
buildExpectedEventMessageShape({
|
||||||
eventName: FulfillmentEvents.SERVICE_ZONE_CREATED,
|
eventName: FulfillmentEvents.SERVICE_ZONE_CREATED,
|
||||||
action: "created",
|
action: "created",
|
||||||
object: "service_zone",
|
object: "service_zone",
|
||||||
data: { id: fulfillmentSets[i].service_zones[0].id },
|
data: {
|
||||||
|
id: expect.arrayContaining([
|
||||||
|
fulfillmentSets[i].service_zones[0].id,
|
||||||
|
]),
|
||||||
|
},
|
||||||
}),
|
}),
|
||||||
]),
|
]),
|
||||||
{
|
{
|
||||||
@@ -505,20 +513,28 @@ moduleIntegrationTestRunner<IFulfillmentModuleService>({
|
|||||||
eventName: FulfillmentEvents.FULFILLMENT_SET_CREATED,
|
eventName: FulfillmentEvents.FULFILLMENT_SET_CREATED,
|
||||||
action: "created",
|
action: "created",
|
||||||
object: "fulfillment_set",
|
object: "fulfillment_set",
|
||||||
data: { id: fulfillmentSets[i].id },
|
data: {
|
||||||
|
id: expect.arrayContaining([fulfillmentSets[i].id]),
|
||||||
|
},
|
||||||
}),
|
}),
|
||||||
buildExpectedEventMessageShape({
|
buildExpectedEventMessageShape({
|
||||||
eventName: FulfillmentEvents.SERVICE_ZONE_CREATED,
|
eventName: FulfillmentEvents.SERVICE_ZONE_CREATED,
|
||||||
action: "created",
|
action: "created",
|
||||||
object: "service_zone",
|
object: "service_zone",
|
||||||
data: { id: fulfillmentSets[i].service_zones[0].id },
|
data: {
|
||||||
|
id: expect.arrayContaining([
|
||||||
|
fulfillmentSets[i].service_zones[0].id,
|
||||||
|
]),
|
||||||
|
},
|
||||||
}),
|
}),
|
||||||
buildExpectedEventMessageShape({
|
buildExpectedEventMessageShape({
|
||||||
eventName: FulfillmentEvents.GEO_ZONE_CREATED,
|
eventName: FulfillmentEvents.GEO_ZONE_CREATED,
|
||||||
action: "created",
|
action: "created",
|
||||||
object: "geo_zone",
|
object: "geo_zone",
|
||||||
data: {
|
data: {
|
||||||
id: fulfillmentSets[i].service_zones[0].geo_zones[0].id,
|
id: expect.arrayContaining([
|
||||||
|
fulfillmentSets[i].service_zones[0].geo_zones[0].id,
|
||||||
|
]),
|
||||||
},
|
},
|
||||||
}),
|
}),
|
||||||
]),
|
]),
|
||||||
@@ -708,7 +724,7 @@ moduleIntegrationTestRunner<IFulfillmentModuleService>({
|
|||||||
})
|
})
|
||||||
|
|
||||||
expect(updatedFulfillmentSets).toHaveLength(2)
|
expect(updatedFulfillmentSets).toHaveLength(2)
|
||||||
expect(eventBusEmitSpy.mock.calls[1][0]).toHaveLength(2)
|
expect(eventBusEmitSpy.mock.calls[1][0]).toHaveLength(1)
|
||||||
|
|
||||||
for (const data_ of updateData) {
|
for (const data_ of updateData) {
|
||||||
const currentFullfillmentSet = fullfillmentSets.find(
|
const currentFullfillmentSet = fullfillmentSets.find(
|
||||||
@@ -729,7 +745,9 @@ moduleIntegrationTestRunner<IFulfillmentModuleService>({
|
|||||||
eventName: FulfillmentEvents.FULFILLMENT_SET_UPDATED,
|
eventName: FulfillmentEvents.FULFILLMENT_SET_UPDATED,
|
||||||
action: "updated",
|
action: "updated",
|
||||||
object: "fulfillment_set",
|
object: "fulfillment_set",
|
||||||
data: { id: currentFullfillmentSet.id },
|
data: {
|
||||||
|
id: expect.arrayContaining([currentFullfillmentSet.id]),
|
||||||
|
},
|
||||||
}),
|
}),
|
||||||
]),
|
]),
|
||||||
{
|
{
|
||||||
@@ -1057,7 +1075,7 @@ moduleIntegrationTestRunner<IFulfillmentModuleService>({
|
|||||||
)
|
)
|
||||||
|
|
||||||
expect(updatedFulfillmentSets).toHaveLength(2)
|
expect(updatedFulfillmentSets).toHaveLength(2)
|
||||||
expect(eventBusEmitSpy.mock.calls[1][0]).toHaveLength(10)
|
expect(eventBusEmitSpy.mock.calls[1][0]).toHaveLength(5)
|
||||||
|
|
||||||
for (const data_ of updateData) {
|
for (const data_ of updateData) {
|
||||||
const expectedFulfillmentSet = updatedFulfillmentSets.find(
|
const expectedFulfillmentSet = updatedFulfillmentSets.find(
|
||||||
@@ -1097,36 +1115,48 @@ moduleIntegrationTestRunner<IFulfillmentModuleService>({
|
|||||||
eventName: FulfillmentEvents.FULFILLMENT_SET_UPDATED,
|
eventName: FulfillmentEvents.FULFILLMENT_SET_UPDATED,
|
||||||
action: "updated",
|
action: "updated",
|
||||||
object: "fulfillment_set",
|
object: "fulfillment_set",
|
||||||
data: { id: expectedFulfillmentSet.id },
|
data: {
|
||||||
|
id: expect.arrayContaining([expectedFulfillmentSet.id]),
|
||||||
|
},
|
||||||
}),
|
}),
|
||||||
buildExpectedEventMessageShape({
|
buildExpectedEventMessageShape({
|
||||||
eventName: FulfillmentEvents.SERVICE_ZONE_CREATED,
|
eventName: FulfillmentEvents.SERVICE_ZONE_CREATED,
|
||||||
action: "created",
|
action: "created",
|
||||||
object: "service_zone",
|
object: "service_zone",
|
||||||
data: { id: expectedFulfillmentSet.service_zones[0].id },
|
data: {
|
||||||
|
id: expect.arrayContaining([
|
||||||
|
expectedFulfillmentSet.service_zones[0].id,
|
||||||
|
]),
|
||||||
|
},
|
||||||
}),
|
}),
|
||||||
buildExpectedEventMessageShape({
|
buildExpectedEventMessageShape({
|
||||||
eventName: FulfillmentEvents.GEO_ZONE_CREATED,
|
eventName: FulfillmentEvents.GEO_ZONE_CREATED,
|
||||||
action: "created",
|
action: "created",
|
||||||
object: "geo_zone",
|
object: "geo_zone",
|
||||||
data: {
|
data: {
|
||||||
id: expectedFulfillmentSet.service_zones[0].geo_zones[0]
|
id: expect.arrayContaining([
|
||||||
.id,
|
expectedFulfillmentSet.service_zones[0].geo_zones[0].id,
|
||||||
|
]),
|
||||||
},
|
},
|
||||||
}),
|
}),
|
||||||
buildExpectedEventMessageShape({
|
buildExpectedEventMessageShape({
|
||||||
eventName: FulfillmentEvents.SERVICE_ZONE_DELETED,
|
eventName: FulfillmentEvents.SERVICE_ZONE_DELETED,
|
||||||
action: "deleted",
|
action: "deleted",
|
||||||
object: "service_zone",
|
object: "service_zone",
|
||||||
data: { id: originalFulfillmentSet.service_zones[0].id },
|
data: {
|
||||||
|
id: expect.arrayContaining([
|
||||||
|
originalFulfillmentSet.service_zones[0].id,
|
||||||
|
]),
|
||||||
|
},
|
||||||
}),
|
}),
|
||||||
buildExpectedEventMessageShape({
|
buildExpectedEventMessageShape({
|
||||||
eventName: FulfillmentEvents.GEO_ZONE_DELETED,
|
eventName: FulfillmentEvents.GEO_ZONE_DELETED,
|
||||||
action: "deleted",
|
action: "deleted",
|
||||||
object: "geo_zone",
|
object: "geo_zone",
|
||||||
data: {
|
data: {
|
||||||
id: originalFulfillmentSet.service_zones[0].geo_zones[0]
|
id: expect.arrayContaining([
|
||||||
.id,
|
originalFulfillmentSet.service_zones[0].geo_zones[0].id,
|
||||||
|
]),
|
||||||
},
|
},
|
||||||
}),
|
}),
|
||||||
]),
|
]),
|
||||||
@@ -1215,7 +1245,7 @@ moduleIntegrationTestRunner<IFulfillmentModuleService>({
|
|||||||
)
|
)
|
||||||
|
|
||||||
expect(updatedFulfillmentSets).toHaveLength(2)
|
expect(updatedFulfillmentSets).toHaveLength(2)
|
||||||
expect(eventBusEmitSpy.mock.calls[1][0]).toHaveLength(6)
|
expect(eventBusEmitSpy.mock.calls[1][0]).toHaveLength(3)
|
||||||
|
|
||||||
for (const data_ of updateData) {
|
for (const data_ of updateData) {
|
||||||
const expectedFulfillmentSet = updatedFulfillmentSets.find(
|
const expectedFulfillmentSet = updatedFulfillmentSets.find(
|
||||||
@@ -1259,20 +1289,26 @@ moduleIntegrationTestRunner<IFulfillmentModuleService>({
|
|||||||
eventName: FulfillmentEvents.FULFILLMENT_SET_UPDATED,
|
eventName: FulfillmentEvents.FULFILLMENT_SET_UPDATED,
|
||||||
action: "updated",
|
action: "updated",
|
||||||
object: "fulfillment_set",
|
object: "fulfillment_set",
|
||||||
data: { id: expectedFulfillmentSet.id },
|
data: {
|
||||||
|
id: expect.arrayContaining([expectedFulfillmentSet.id]),
|
||||||
|
},
|
||||||
}),
|
}),
|
||||||
buildExpectedEventMessageShape({
|
buildExpectedEventMessageShape({
|
||||||
eventName: FulfillmentEvents.SERVICE_ZONE_CREATED,
|
eventName: FulfillmentEvents.SERVICE_ZONE_CREATED,
|
||||||
action: "created",
|
action: "created",
|
||||||
object: "service_zone",
|
object: "service_zone",
|
||||||
data: { id: createdServiceZone.id },
|
data: {
|
||||||
|
id: expect.arrayContaining([createdServiceZone.id]),
|
||||||
|
},
|
||||||
}),
|
}),
|
||||||
buildExpectedEventMessageShape({
|
buildExpectedEventMessageShape({
|
||||||
eventName: FulfillmentEvents.GEO_ZONE_CREATED,
|
eventName: FulfillmentEvents.GEO_ZONE_CREATED,
|
||||||
action: "created",
|
action: "created",
|
||||||
object: "geo_zone",
|
object: "geo_zone",
|
||||||
data: {
|
data: {
|
||||||
id: createdServiceZone.geo_zones[0].id,
|
id: expect.arrayContaining([
|
||||||
|
createdServiceZone.geo_zones[0].id,
|
||||||
|
]),
|
||||||
},
|
},
|
||||||
}),
|
}),
|
||||||
]),
|
]),
|
||||||
|
|||||||
+4
-4
@@ -154,7 +154,7 @@ moduleIntegrationTestRunner<IFulfillmentModuleService>({
|
|||||||
const geoZones = await service.createGeoZones(data)
|
const geoZones = await service.createGeoZones(data)
|
||||||
|
|
||||||
expect(geoZones).toHaveLength(2)
|
expect(geoZones).toHaveLength(2)
|
||||||
expect(eventBusEmitSpy.mock.calls[0][0]).toHaveLength(2)
|
expect(eventBusEmitSpy.mock.calls[0][0]).toHaveLength(1)
|
||||||
|
|
||||||
let i = 0
|
let i = 0
|
||||||
for (const data_ of data) {
|
for (const data_ of data) {
|
||||||
@@ -172,7 +172,7 @@ moduleIntegrationTestRunner<IFulfillmentModuleService>({
|
|||||||
eventName: FulfillmentEvents.GEO_ZONE_CREATED,
|
eventName: FulfillmentEvents.GEO_ZONE_CREATED,
|
||||||
action: "created",
|
action: "created",
|
||||||
object: "geo_zone",
|
object: "geo_zone",
|
||||||
data: { id: geoZones[i].id },
|
data: { id: expect.arrayContaining([geoZones[i].id]) },
|
||||||
}),
|
}),
|
||||||
]),
|
]),
|
||||||
{
|
{
|
||||||
@@ -331,7 +331,7 @@ moduleIntegrationTestRunner<IFulfillmentModuleService>({
|
|||||||
const updatedGeoZones = await service.updateGeoZones(updateData)
|
const updatedGeoZones = await service.updateGeoZones(updateData)
|
||||||
|
|
||||||
expect(updatedGeoZones).toHaveLength(2)
|
expect(updatedGeoZones).toHaveLength(2)
|
||||||
expect(eventBusEmitSpy.mock.calls[0][0]).toHaveLength(2)
|
expect(eventBusEmitSpy.mock.calls[0][0]).toHaveLength(1)
|
||||||
|
|
||||||
for (const data_ of updateData) {
|
for (const data_ of updateData) {
|
||||||
const expectedGeoZone = updatedGeoZones.find(
|
const expectedGeoZone = updatedGeoZones.find(
|
||||||
@@ -352,7 +352,7 @@ moduleIntegrationTestRunner<IFulfillmentModuleService>({
|
|||||||
eventName: FulfillmentEvents.GEO_ZONE_UPDATED,
|
eventName: FulfillmentEvents.GEO_ZONE_UPDATED,
|
||||||
action: "updated",
|
action: "updated",
|
||||||
object: "geo_zone",
|
object: "geo_zone",
|
||||||
data: { id: expectedGeoZone.id },
|
data: { id: expect.arrayContaining([expectedGeoZone.id]) },
|
||||||
}),
|
}),
|
||||||
]),
|
]),
|
||||||
{
|
{
|
||||||
|
|||||||
+1
-1
@@ -510,7 +510,7 @@ moduleIntegrationTestRunner<IFulfillmentModuleService>({
|
|||||||
|
|
||||||
expect(updatedServiceZones).toHaveLength(2)
|
expect(updatedServiceZones).toHaveLength(2)
|
||||||
|
|
||||||
expect(eventBusEmitSpy.mock.calls[0][0]).toHaveLength(6) // Since the update only calls create and update which are already tested, only check the length
|
expect(eventBusEmitSpy.mock.calls[0][0]).toHaveLength(3) // Since the update only calls create and update which are already tested, only check the length
|
||||||
|
|
||||||
for (const data_ of updateData) {
|
for (const data_ of updateData) {
|
||||||
const expectedServiceZone = updatedServiceZones.find(
|
const expectedServiceZone = updatedServiceZones.find(
|
||||||
|
|||||||
+16
-4
@@ -582,7 +582,7 @@ moduleIntegrationTestRunner<IFulfillmentModuleService>({
|
|||||||
)
|
)
|
||||||
|
|
||||||
expect(createdShippingOptions).toHaveLength(2)
|
expect(createdShippingOptions).toHaveLength(2)
|
||||||
expect(eventBusEmitSpy.mock.calls[0][0]).toHaveLength(6)
|
expect(eventBusEmitSpy.mock.calls[0][0]).toHaveLength(3)
|
||||||
|
|
||||||
let i = 0
|
let i = 0
|
||||||
for (const data_ of createData) {
|
for (const data_ of createData) {
|
||||||
@@ -619,19 +619,31 @@ moduleIntegrationTestRunner<IFulfillmentModuleService>({
|
|||||||
eventName: FulfillmentEvents.SHIPPING_OPTION_CREATED,
|
eventName: FulfillmentEvents.SHIPPING_OPTION_CREATED,
|
||||||
action: "created",
|
action: "created",
|
||||||
object: "shipping_option",
|
object: "shipping_option",
|
||||||
data: { id: createdShippingOptions[i].id },
|
data: {
|
||||||
|
id: expect.arrayContaining([
|
||||||
|
createdShippingOptions[i].id,
|
||||||
|
]),
|
||||||
|
},
|
||||||
}),
|
}),
|
||||||
buildExpectedEventMessageShape({
|
buildExpectedEventMessageShape({
|
||||||
eventName: FulfillmentEvents.SHIPPING_OPTION_TYPE_CREATED,
|
eventName: FulfillmentEvents.SHIPPING_OPTION_TYPE_CREATED,
|
||||||
action: "created",
|
action: "created",
|
||||||
object: "shipping_option_type",
|
object: "shipping_option_type",
|
||||||
data: { id: createdShippingOptions[i].type.id },
|
data: {
|
||||||
|
id: expect.arrayContaining([
|
||||||
|
createdShippingOptions[i].type.id,
|
||||||
|
]),
|
||||||
|
},
|
||||||
}),
|
}),
|
||||||
buildExpectedEventMessageShape({
|
buildExpectedEventMessageShape({
|
||||||
eventName: FulfillmentEvents.SHIPPING_OPTION_RULE_CREATED,
|
eventName: FulfillmentEvents.SHIPPING_OPTION_RULE_CREATED,
|
||||||
action: "created",
|
action: "created",
|
||||||
object: "shipping_option_rule",
|
object: "shipping_option_rule",
|
||||||
data: { id: createdShippingOptions[i].rules[0].id },
|
data: {
|
||||||
|
id: expect.arrayContaining([
|
||||||
|
createdShippingOptions[i].rules[0].id,
|
||||||
|
]),
|
||||||
|
},
|
||||||
}),
|
}),
|
||||||
]),
|
]),
|
||||||
{
|
{
|
||||||
|
|||||||
+6
-2
@@ -100,7 +100,7 @@ moduleIntegrationTestRunner<IFulfillmentModuleService>({
|
|||||||
await service.createShippingProfiles(createData)
|
await service.createShippingProfiles(createData)
|
||||||
|
|
||||||
expect(createdShippingProfiles).toHaveLength(2)
|
expect(createdShippingProfiles).toHaveLength(2)
|
||||||
expect(eventBusEmitSpy.mock.calls[0][0]).toHaveLength(2)
|
expect(eventBusEmitSpy.mock.calls[0][0]).toHaveLength(1)
|
||||||
|
|
||||||
let i = 0
|
let i = 0
|
||||||
for (const data_ of createData) {
|
for (const data_ of createData) {
|
||||||
@@ -117,7 +117,11 @@ moduleIntegrationTestRunner<IFulfillmentModuleService>({
|
|||||||
eventName: FulfillmentEvents.SHIPPING_PROFILE_CREATED,
|
eventName: FulfillmentEvents.SHIPPING_PROFILE_CREATED,
|
||||||
action: "created",
|
action: "created",
|
||||||
object: "shipping_profile",
|
object: "shipping_profile",
|
||||||
data: { id: createdShippingProfiles[i].id },
|
data: {
|
||||||
|
id: expect.arrayContaining([
|
||||||
|
createdShippingProfiles[i].id,
|
||||||
|
]),
|
||||||
|
},
|
||||||
}),
|
}),
|
||||||
]),
|
]),
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -19,7 +19,7 @@ import { asValue } from "awilix"
|
|||||||
import * as path from "path"
|
import * as path from "path"
|
||||||
import { setTimeout } from "timers/promises"
|
import { setTimeout } from "timers/promises"
|
||||||
import { EventBusServiceMock } from "../__fixtures__"
|
import { EventBusServiceMock } from "../__fixtures__"
|
||||||
import { dbName } from "../__fixtures__/medusa-config"
|
import config, { dbName } from "../__fixtures__/medusa-config"
|
||||||
|
|
||||||
const eventBusMock = new EventBusServiceMock()
|
const eventBusMock = new EventBusServiceMock()
|
||||||
const queryMock = {
|
const queryMock = {
|
||||||
@@ -147,14 +147,15 @@ describe("DataSynchronizer", () => {
|
|||||||
// Mock query response for products
|
// Mock query response for products
|
||||||
queryMock.graph.mockImplementation(async (config) => {
|
queryMock.graph.mockImplementation(async (config) => {
|
||||||
if (Array.isArray(config.filters.id)) {
|
if (Array.isArray(config.filters.id)) {
|
||||||
|
let data: any[] = []
|
||||||
if (config.filters.id.includes(testProductId)) {
|
if (config.filters.id.includes(testProductId)) {
|
||||||
return {
|
data.push(mockData[0])
|
||||||
data: [mockData[0]],
|
|
||||||
}
|
|
||||||
} else if (config.filters.id.includes(testProductId2)) {
|
} else if (config.filters.id.includes(testProductId2)) {
|
||||||
return {
|
data.push(mockData[1])
|
||||||
data: [mockData[1]],
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return {
|
||||||
|
data,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -141,6 +141,7 @@ const beforeAll_ = async () => {
|
|||||||
;(index as any).eventBusModuleService_ = eventBusMock
|
;(index as any).eventBusModuleService_ = eventBusMock
|
||||||
|
|
||||||
await globalApp.onApplicationStart()
|
await globalApp.onApplicationStart()
|
||||||
|
await setTimeout(3000)
|
||||||
;(index as any).storageProvider_.query_ = queryMock
|
;(index as any).storageProvider_.query_ = queryMock
|
||||||
|
|
||||||
return globalApp
|
return globalApp
|
||||||
@@ -196,6 +197,8 @@ describe("IndexModuleService", function () {
|
|||||||
await dbUtils.shutdown(dbName)
|
await dbUtils.shutdown(dbName)
|
||||||
})
|
})
|
||||||
|
|
||||||
|
afterEach(afterEach_)
|
||||||
|
|
||||||
describe("on created or attached events", function () {
|
describe("on created or attached events", function () {
|
||||||
let manager
|
let manager
|
||||||
|
|
||||||
@@ -222,7 +225,7 @@ describe("IndexModuleService", function () {
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "PriceSet.created",
|
name: "pricing.price-set.created",
|
||||||
data: {
|
data: {
|
||||||
id: priceSetId,
|
id: priceSetId,
|
||||||
},
|
},
|
||||||
@@ -247,7 +250,6 @@ describe("IndexModuleService", function () {
|
|||||||
]
|
]
|
||||||
|
|
||||||
beforeEach(async () => {
|
beforeEach(async () => {
|
||||||
await setTimeout(1000)
|
|
||||||
await beforeEach_(eventDataToEmit)
|
await beforeEach_(eventDataToEmit)
|
||||||
|
|
||||||
manager = (medusaApp.sharedContainer!.resolve(Modules.INDEX) as any)
|
manager = (medusaApp.sharedContainer!.resolve(Modules.INDEX) as any)
|
||||||
@@ -392,7 +394,7 @@ describe("IndexModuleService", function () {
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "PriceSet.created",
|
name: "pricing.price-set.created",
|
||||||
data: {
|
data: {
|
||||||
id: priceSetId,
|
id: priceSetId,
|
||||||
},
|
},
|
||||||
@@ -689,7 +691,7 @@ describe("IndexModuleService", function () {
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "PriceSet.created",
|
name: "pricing.price-set.created",
|
||||||
data: {
|
data: {
|
||||||
id: priceSetId,
|
id: priceSetId,
|
||||||
},
|
},
|
||||||
@@ -761,8 +763,6 @@ describe("IndexModuleService", function () {
|
|||||||
await eventBusMock.emit(deleteEventDataToEmit)
|
await eventBusMock.emit(deleteEventDataToEmit)
|
||||||
})
|
})
|
||||||
|
|
||||||
afterEach(afterEach_)
|
|
||||||
|
|
||||||
it("should consume all deleted events and delete the index entries", async () => {
|
it("should consume all deleted events and delete the index entries", async () => {
|
||||||
const indexEntries = await manager.find(toMikroORMEntity(IndexData), {})
|
const indexEntries = await manager.find(toMikroORMEntity(IndexData), {})
|
||||||
const indexRelationEntries = await manager.find(
|
const indexRelationEntries = await manager.find(
|
||||||
|
|||||||
@@ -290,7 +290,7 @@ export class DataSynchronizer {
|
|||||||
filters["updated_at"] = { $gt: pagination.updated_at }
|
filters["updated_at"] = { $gt: pagination.updated_at }
|
||||||
}
|
}
|
||||||
|
|
||||||
const { data } = await this.#query.graph({
|
const queryResult = await this.#query.graph({
|
||||||
entity: alias,
|
entity: alias,
|
||||||
fields: [entityPrimaryKey],
|
fields: [entityPrimaryKey],
|
||||||
filters,
|
filters,
|
||||||
@@ -302,10 +302,12 @@ export class DataSynchronizer {
|
|||||||
},
|
},
|
||||||
})
|
})
|
||||||
|
|
||||||
if (!data.length) {
|
if (!queryResult?.data?.length) {
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const data = queryResult.data
|
||||||
|
|
||||||
const envelop: Event = {
|
const envelop: Event = {
|
||||||
data,
|
data,
|
||||||
name: !isLink
|
name: !isLink
|
||||||
|
|||||||
@@ -163,9 +163,11 @@ export class PostgresProvider implements IndexTypes.StorageProvider {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
protected static parseMessageData<T>(message?: Event): {
|
protected static parseMessageData<TData extends { id: string | string[] }>(
|
||||||
|
message?: Event
|
||||||
|
): {
|
||||||
action: string
|
action: string
|
||||||
data: { id: string }[]
|
data: TData[]
|
||||||
ids: string[]
|
ids: string[]
|
||||||
} | void {
|
} | void {
|
||||||
const isExpectedFormat =
|
const isExpectedFormat =
|
||||||
@@ -177,7 +179,7 @@ export class PostgresProvider implements IndexTypes.StorageProvider {
|
|||||||
|
|
||||||
const result: {
|
const result: {
|
||||||
action: string
|
action: string
|
||||||
data: { id: string }[]
|
data: TData[]
|
||||||
ids: string[]
|
ids: string[]
|
||||||
} = {
|
} = {
|
||||||
action: "",
|
action: "",
|
||||||
@@ -186,43 +188,64 @@ export class PostgresProvider implements IndexTypes.StorageProvider {
|
|||||||
}
|
}
|
||||||
|
|
||||||
result.action = message!.metadata!.action as string
|
result.action = message!.metadata!.action as string
|
||||||
result.data = message!.data as { id: string }[]
|
result.data = message!.data as TData[]
|
||||||
result.data = Array.isArray(result.data) ? result.data : [result.data]
|
result.data = Array.isArray(result.data) ? result.data : [result.data]
|
||||||
result.ids = result.data.map((d) => d.id)
|
result.ids = result.data.flatMap((d) =>
|
||||||
|
Array.isArray(d.id) ? d.id : [d.id]
|
||||||
|
)
|
||||||
|
|
||||||
return result
|
return result
|
||||||
}
|
}
|
||||||
|
|
||||||
consumeEvent(
|
consumeEvent(
|
||||||
schemaEntityObjectRepresentation: IndexTypes.SchemaObjectEntityRepresentation
|
schemaEntityObjectRepresentation: IndexTypes.SchemaObjectEntityRepresentation
|
||||||
): Subscriber<{ id: string }> {
|
): Subscriber<{ id: string | string[] }> {
|
||||||
return async (data: Event) => {
|
return async (event: Event) => {
|
||||||
await this.#isReady_
|
await this.#isReady_
|
||||||
|
|
||||||
const data_: { id: string }[] = Array.isArray(data.data)
|
const data_: { id: string }[] = Array.isArray(event.data)
|
||||||
? data.data
|
? event.data
|
||||||
: [data.data]
|
: [event.data]
|
||||||
let ids: string[] = data_.map((d) => d.id)
|
let ids: string[] = data_.flatMap((d) =>
|
||||||
let action = data.name.split(".").pop() || ""
|
Array.isArray(d.id) ? d.id : [d.id]
|
||||||
|
)
|
||||||
|
let action = event.name.split(".").pop() || ""
|
||||||
|
|
||||||
const parsedMessage = PostgresProvider.parseMessageData(data)
|
const parsedMessage = PostgresProvider.parseMessageData(event)
|
||||||
if (parsedMessage) {
|
if (parsedMessage) {
|
||||||
action = parsedMessage.action
|
action = parsedMessage.action
|
||||||
ids = parsedMessage.ids
|
ids = parsedMessage.ids
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const targetMethod = this.eventActionToMethodMap_[action]
|
||||||
|
|
||||||
|
if (!targetMethod) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
const { fields, alias } = schemaEntityObjectRepresentation
|
const { fields, alias } = schemaEntityObjectRepresentation
|
||||||
|
|
||||||
|
let withDeleted: boolean | undefined
|
||||||
|
if (action === CommonEvents.DELETED || action === CommonEvents.DETACHED) {
|
||||||
|
withDeleted = true
|
||||||
|
}
|
||||||
|
|
||||||
|
// Process ids in batches of 100
|
||||||
|
const batchSize = 100
|
||||||
|
const idsBatches: string[][] = []
|
||||||
|
|
||||||
|
for (let i = 0; i < ids.length; i += batchSize) {
|
||||||
|
idsBatches.push(ids.slice(i, i + batchSize))
|
||||||
|
}
|
||||||
|
|
||||||
|
for (const idsBatch of idsBatches) {
|
||||||
const graphConfig: Parameters<QueryGraphFunction>[0] = {
|
const graphConfig: Parameters<QueryGraphFunction>[0] = {
|
||||||
entity: alias,
|
entity: alias,
|
||||||
filters: {
|
filters: {
|
||||||
id: ids,
|
id: idsBatch,
|
||||||
},
|
},
|
||||||
fields: [...new Set(["id", ...fields])],
|
fields: [...new Set(["id", ...fields])],
|
||||||
}
|
withDeleted,
|
||||||
|
|
||||||
if (action === CommonEvents.DELETED || action === CommonEvents.DETACHED) {
|
|
||||||
graphConfig.withDeleted = true
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const { data: entityData } = await this.query_.graph(graphConfig)
|
const { data: entityData } = await this.query_.graph(graphConfig)
|
||||||
@@ -233,15 +256,10 @@ export class PostgresProvider implements IndexTypes.StorageProvider {
|
|||||||
schemaEntityObjectRepresentation,
|
schemaEntityObjectRepresentation,
|
||||||
}
|
}
|
||||||
|
|
||||||
const targetMethod = this.eventActionToMethodMap_[action]
|
|
||||||
|
|
||||||
if (!targetMethod) {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
await this[targetMethod](argument)
|
await this[targetMethod](argument)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@InjectManager()
|
@InjectManager()
|
||||||
async query<const TEntry extends string>(
|
async query<const TEntry extends string>(
|
||||||
@@ -374,7 +392,9 @@ export class PostgresProvider implements IndexTypes.StorageProvider {
|
|||||||
@MedusaContext() sharedContext: Context<SqlEntityManager> = {}
|
@MedusaContext() sharedContext: Context<SqlEntityManager> = {}
|
||||||
) {
|
) {
|
||||||
const { transactionManager: em } = sharedContext
|
const { transactionManager: em } = sharedContext
|
||||||
const indexRepository = em!.getRepository(toMikroORMEntity(IndexData))
|
const indexRepository = em!.getRepository(
|
||||||
|
toMikroORMEntity(IndexData)
|
||||||
|
) as EntityRepository<any>
|
||||||
const indexRelationRepository: EntityRepository<any> = em!.getRepository(
|
const indexRelationRepository: EntityRepository<any> = em!.getRepository(
|
||||||
toMikroORMEntity(IndexRelation)
|
toMikroORMEntity(IndexRelation)
|
||||||
)
|
)
|
||||||
@@ -385,33 +405,32 @@ export class PostgresProvider implements IndexTypes.StorageProvider {
|
|||||||
parentsProperties,
|
parentsProperties,
|
||||||
} = PostgresProvider.parseData(data, schemaEntityObjectRepresentation)
|
} = PostgresProvider.parseData(data, schemaEntityObjectRepresentation)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Clean the entity data to only keep the properties that are defined in the schema
|
||||||
|
*/
|
||||||
|
const cleanedData = data_.map((entityData) => {
|
||||||
|
return entityProperties.reduce((acc, property) => {
|
||||||
|
acc[property] = entityData[property]
|
||||||
|
return acc
|
||||||
|
}, {}) as TData
|
||||||
|
})
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Loop through the data and create index entries for each entity as well as the
|
* Loop through the data and create index entries for each entity as well as the
|
||||||
* index relation entries if the entity has parents
|
* index relation entries if the entity has parents
|
||||||
*/
|
*/
|
||||||
|
|
||||||
for (const entityData of data_) {
|
const entitiesToUpsert: Set<string> = new Set()
|
||||||
/**
|
const relationsToUpsert: Set<string> = new Set()
|
||||||
* Clean the entity data to only keep the properties that are defined in the schema
|
|
||||||
*/
|
|
||||||
|
|
||||||
const cleanedEntityData = entityProperties.reduce((acc, property) => {
|
cleanedData.forEach((entityData, index) => {
|
||||||
acc[property] = entityData[property]
|
entitiesToUpsert.add(
|
||||||
return acc
|
JSON.stringify({
|
||||||
}, {}) as TData
|
id: entityData.id,
|
||||||
|
|
||||||
await indexRepository.upsert(
|
|
||||||
{
|
|
||||||
id: cleanedEntityData.id,
|
|
||||||
name: entity,
|
name: entity,
|
||||||
data: cleanedEntityData,
|
data: entityData,
|
||||||
staled_at: null,
|
staled_at: null,
|
||||||
},
|
})
|
||||||
{
|
|
||||||
onConflictAction: "merge",
|
|
||||||
onConflictFields: ["id", "name"],
|
|
||||||
onConflictMergeFields: ["data", "staled_at"],
|
|
||||||
}
|
|
||||||
)
|
)
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -422,7 +441,7 @@ export class PostgresProvider implements IndexTypes.StorageProvider {
|
|||||||
parentsProperties
|
parentsProperties
|
||||||
)) {
|
)) {
|
||||||
const parentAlias = parentProperties[0].split(".")[0]
|
const parentAlias = parentProperties[0].split(".")[0]
|
||||||
const parentData = entityData[parentAlias] as TData[]
|
const parentData = data_[index][parentAlias] as TData[]
|
||||||
|
|
||||||
if (!parentData) {
|
if (!parentData) {
|
||||||
continue
|
continue
|
||||||
@@ -433,29 +452,34 @@ export class PostgresProvider implements IndexTypes.StorageProvider {
|
|||||||
: [parentData]
|
: [parentData]
|
||||||
|
|
||||||
for (const parentData_ of parentDataCollection) {
|
for (const parentData_ of parentDataCollection) {
|
||||||
await indexRepository.upsert(
|
relationsToUpsert.add(
|
||||||
{
|
JSON.stringify({
|
||||||
id: (parentData_ as any).id,
|
parent_id: parentData_.id,
|
||||||
name: parentEntity,
|
|
||||||
data: parentData_,
|
|
||||||
staled_at: null,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
onConflictAction: "merge",
|
|
||||||
onConflictFields: ["id", "name"],
|
|
||||||
onConflictMergeFields: ["staled_at"],
|
|
||||||
}
|
|
||||||
)
|
|
||||||
|
|
||||||
await indexRelationRepository.upsert(
|
|
||||||
{
|
|
||||||
parent_id: (parentData_ as any).id,
|
|
||||||
parent_name: parentEntity,
|
parent_name: parentEntity,
|
||||||
child_id: cleanedEntityData.id,
|
child_id: entityData.id,
|
||||||
child_name: entity,
|
child_name: entity,
|
||||||
pivot: `${parentEntity}-${entity}`,
|
pivot: `${parentEntity}-${entity}`,
|
||||||
staled_at: null,
|
staled_at: null,
|
||||||
},
|
})
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
if (entitiesToUpsert.size) {
|
||||||
|
await indexRepository.upsertMany(
|
||||||
|
Array.from(entitiesToUpsert).map((entity) => JSON.parse(entity)),
|
||||||
|
{
|
||||||
|
onConflictAction: "merge",
|
||||||
|
onConflictFields: ["id", "name"],
|
||||||
|
onConflictMergeFields: ["data", "staled_at"],
|
||||||
|
}
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
if (relationsToUpsert.size) {
|
||||||
|
await indexRelationRepository.upsertMany(
|
||||||
|
Array.from(relationsToUpsert).map((relation) => JSON.parse(relation)),
|
||||||
{
|
{
|
||||||
onConflictAction: "merge",
|
onConflictAction: "merge",
|
||||||
onConflictFields: [
|
onConflictFields: [
|
||||||
@@ -470,8 +494,6 @@ export class PostgresProvider implements IndexTypes.StorageProvider {
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Update the index entry when this event is emitted.
|
* Update the index entry when this event is emitted.
|
||||||
@@ -495,7 +517,9 @@ export class PostgresProvider implements IndexTypes.StorageProvider {
|
|||||||
@MedusaContext() sharedContext: Context<SqlEntityManager> = {}
|
@MedusaContext() sharedContext: Context<SqlEntityManager> = {}
|
||||||
) {
|
) {
|
||||||
const { transactionManager: em } = sharedContext
|
const { transactionManager: em } = sharedContext
|
||||||
const indexRepository = em!.getRepository(toMikroORMEntity(IndexData))
|
const indexRepository = em!.getRepository(
|
||||||
|
toMikroORMEntity(IndexData)
|
||||||
|
) as EntityRepository<any>
|
||||||
|
|
||||||
const { data: data_, entityProperties } = PostgresProvider.parseData(
|
const { data: data_, entityProperties } = PostgresProvider.parseData(
|
||||||
data,
|
data,
|
||||||
@@ -503,8 +527,7 @@ export class PostgresProvider implements IndexTypes.StorageProvider {
|
|||||||
)
|
)
|
||||||
|
|
||||||
await indexRepository.upsertMany(
|
await indexRepository.upsertMany(
|
||||||
data_.map(
|
data_.map((entityData) => {
|
||||||
(entityData) => {
|
|
||||||
return {
|
return {
|
||||||
id: entityData.id,
|
id: entityData.id,
|
||||||
name: entity,
|
name: entity,
|
||||||
@@ -514,14 +537,13 @@ export class PostgresProvider implements IndexTypes.StorageProvider {
|
|||||||
}, {}),
|
}, {}),
|
||||||
staled_at: null,
|
staled_at: null,
|
||||||
}
|
}
|
||||||
},
|
}),
|
||||||
{
|
{
|
||||||
onConflictAction: "merge",
|
onConflictAction: "merge",
|
||||||
onConflictFields: ["id", "name"],
|
onConflictFields: ["id", "name"],
|
||||||
onConflictMergeFields: ["data", "staled_at"],
|
onConflictMergeFields: ["data", "staled_at"],
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -601,7 +623,7 @@ export class PostgresProvider implements IndexTypes.StorageProvider {
|
|||||||
const indexRepository = em!.getRepository(toMikroORMEntity(IndexData))
|
const indexRepository = em!.getRepository(toMikroORMEntity(IndexData))
|
||||||
const indexRelationRepository = em!.getRepository(
|
const indexRelationRepository = em!.getRepository(
|
||||||
toMikroORMEntity(IndexRelation)
|
toMikroORMEntity(IndexRelation)
|
||||||
)
|
) as EntityRepository<any>
|
||||||
|
|
||||||
const { data: data_, entityProperties } = PostgresProvider.parseData(
|
const { data: data_, entityProperties } = PostgresProvider.parseData(
|
||||||
data,
|
data,
|
||||||
@@ -652,66 +674,56 @@ export class PostgresProvider implements IndexTypes.StorageProvider {
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
for (const entityData of data_) {
|
|
||||||
/**
|
/**
|
||||||
* Clean the link entity data to only keep the properties that are defined in the schema
|
* Clean the link entity data to only keep the properties that are defined in the schema
|
||||||
*/
|
*/
|
||||||
|
|
||||||
const cleanedEntityData = entityProperties.reduce((acc, property) => {
|
const cleanedData = data_.map((entityData) => {
|
||||||
|
return entityProperties.reduce((acc, property) => {
|
||||||
acc[property] = entityData[property]
|
acc[property] = entityData[property]
|
||||||
return acc
|
return acc
|
||||||
}, {}) as TData
|
}, {}) as TData
|
||||||
|
})
|
||||||
|
|
||||||
await indexRepository.upsert(
|
let relationsToUpsert: any[] = []
|
||||||
{
|
const entitiesToUpdate = cleanedData.map((entityData) => {
|
||||||
id: cleanedEntityData.id,
|
relationsToUpsert.push(
|
||||||
name: entity,
|
|
||||||
data: cleanedEntityData,
|
|
||||||
staled_at: null,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
onConflictAction: "merge",
|
|
||||||
onConflictFields: ["id", "name"],
|
|
||||||
onConflictMergeFields: ["data", "staled_at"],
|
|
||||||
}
|
|
||||||
)
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Create the index relation entries for the parent entity and the child entity
|
|
||||||
*/
|
|
||||||
|
|
||||||
await indexRelationRepository.upsert(
|
|
||||||
{
|
{
|
||||||
parent_id: entityData[parentPropertyId] as string,
|
parent_id: entityData[parentPropertyId] as string,
|
||||||
parent_name: parentEntityName,
|
parent_name: parentEntityName,
|
||||||
child_id: cleanedEntityData.id,
|
child_id: entityData.id,
|
||||||
child_name: entity,
|
child_name: entity,
|
||||||
pivot: `${parentEntityName}-${entity}`,
|
pivot: `${parentEntityName}-${entity}`,
|
||||||
staled_at: null,
|
staled_at: null,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
onConflictAction: "merge",
|
parent_id: entityData.id,
|
||||||
onConflictFields: [
|
|
||||||
"pivot",
|
|
||||||
"parent_id",
|
|
||||||
"child_id",
|
|
||||||
"parent_name",
|
|
||||||
"child_name",
|
|
||||||
],
|
|
||||||
onConflictMergeFields: ["staled_at"],
|
|
||||||
}
|
|
||||||
)
|
|
||||||
|
|
||||||
await indexRelationRepository.upsert(
|
|
||||||
{
|
|
||||||
parent_id: cleanedEntityData.id,
|
|
||||||
parent_name: entity,
|
parent_name: entity,
|
||||||
child_id: entityData[childPropertyId] as string,
|
child_id: entityData[childPropertyId] as string,
|
||||||
child_name: childEntityName,
|
child_name: childEntityName,
|
||||||
pivot: `${entity}-${childEntityName}`,
|
pivot: `${entity}-${childEntityName}`,
|
||||||
staled_at: null,
|
staled_at: null,
|
||||||
},
|
}
|
||||||
{
|
)
|
||||||
|
|
||||||
|
return {
|
||||||
|
id: entityData.id,
|
||||||
|
name: entity,
|
||||||
|
data: entityData,
|
||||||
|
staled_at: null,
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
if (entitiesToUpdate.length) {
|
||||||
|
await indexRepository.upsertMany(entitiesToUpdate, {
|
||||||
|
onConflictAction: "merge",
|
||||||
|
onConflictFields: ["id", "name"],
|
||||||
|
onConflictMergeFields: ["data", "staled_at"],
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
if (relationsToUpsert.length) {
|
||||||
|
await indexRelationRepository.upsertMany(relationsToUpsert, {
|
||||||
onConflictAction: "merge",
|
onConflictAction: "merge",
|
||||||
onConflictFields: [
|
onConflictFields: [
|
||||||
"pivot",
|
"pivot",
|
||||||
@@ -721,8 +733,7 @@ export class PostgresProvider implements IndexTypes.StorageProvider {
|
|||||||
"child_name",
|
"child_name",
|
||||||
],
|
],
|
||||||
onConflictMergeFields: ["staled_at"],
|
onConflictMergeFields: ["staled_at"],
|
||||||
}
|
})
|
||||||
)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -5,7 +5,11 @@ import {
|
|||||||
ModuleJoinerConfig,
|
ModuleJoinerConfig,
|
||||||
ModuleJoinerRelationship,
|
ModuleJoinerRelationship,
|
||||||
} from "@medusajs/framework/types"
|
} from "@medusajs/framework/types"
|
||||||
import { CommonEvents, GraphQLUtils } from "@medusajs/framework/utils"
|
import {
|
||||||
|
buildModuleResourceEventName,
|
||||||
|
CommonEvents,
|
||||||
|
GraphQLUtils,
|
||||||
|
} from "@medusajs/framework/utils"
|
||||||
import { schemaObjectRepresentationPropertiesToOmit } from "@types"
|
import { schemaObjectRepresentationPropertiesToOmit } from "@types"
|
||||||
|
|
||||||
export const CustomDirectives = {
|
export const CustomDirectives = {
|
||||||
@@ -561,9 +565,23 @@ function processEntity(
|
|||||||
|
|
||||||
intermediateEntityObjectRepresentationRef.alias =
|
intermediateEntityObjectRepresentationRef.alias =
|
||||||
intermediateEntityAlias
|
intermediateEntityAlias
|
||||||
|
|
||||||
intermediateEntityObjectRepresentationRef.listeners = [
|
intermediateEntityObjectRepresentationRef.listeners = [
|
||||||
intermediateEntityName + "." + CommonEvents.CREATED,
|
buildModuleResourceEventName({
|
||||||
intermediateEntityName + "." + CommonEvents.UPDATED,
|
action: CommonEvents.CREATED,
|
||||||
|
objectName: intermediateEntityName,
|
||||||
|
prefix: intermediateEntityModule.serviceName,
|
||||||
|
}),
|
||||||
|
buildModuleResourceEventName({
|
||||||
|
action: CommonEvents.UPDATED,
|
||||||
|
objectName: intermediateEntityName,
|
||||||
|
prefix: intermediateEntityModule.serviceName,
|
||||||
|
}),
|
||||||
|
buildModuleResourceEventName({
|
||||||
|
action: CommonEvents.DELETED,
|
||||||
|
objectName: intermediateEntityName,
|
||||||
|
prefix: intermediateEntityModule.serviceName,
|
||||||
|
}),
|
||||||
]
|
]
|
||||||
intermediateEntityObjectRepresentationRef.moduleConfig =
|
intermediateEntityObjectRepresentationRef.moduleConfig =
|
||||||
intermediateEntityModule
|
intermediateEntityModule
|
||||||
|
|||||||
@@ -26,6 +26,7 @@ import {
|
|||||||
MedusaContext,
|
MedusaContext,
|
||||||
MedusaError,
|
MedusaError,
|
||||||
MedusaService,
|
MedusaService,
|
||||||
|
moduleEventBuilderFactory,
|
||||||
Modules,
|
Modules,
|
||||||
partitionArray,
|
partitionArray,
|
||||||
} from "@medusajs/framework/utils"
|
} from "@medusajs/framework/utils"
|
||||||
@@ -248,16 +249,15 @@ export default class InventoryModuleService
|
|||||||
const toCreate = Array.isArray(input) ? input : [input]
|
const toCreate = Array.isArray(input) ? input : [input]
|
||||||
const created = await this.createReservationItems_(toCreate, context)
|
const created = await this.createReservationItems_(toCreate, context)
|
||||||
|
|
||||||
context.messageAggregator?.saveRawMessageData(
|
moduleEventBuilderFactory({
|
||||||
created.map((reservationItem) => ({
|
|
||||||
eventName: InventoryEvents.RESERVATION_ITEM_CREATED,
|
|
||||||
source: Modules.INVENTORY,
|
|
||||||
action: CommonEvents.CREATED,
|
action: CommonEvents.CREATED,
|
||||||
object: "reservation-item",
|
object: "reservation-item",
|
||||||
context,
|
source: Modules.INVENTORY,
|
||||||
data: { id: reservationItem.id },
|
eventName: InventoryEvents.RESERVATION_ITEM_CREATED,
|
||||||
}))
|
})({
|
||||||
)
|
data: created,
|
||||||
|
sharedContext: context,
|
||||||
|
})
|
||||||
|
|
||||||
const serializedReservations = await this.baseRepository_.serialize<
|
const serializedReservations = await this.baseRepository_.serialize<
|
||||||
InventoryTypes.ReservationItemDTO[] | InventoryTypes.ReservationItemDTO
|
InventoryTypes.ReservationItemDTO[] | InventoryTypes.ReservationItemDTO
|
||||||
@@ -350,16 +350,15 @@ export default class InventoryModuleService
|
|||||||
)
|
)
|
||||||
const result = await this.createInventoryItems_(toCreate, context)
|
const result = await this.createInventoryItems_(toCreate, context)
|
||||||
|
|
||||||
context.messageAggregator?.saveRawMessageData(
|
moduleEventBuilderFactory({
|
||||||
result.map((inventoryItem) => ({
|
|
||||||
eventName: InventoryEvents.INVENTORY_ITEM_CREATED,
|
|
||||||
source: Modules.INVENTORY,
|
|
||||||
action: CommonEvents.CREATED,
|
action: CommonEvents.CREATED,
|
||||||
object: "inventory-item",
|
object: "inventory-item",
|
||||||
context,
|
source: Modules.INVENTORY,
|
||||||
data: { id: inventoryItem.id },
|
eventName: InventoryEvents.INVENTORY_ITEM_CREATED,
|
||||||
}))
|
})({
|
||||||
)
|
data: result,
|
||||||
|
sharedContext: context,
|
||||||
|
})
|
||||||
|
|
||||||
const serializedItems = await this.baseRepository_.serialize<
|
const serializedItems = await this.baseRepository_.serialize<
|
||||||
InventoryTypes.InventoryItemDTO | InventoryTypes.InventoryItemDTO[]
|
InventoryTypes.InventoryItemDTO | InventoryTypes.InventoryItemDTO[]
|
||||||
@@ -406,16 +405,15 @@ export default class InventoryModuleService
|
|||||||
|
|
||||||
const created = await this.createInventoryLevels_(toCreate, context)
|
const created = await this.createInventoryLevels_(toCreate, context)
|
||||||
|
|
||||||
context.messageAggregator?.saveRawMessageData(
|
moduleEventBuilderFactory({
|
||||||
created.map((inventoryLevel) => ({
|
|
||||||
eventName: InventoryEvents.INVENTORY_LEVEL_CREATED,
|
|
||||||
source: Modules.INVENTORY,
|
|
||||||
action: CommonEvents.CREATED,
|
action: CommonEvents.CREATED,
|
||||||
object: "inventory-level",
|
object: "inventory-level",
|
||||||
context,
|
source: Modules.INVENTORY,
|
||||||
data: { id: inventoryLevel.id },
|
eventName: InventoryEvents.INVENTORY_LEVEL_CREATED,
|
||||||
}))
|
})({
|
||||||
)
|
data: created,
|
||||||
|
sharedContext: context,
|
||||||
|
})
|
||||||
|
|
||||||
const serialized = await this.baseRepository_.serialize<
|
const serialized = await this.baseRepository_.serialize<
|
||||||
InventoryTypes.InventoryLevelDTO[] | InventoryTypes.InventoryLevelDTO
|
InventoryTypes.InventoryLevelDTO[] | InventoryTypes.InventoryLevelDTO
|
||||||
@@ -462,16 +460,15 @@ export default class InventoryModuleService
|
|||||||
|
|
||||||
const result = await this.updateInventoryItems_(updates, context)
|
const result = await this.updateInventoryItems_(updates, context)
|
||||||
|
|
||||||
context.messageAggregator?.saveRawMessageData(
|
moduleEventBuilderFactory({
|
||||||
result.map((inventoryItem) => ({
|
|
||||||
eventName: InventoryEvents.INVENTORY_ITEM_UPDATED,
|
|
||||||
source: Modules.INVENTORY,
|
|
||||||
action: CommonEvents.UPDATED,
|
action: CommonEvents.UPDATED,
|
||||||
object: "inventory-item",
|
object: "inventory-item",
|
||||||
context,
|
source: Modules.INVENTORY,
|
||||||
data: { id: inventoryItem.id },
|
eventName: InventoryEvents.INVENTORY_ITEM_UPDATED,
|
||||||
}))
|
})({
|
||||||
)
|
data: result,
|
||||||
|
sharedContext: context,
|
||||||
|
})
|
||||||
|
|
||||||
const serializedItems = await this.baseRepository_.serialize<
|
const serializedItems = await this.baseRepository_.serialize<
|
||||||
InventoryTypes.InventoryItemDTO | InventoryTypes.InventoryItemDTO[]
|
InventoryTypes.InventoryItemDTO | InventoryTypes.InventoryItemDTO[]
|
||||||
@@ -503,16 +500,15 @@ export default class InventoryModuleService
|
|||||||
context
|
context
|
||||||
)
|
)
|
||||||
|
|
||||||
context.messageAggregator?.saveRawMessageData(
|
moduleEventBuilderFactory({
|
||||||
result[0].map((inventoryLevel) => ({
|
|
||||||
eventName: InventoryEvents.INVENTORY_LEVEL_DELETED,
|
|
||||||
source: Modules.INVENTORY,
|
|
||||||
action: CommonEvents.DELETED,
|
action: CommonEvents.DELETED,
|
||||||
object: "inventory-level",
|
object: "inventory-level",
|
||||||
context,
|
source: Modules.INVENTORY,
|
||||||
data: { id: inventoryLevel.id },
|
eventName: InventoryEvents.INVENTORY_LEVEL_DELETED,
|
||||||
}))
|
})({
|
||||||
)
|
data: result[0],
|
||||||
|
sharedContext: context,
|
||||||
|
})
|
||||||
|
|
||||||
return result
|
return result
|
||||||
}
|
}
|
||||||
@@ -524,6 +520,7 @@ export default class InventoryModuleService
|
|||||||
* @param context
|
* @param context
|
||||||
*/
|
*/
|
||||||
@InjectTransactionManager()
|
@InjectTransactionManager()
|
||||||
|
@EmitEvents()
|
||||||
async deleteInventoryLevel(
|
async deleteInventoryLevel(
|
||||||
inventoryItemId: string,
|
inventoryItemId: string,
|
||||||
locationId: string,
|
locationId: string,
|
||||||
@@ -535,13 +532,14 @@ export default class InventoryModuleService
|
|||||||
context
|
context
|
||||||
)
|
)
|
||||||
|
|
||||||
context.messageAggregator?.saveRawMessageData({
|
moduleEventBuilderFactory({
|
||||||
eventName: InventoryEvents.INVENTORY_LEVEL_DELETED,
|
|
||||||
source: Modules.INVENTORY,
|
|
||||||
action: CommonEvents.DELETED,
|
action: CommonEvents.DELETED,
|
||||||
object: "inventory-level",
|
object: "inventory-level",
|
||||||
context,
|
source: Modules.INVENTORY,
|
||||||
|
eventName: InventoryEvents.INVENTORY_LEVEL_DELETED,
|
||||||
|
})({
|
||||||
data: { id: inventoryLevel.id },
|
data: { id: inventoryLevel.id },
|
||||||
|
sharedContext: context,
|
||||||
})
|
})
|
||||||
|
|
||||||
if (!inventoryLevel) {
|
if (!inventoryLevel) {
|
||||||
@@ -579,16 +577,15 @@ export default class InventoryModuleService
|
|||||||
|
|
||||||
const levels = await this.updateInventoryLevels_(input, context)
|
const levels = await this.updateInventoryLevels_(input, context)
|
||||||
|
|
||||||
context.messageAggregator?.saveRawMessageData(
|
moduleEventBuilderFactory({
|
||||||
levels.map((inventoryLevel) => ({
|
|
||||||
eventName: InventoryEvents.INVENTORY_LEVEL_UPDATED,
|
|
||||||
source: Modules.INVENTORY,
|
|
||||||
action: CommonEvents.UPDATED,
|
action: CommonEvents.UPDATED,
|
||||||
object: "inventory-level",
|
object: "inventory-level",
|
||||||
context,
|
source: Modules.INVENTORY,
|
||||||
data: { id: inventoryLevel.id },
|
eventName: InventoryEvents.INVENTORY_LEVEL_UPDATED,
|
||||||
}))
|
})({
|
||||||
)
|
data: levels,
|
||||||
|
sharedContext: context,
|
||||||
|
})
|
||||||
|
|
||||||
const updatedLevels = await this.baseRepository_.serialize<
|
const updatedLevels = await this.baseRepository_.serialize<
|
||||||
InventoryTypes.InventoryLevelDTO | InventoryTypes.InventoryLevelDTO[]
|
InventoryTypes.InventoryLevelDTO | InventoryTypes.InventoryLevelDTO[]
|
||||||
@@ -662,16 +659,15 @@ export default class InventoryModuleService
|
|||||||
const update = Array.isArray(input) ? input : [input]
|
const update = Array.isArray(input) ? input : [input]
|
||||||
const result = await this.updateReservationItems_(update, context)
|
const result = await this.updateReservationItems_(update, context)
|
||||||
|
|
||||||
context.messageAggregator?.saveRawMessageData(
|
moduleEventBuilderFactory({
|
||||||
result.map((reservationItem) => ({
|
|
||||||
eventName: InventoryEvents.RESERVATION_ITEM_UPDATED,
|
|
||||||
source: Modules.INVENTORY,
|
|
||||||
action: CommonEvents.UPDATED,
|
action: CommonEvents.UPDATED,
|
||||||
object: "reservation-item",
|
object: "reservation-item",
|
||||||
context,
|
source: Modules.INVENTORY,
|
||||||
data: { id: reservationItem.id },
|
eventName: InventoryEvents.RESERVATION_ITEM_UPDATED,
|
||||||
}))
|
})({
|
||||||
)
|
data: result,
|
||||||
|
sharedContext: context,
|
||||||
|
})
|
||||||
|
|
||||||
const serialized = await this.baseRepository_.serialize<
|
const serialized = await this.baseRepository_.serialize<
|
||||||
InventoryTypes.ReservationItemDTO | InventoryTypes.ReservationItemDTO[]
|
InventoryTypes.ReservationItemDTO | InventoryTypes.ReservationItemDTO[]
|
||||||
@@ -867,16 +863,15 @@ export default class InventoryModuleService
|
|||||||
context
|
context
|
||||||
)
|
)
|
||||||
|
|
||||||
context.messageAggregator?.saveRawMessageData(
|
moduleEventBuilderFactory({
|
||||||
reservations.map((reservationItem) => ({
|
|
||||||
eventName: InventoryEvents.RESERVATION_ITEM_DELETED,
|
|
||||||
source: Modules.INVENTORY,
|
|
||||||
action: CommonEvents.DELETED,
|
action: CommonEvents.DELETED,
|
||||||
object: "reservation-item",
|
object: "reservation-item",
|
||||||
context,
|
source: Modules.INVENTORY,
|
||||||
data: { id: reservationItem.id },
|
eventName: InventoryEvents.RESERVATION_ITEM_DELETED,
|
||||||
}))
|
})({
|
||||||
)
|
data: reservations,
|
||||||
|
sharedContext: context,
|
||||||
|
})
|
||||||
|
|
||||||
await this.adjustInventoryLevelsForReservationsDeletion(
|
await this.adjustInventoryLevelsForReservationsDeletion(
|
||||||
reservations,
|
reservations,
|
||||||
@@ -909,16 +904,15 @@ export default class InventoryModuleService
|
|||||||
context
|
context
|
||||||
)
|
)
|
||||||
|
|
||||||
context.messageAggregator?.saveRawMessageData(
|
moduleEventBuilderFactory({
|
||||||
reservations.map((reservationItem) => ({
|
|
||||||
eventName: InventoryEvents.RESERVATION_ITEM_DELETED,
|
|
||||||
source: Modules.INVENTORY,
|
|
||||||
action: CommonEvents.DELETED,
|
action: CommonEvents.DELETED,
|
||||||
object: "reservation-item",
|
object: "reservation-item",
|
||||||
context,
|
source: Modules.INVENTORY,
|
||||||
data: { id: reservationItem.id },
|
eventName: InventoryEvents.RESERVATION_ITEM_DELETED,
|
||||||
}))
|
})({
|
||||||
)
|
data: reservations,
|
||||||
|
sharedContext: context,
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -946,16 +940,15 @@ export default class InventoryModuleService
|
|||||||
context
|
context
|
||||||
)
|
)
|
||||||
|
|
||||||
context.messageAggregator?.saveRawMessageData(
|
moduleEventBuilderFactory({
|
||||||
reservations.map((reservationItem) => ({
|
|
||||||
eventName: InventoryEvents.RESERVATION_ITEM_CREATED,
|
|
||||||
source: Modules.INVENTORY,
|
|
||||||
action: CommonEvents.CREATED,
|
action: CommonEvents.CREATED,
|
||||||
object: "reservation-item",
|
object: "reservation-item",
|
||||||
context,
|
source: Modules.INVENTORY,
|
||||||
data: { id: reservationItem.id },
|
eventName: InventoryEvents.RESERVATION_ITEM_CREATED,
|
||||||
}))
|
})({
|
||||||
)
|
data: reservations,
|
||||||
|
sharedContext: context,
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -1016,13 +1009,14 @@ export default class InventoryModuleService
|
|||||||
)
|
)
|
||||||
results.push(result)
|
results.push(result)
|
||||||
|
|
||||||
context.messageAggregator?.saveRawMessageData({
|
moduleEventBuilderFactory({
|
||||||
eventName: InventoryEvents.INVENTORY_LEVEL_UPDATED,
|
|
||||||
source: Modules.INVENTORY,
|
|
||||||
action: CommonEvents.UPDATED,
|
action: CommonEvents.UPDATED,
|
||||||
object: "inventory-level",
|
object: "inventory-level",
|
||||||
context,
|
source: Modules.INVENTORY,
|
||||||
|
eventName: InventoryEvents.INVENTORY_LEVEL_UPDATED,
|
||||||
|
})({
|
||||||
data: { id: result.id },
|
data: { id: result.id },
|
||||||
|
sharedContext: context,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -11,6 +11,7 @@ import {
|
|||||||
} from "@medusajs/framework/types"
|
} from "@medusajs/framework/types"
|
||||||
import {
|
import {
|
||||||
CommonEvents,
|
CommonEvents,
|
||||||
|
EmitEvents,
|
||||||
InjectManager,
|
InjectManager,
|
||||||
InjectTransactionManager,
|
InjectTransactionManager,
|
||||||
isDefined,
|
isDefined,
|
||||||
@@ -18,6 +19,7 @@ import {
|
|||||||
MapToConfig,
|
MapToConfig,
|
||||||
MedusaContext,
|
MedusaContext,
|
||||||
MedusaError,
|
MedusaError,
|
||||||
|
moduleEventBuilderFactory,
|
||||||
Modules,
|
Modules,
|
||||||
ModulesSdkUtils,
|
ModulesSdkUtils,
|
||||||
} from "@medusajs/framework/utils"
|
} from "@medusajs/framework/utils"
|
||||||
@@ -175,6 +177,7 @@ export default class LinkModuleService implements ILinkModule {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@InjectTransactionManager()
|
@InjectTransactionManager()
|
||||||
|
@EmitEvents()
|
||||||
async create(
|
async create(
|
||||||
primaryKeyOrBulkData:
|
primaryKeyOrBulkData:
|
||||||
| string
|
| string
|
||||||
@@ -207,18 +210,15 @@ export default class LinkModuleService implements ILinkModule {
|
|||||||
|
|
||||||
const links = await this.linkService_.create(data, sharedContext)
|
const links = await this.linkService_.create(data, sharedContext)
|
||||||
|
|
||||||
await this.eventBusModuleService_?.emit<Record<string, unknown>>(
|
moduleEventBuilderFactory({
|
||||||
(data as { id: unknown }[]).map(({ id }) => ({
|
|
||||||
name: this.entityName_ + "." + CommonEvents.ATTACHED,
|
|
||||||
metadata: {
|
|
||||||
source: this.serviceName_,
|
|
||||||
action: CommonEvents.ATTACHED,
|
action: CommonEvents.ATTACHED,
|
||||||
object: this.entityName_,
|
object: this.entityName_,
|
||||||
eventGroupId: sharedContext.eventGroupId,
|
source: this.serviceName_,
|
||||||
},
|
eventName: this.entityName_ + "." + CommonEvents.ATTACHED,
|
||||||
data: { id },
|
})({
|
||||||
}))
|
data: data as { id: string }[],
|
||||||
)
|
sharedContext,
|
||||||
|
})
|
||||||
|
|
||||||
return (await this.baseRepository_.serialize(links)) as unknown[]
|
return (await this.baseRepository_.serialize(links)) as unknown[]
|
||||||
}
|
}
|
||||||
@@ -249,6 +249,7 @@ export default class LinkModuleService implements ILinkModule {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@InjectTransactionManager()
|
@InjectTransactionManager()
|
||||||
|
@EmitEvents()
|
||||||
async delete(
|
async delete(
|
||||||
data: any,
|
data: any,
|
||||||
@MedusaContext() sharedContext: Context = {}
|
@MedusaContext() sharedContext: Context = {}
|
||||||
@@ -258,20 +259,19 @@ export default class LinkModuleService implements ILinkModule {
|
|||||||
await this.linkService_.delete(data, sharedContext)
|
await this.linkService_.delete(data, sharedContext)
|
||||||
|
|
||||||
const allData = Array.isArray(data) ? data : [data]
|
const allData = Array.isArray(data) ? data : [data]
|
||||||
await this.eventBusModuleService_?.emit<Record<string, unknown>>(
|
moduleEventBuilderFactory({
|
||||||
allData.map(({ id }) => ({
|
|
||||||
name: this.entityName_ + "." + CommonEvents.DETACHED,
|
|
||||||
metadata: {
|
|
||||||
source: this.serviceName_,
|
|
||||||
action: CommonEvents.DETACHED,
|
action: CommonEvents.DETACHED,
|
||||||
object: this.entityName_,
|
object: this.entityName_,
|
||||||
eventGroupId: sharedContext.eventGroupId,
|
source: this.serviceName_,
|
||||||
},
|
eventName: this.entityName_ + "." + CommonEvents.DETACHED,
|
||||||
data: { id },
|
})({
|
||||||
}))
|
data: allData as { id: string }[],
|
||||||
)
|
sharedContext,
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@InjectTransactionManager()
|
||||||
|
@EmitEvents()
|
||||||
async softDelete(
|
async softDelete(
|
||||||
data: any,
|
data: any,
|
||||||
{ returnLinkableKeys }: SoftDeleteReturn = {},
|
{ returnLinkableKeys }: SoftDeleteReturn = {},
|
||||||
@@ -307,18 +307,15 @@ export default class LinkModuleService implements ILinkModule {
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
await this.eventBusModuleService_?.emit<Record<string, unknown>>(
|
moduleEventBuilderFactory({
|
||||||
(deletedEntities as { id: string }[]).map(({ id }) => ({
|
|
||||||
name: this.entityName_ + "." + CommonEvents.DETACHED,
|
|
||||||
metadata: {
|
|
||||||
source: this.serviceName_,
|
|
||||||
action: CommonEvents.DETACHED,
|
action: CommonEvents.DETACHED,
|
||||||
object: this.entityName_,
|
object: this.entityName_,
|
||||||
eventGroupId: sharedContext.eventGroupId,
|
source: this.serviceName_,
|
||||||
},
|
eventName: this.entityName_ + "." + CommonEvents.DETACHED,
|
||||||
data: { id },
|
})({
|
||||||
}))
|
data: deletedEntities as { id: string }[],
|
||||||
)
|
sharedContext,
|
||||||
|
})
|
||||||
|
|
||||||
return mappedCascadedEntitiesMap ? mappedCascadedEntitiesMap : void 0
|
return mappedCascadedEntitiesMap ? mappedCascadedEntitiesMap : void 0
|
||||||
}
|
}
|
||||||
@@ -331,6 +328,8 @@ export default class LinkModuleService implements ILinkModule {
|
|||||||
return await this.linkService_.softDelete(data, sharedContext)
|
return await this.linkService_.softDelete(data, sharedContext)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@InjectTransactionManager()
|
||||||
|
@EmitEvents()
|
||||||
async restore(
|
async restore(
|
||||||
data: any,
|
data: any,
|
||||||
{ returnLinkableKeys }: RestoreReturn = {},
|
{ returnLinkableKeys }: RestoreReturn = {},
|
||||||
@@ -365,18 +364,15 @@ export default class LinkModuleService implements ILinkModule {
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
await this.eventBusModuleService_?.emit<Record<string, unknown>>(
|
moduleEventBuilderFactory({
|
||||||
(restoredEntities as { id: string }[]).map(({ id }) => ({
|
|
||||||
name: this.entityName_ + "." + CommonEvents.ATTACHED,
|
|
||||||
metadata: {
|
|
||||||
source: this.serviceName_,
|
|
||||||
action: CommonEvents.ATTACHED,
|
action: CommonEvents.ATTACHED,
|
||||||
object: this.entityName_,
|
object: this.entityName_,
|
||||||
eventGroupId: sharedContext.eventGroupId,
|
source: this.serviceName_,
|
||||||
},
|
eventName: this.entityName_ + "." + CommonEvents.ATTACHED,
|
||||||
data: { id },
|
})({
|
||||||
}))
|
data: restoredEntities as { id: string }[],
|
||||||
)
|
sharedContext,
|
||||||
|
})
|
||||||
|
|
||||||
return mappedCascadedEntitiesMap ? mappedCascadedEntitiesMap : void 0
|
return mappedCascadedEntitiesMap ? mappedCascadedEntitiesMap : void 0
|
||||||
}
|
}
|
||||||
@@ -388,4 +384,21 @@ export default class LinkModuleService implements ILinkModule {
|
|||||||
): Promise<[object[], Record<string, string[]>]> {
|
): Promise<[object[], Record<string, string[]>]> {
|
||||||
return await this.linkService_.restore(data, sharedContext)
|
return await this.linkService_.restore(data, sharedContext)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected async emitEvents_(groupedEvents) {
|
||||||
|
if (!this.eventBusModuleService_ || !groupedEvents) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
const promises: Promise<void>[] = []
|
||||||
|
for (const group of Object.keys(groupedEvents)) {
|
||||||
|
promises.push(
|
||||||
|
this.eventBusModuleService_.emit(groupedEvents[group], {
|
||||||
|
internal: true,
|
||||||
|
})
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
await Promise.all(promises)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
+7
-10
@@ -461,7 +461,7 @@ moduleIntegrationTestRunner<IPricingModuleService>({
|
|||||||
)
|
)
|
||||||
|
|
||||||
const events = eventBusEmitSpy.mock.calls[0][0]
|
const events = eventBusEmitSpy.mock.calls[0][0]
|
||||||
expect(events).toHaveLength(4)
|
expect(events).toHaveLength(3)
|
||||||
expect(events[0]).toEqual(
|
expect(events[0]).toEqual(
|
||||||
composeMessage(PricingEvents.PRICE_LIST_CREATED, {
|
composeMessage(PricingEvents.PRICE_LIST_CREATED, {
|
||||||
source: Modules.PRICING,
|
source: Modules.PRICING,
|
||||||
@@ -475,18 +475,15 @@ moduleIntegrationTestRunner<IPricingModuleService>({
|
|||||||
source: Modules.PRICING,
|
source: Modules.PRICING,
|
||||||
action: CommonEvents.CREATED,
|
action: CommonEvents.CREATED,
|
||||||
object: "price_list_rule",
|
object: "price_list_rule",
|
||||||
data: { id: priceList.price_list_rules?.[0].id },
|
data: {
|
||||||
|
id: [
|
||||||
|
priceList.price_list_rules?.[0].id,
|
||||||
|
priceList.price_list_rules?.[1].id,
|
||||||
|
],
|
||||||
|
},
|
||||||
})
|
})
|
||||||
)
|
)
|
||||||
expect(events[2]).toEqual(
|
expect(events[2]).toEqual(
|
||||||
composeMessage(PricingEvents.PRICE_LIST_RULE_CREATED, {
|
|
||||||
source: Modules.PRICING,
|
|
||||||
action: CommonEvents.CREATED,
|
|
||||||
object: "price_list_rule",
|
|
||||||
data: { id: priceList.price_list_rules?.[1].id },
|
|
||||||
})
|
|
||||||
)
|
|
||||||
expect(events[3]).toEqual(
|
|
||||||
composeMessage(PricingEvents.PRICE_CREATED, {
|
composeMessage(PricingEvents.PRICE_CREATED, {
|
||||||
source: Modules.PRICING,
|
source: Modules.PRICING,
|
||||||
action: CommonEvents.CREATED,
|
action: CommonEvents.CREATED,
|
||||||
|
|||||||
@@ -1003,12 +1003,12 @@ export default class PricingModuleService
|
|||||||
})
|
})
|
||||||
|
|
||||||
// Bulk create price sets
|
// Bulk create price sets
|
||||||
const createdPriceSets = await this.priceSetService_.create(
|
const priceSets = await this.priceSetService_.create(
|
||||||
toCreate,
|
toCreate,
|
||||||
sharedContext
|
sharedContext
|
||||||
)
|
)
|
||||||
|
|
||||||
const eventsData = createdPriceSets.reduce(
|
const eventsData = priceSets.reduce(
|
||||||
(eventsData, priceSet) => {
|
(eventsData, priceSet) => {
|
||||||
eventsData.priceSets.push({
|
eventsData.priceSets.push({
|
||||||
id: priceSet.id,
|
id: priceSet.id,
|
||||||
@@ -1051,7 +1051,7 @@ export default class PricingModuleService
|
|||||||
sharedContext,
|
sharedContext,
|
||||||
})
|
})
|
||||||
|
|
||||||
return createdPriceSets
|
return priceSets
|
||||||
}
|
}
|
||||||
|
|
||||||
@InjectTransactionManager()
|
@InjectTransactionManager()
|
||||||
|
|||||||
@@ -255,19 +255,11 @@ moduleIntegrationTestRunner<IUserModuleService>({
|
|||||||
expect(eventBusSpy).toHaveBeenCalledWith(
|
expect(eventBusSpy).toHaveBeenCalledWith(
|
||||||
[
|
[
|
||||||
expect.objectContaining({
|
expect.objectContaining({
|
||||||
data: { id: "1" },
|
data: { id: ["1", "2"] },
|
||||||
name: UserEvents.INVITE_CREATED,
|
name: UserEvents.INVITE_CREATED,
|
||||||
}),
|
}),
|
||||||
expect.objectContaining({
|
expect.objectContaining({
|
||||||
data: { id: "2" },
|
data: { id: ["1", "2"] },
|
||||||
name: UserEvents.INVITE_CREATED,
|
|
||||||
}),
|
|
||||||
expect.objectContaining({
|
|
||||||
data: { id: "1" },
|
|
||||||
name: UserEvents.INVITE_TOKEN_GENERATED,
|
|
||||||
}),
|
|
||||||
expect.objectContaining({
|
|
||||||
data: { id: "2" },
|
|
||||||
name: UserEvents.INVITE_TOKEN_GENERATED,
|
name: UserEvents.INVITE_TOKEN_GENERATED,
|
||||||
}),
|
}),
|
||||||
],
|
],
|
||||||
|
|||||||
@@ -257,11 +257,7 @@ moduleIntegrationTestRunner<IUserModuleService>({
|
|||||||
expect(eventBusSpy).toHaveBeenCalledWith(
|
expect(eventBusSpy).toHaveBeenCalledWith(
|
||||||
[
|
[
|
||||||
expect.objectContaining({
|
expect.objectContaining({
|
||||||
data: { id: "1" },
|
data: { id: ["1", "2"] },
|
||||||
name: UserEvents.USER_CREATED,
|
|
||||||
}),
|
|
||||||
expect.objectContaining({
|
|
||||||
data: { id: "2" },
|
|
||||||
name: UserEvents.USER_CREATED,
|
name: UserEvents.USER_CREATED,
|
||||||
}),
|
}),
|
||||||
],
|
],
|
||||||
|
|||||||
@@ -16,6 +16,8 @@ import {
|
|||||||
MedusaContext,
|
MedusaContext,
|
||||||
MedusaError,
|
MedusaError,
|
||||||
MedusaService,
|
MedusaService,
|
||||||
|
moduleEventBuilderFactory,
|
||||||
|
Modules,
|
||||||
UserEvents,
|
UserEvents,
|
||||||
} from "@medusajs/framework/utils"
|
} from "@medusajs/framework/utils"
|
||||||
import jwt, { JwtPayload } from "jsonwebtoken"
|
import jwt, { JwtPayload } from "jsonwebtoken"
|
||||||
@@ -110,16 +112,15 @@ export default class UserModuleService
|
|||||||
): Promise<UserTypes.InviteDTO[]> {
|
): Promise<UserTypes.InviteDTO[]> {
|
||||||
const invites = await this.refreshInviteTokens_(inviteIds, sharedContext)
|
const invites = await this.refreshInviteTokens_(inviteIds, sharedContext)
|
||||||
|
|
||||||
sharedContext.messageAggregator?.saveRawMessageData(
|
moduleEventBuilderFactory({
|
||||||
invites.map((invite) => ({
|
|
||||||
eventName: UserEvents.INVITE_TOKEN_GENERATED,
|
eventName: UserEvents.INVITE_TOKEN_GENERATED,
|
||||||
source: this.constructor.name,
|
source: Modules.USER,
|
||||||
action: "token_generated",
|
action: "token_generated",
|
||||||
object: "invite",
|
object: "invite",
|
||||||
context: sharedContext,
|
})({
|
||||||
data: { id: invite.id },
|
data: invites,
|
||||||
}))
|
sharedContext,
|
||||||
)
|
})
|
||||||
|
|
||||||
return await this.baseRepository_.serialize<UserTypes.InviteDTO[]>(
|
return await this.baseRepository_.serialize<UserTypes.InviteDTO[]>(
|
||||||
invites,
|
invites,
|
||||||
@@ -193,16 +194,15 @@ export default class UserModuleService
|
|||||||
populate: true,
|
populate: true,
|
||||||
})
|
})
|
||||||
|
|
||||||
sharedContext.messageAggregator?.saveRawMessageData(
|
moduleEventBuilderFactory({
|
||||||
users.map((user) => ({
|
|
||||||
eventName: UserEvents.USER_CREATED,
|
eventName: UserEvents.USER_CREATED,
|
||||||
source: this.constructor.name,
|
source: Modules.USER,
|
||||||
action: CommonEvents.CREATED,
|
action: CommonEvents.CREATED,
|
||||||
object: "user",
|
object: "user",
|
||||||
context: sharedContext,
|
})({
|
||||||
data: { id: user.id },
|
data: serializedUsers,
|
||||||
}))
|
sharedContext,
|
||||||
)
|
})
|
||||||
|
|
||||||
return Array.isArray(data) ? serializedUsers : serializedUsers[0]
|
return Array.isArray(data) ? serializedUsers : serializedUsers[0]
|
||||||
}
|
}
|
||||||
@@ -235,16 +235,15 @@ export default class UserModuleService
|
|||||||
populate: true,
|
populate: true,
|
||||||
})
|
})
|
||||||
|
|
||||||
sharedContext.messageAggregator?.saveRawMessageData(
|
moduleEventBuilderFactory({
|
||||||
updatedUsers.map((user) => ({
|
|
||||||
eventName: UserEvents.USER_UPDATED,
|
eventName: UserEvents.USER_UPDATED,
|
||||||
source: this.constructor.name,
|
source: Modules.USER,
|
||||||
action: CommonEvents.UPDATED,
|
action: CommonEvents.UPDATED,
|
||||||
object: "user",
|
object: "user",
|
||||||
context: sharedContext,
|
})({
|
||||||
data: { id: user.id },
|
data: serializedUsers,
|
||||||
}))
|
sharedContext,
|
||||||
)
|
})
|
||||||
|
|
||||||
return Array.isArray(data) ? serializedUsers : serializedUsers[0]
|
return Array.isArray(data) ? serializedUsers : serializedUsers[0]
|
||||||
}
|
}
|
||||||
@@ -277,27 +276,25 @@ export default class UserModuleService
|
|||||||
populate: true,
|
populate: true,
|
||||||
})
|
})
|
||||||
|
|
||||||
sharedContext.messageAggregator?.saveRawMessageData(
|
moduleEventBuilderFactory({
|
||||||
invites.map((invite) => ({
|
|
||||||
eventName: UserEvents.INVITE_CREATED,
|
eventName: UserEvents.INVITE_CREATED,
|
||||||
source: this.constructor.name,
|
source: Modules.USER,
|
||||||
action: CommonEvents.CREATED,
|
action: CommonEvents.CREATED,
|
||||||
object: "invite",
|
object: "invite",
|
||||||
context: sharedContext,
|
})({
|
||||||
data: { id: invite.id },
|
data: serializedInvites,
|
||||||
}))
|
sharedContext,
|
||||||
)
|
})
|
||||||
|
|
||||||
sharedContext.messageAggregator?.saveRawMessageData(
|
moduleEventBuilderFactory({
|
||||||
invites.map((invite) => ({
|
|
||||||
eventName: UserEvents.INVITE_TOKEN_GENERATED,
|
eventName: UserEvents.INVITE_TOKEN_GENERATED,
|
||||||
source: this.constructor.name,
|
source: Modules.USER,
|
||||||
action: "token_generated",
|
action: "token_generated",
|
||||||
object: "invite",
|
object: "invite",
|
||||||
context: sharedContext,
|
})({
|
||||||
data: { id: invite.id },
|
data: serializedInvites,
|
||||||
}))
|
sharedContext,
|
||||||
)
|
})
|
||||||
|
|
||||||
return Array.isArray(data) ? serializedInvites : serializedInvites[0]
|
return Array.isArray(data) ? serializedInvites : serializedInvites[0]
|
||||||
}
|
}
|
||||||
@@ -364,16 +361,15 @@ export default class UserModuleService
|
|||||||
populate: true,
|
populate: true,
|
||||||
})
|
})
|
||||||
|
|
||||||
sharedContext.messageAggregator?.saveRawMessageData(
|
moduleEventBuilderFactory({
|
||||||
serializedInvites.map((invite) => ({
|
|
||||||
eventName: UserEvents.INVITE_UPDATED,
|
eventName: UserEvents.INVITE_UPDATED,
|
||||||
source: this.constructor.name,
|
source: Modules.USER,
|
||||||
action: CommonEvents.UPDATED,
|
action: CommonEvents.UPDATED,
|
||||||
object: "invite",
|
object: "invite",
|
||||||
context: sharedContext,
|
})({
|
||||||
data: { id: invite.id },
|
data: serializedInvites,
|
||||||
}))
|
sharedContext,
|
||||||
)
|
})
|
||||||
|
|
||||||
return Array.isArray(data) ? serializedInvites : serializedInvites[0]
|
return Array.isArray(data) ? serializedInvites : serializedInvites[0]
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in new issue
Block a user