feat(core, event-bus): Compensate emit event step utility (#13281)
* feat(core, event-bus): Compensate emit event step utility * tests * Update changeset to remove integration-tests-modules Removed integration-tests-modules from changeset. * revert test script
This commit is contained in:
@@ -0,0 +1,141 @@
|
||||
import {
|
||||
CommonEvents,
|
||||
composeMessage,
|
||||
Modules,
|
||||
} from "@medusajs/framework/utils"
|
||||
import { moduleIntegrationTestRunner } from "@medusajs/test-utils"
|
||||
import { IEventBusModuleService } from "@medusajs/types"
|
||||
|
||||
moduleIntegrationTestRunner<IEventBusModuleService>({
|
||||
moduleName: Modules.EVENT_BUS,
|
||||
testSuite: ({ service: eventBus }) => {
|
||||
describe("Event Bus Local Service", () => {
|
||||
it("should emit an event", async () => {
|
||||
const subscriber = jest.fn()
|
||||
eventBus.subscribe("test", subscriber)
|
||||
|
||||
await eventBus.emit(
|
||||
composeMessage("test", {
|
||||
data: {
|
||||
test: "test",
|
||||
},
|
||||
action: CommonEvents.CREATED,
|
||||
source: "test",
|
||||
object: "test",
|
||||
})
|
||||
)
|
||||
|
||||
expect(subscriber).toHaveBeenCalledWith({
|
||||
data: {
|
||||
test: "test",
|
||||
},
|
||||
metadata: {
|
||||
source: "test",
|
||||
object: "test",
|
||||
action: "created",
|
||||
},
|
||||
name: "test",
|
||||
})
|
||||
|
||||
eventBus.unsubscribe("test", subscriber)
|
||||
})
|
||||
|
||||
it("should release grouped events", async () => {
|
||||
const subscriber = jest.fn()
|
||||
eventBus.subscribe("test", subscriber)
|
||||
|
||||
await eventBus.emit(
|
||||
composeMessage("test", {
|
||||
data: {
|
||||
test: "test",
|
||||
},
|
||||
context: {
|
||||
eventGroupId: "123",
|
||||
},
|
||||
action: CommonEvents.CREATED,
|
||||
source: "test",
|
||||
object: "test",
|
||||
})
|
||||
)
|
||||
|
||||
expect(subscriber).toHaveBeenCalledTimes(0)
|
||||
|
||||
await eventBus.releaseGroupedEvents("123")
|
||||
|
||||
expect(subscriber).toHaveBeenCalledTimes(1)
|
||||
|
||||
expect(subscriber).toHaveBeenCalledWith({
|
||||
data: {
|
||||
test: "test",
|
||||
},
|
||||
metadata: {
|
||||
source: "test",
|
||||
eventGroupId: "123",
|
||||
object: "test",
|
||||
action: "created",
|
||||
},
|
||||
name: "test",
|
||||
})
|
||||
|
||||
eventBus.unsubscribe("test", subscriber)
|
||||
})
|
||||
|
||||
it("should clear grouped events", async () => {
|
||||
const subscriber = jest.fn()
|
||||
eventBus.subscribe("test", subscriber)
|
||||
|
||||
await eventBus.emit(
|
||||
composeMessage("test", {
|
||||
data: {
|
||||
test: "test",
|
||||
},
|
||||
context: {
|
||||
eventGroupId: "123",
|
||||
},
|
||||
action: CommonEvents.CREATED,
|
||||
source: "test",
|
||||
object: "test",
|
||||
})
|
||||
)
|
||||
|
||||
expect(subscriber).toHaveBeenCalledTimes(0)
|
||||
|
||||
await eventBus.clearGroupedEvents("123")
|
||||
await eventBus.releaseGroupedEvents("123")
|
||||
|
||||
expect(subscriber).toHaveBeenCalledTimes(0)
|
||||
|
||||
eventBus.unsubscribe("test", subscriber)
|
||||
})
|
||||
|
||||
it("should clear grouped events with event names", async () => {
|
||||
const subscriber = jest.fn()
|
||||
eventBus.subscribe("test", subscriber)
|
||||
|
||||
await eventBus.emit(
|
||||
composeMessage("test", {
|
||||
data: {
|
||||
test: "test",
|
||||
},
|
||||
context: {
|
||||
eventGroupId: "123",
|
||||
},
|
||||
action: CommonEvents.CREATED,
|
||||
source: "test",
|
||||
object: "test",
|
||||
})
|
||||
)
|
||||
|
||||
await eventBus.clearGroupedEvents("123", {
|
||||
eventNames: ["test"],
|
||||
})
|
||||
|
||||
await eventBus.releaseGroupedEvents("123")
|
||||
|
||||
expect(subscriber).toHaveBeenCalledTimes(0)
|
||||
|
||||
eventBus.unsubscribe("test", subscriber)
|
||||
})
|
||||
})
|
||||
},
|
||||
})
|
||||
@@ -33,7 +33,8 @@
|
||||
"scripts": {
|
||||
"watch": "tsc --build --watch",
|
||||
"build": "rimraf dist && tsc --build",
|
||||
"test": "jest --passWithNoTests"
|
||||
"test": "jest --passWithNoTests",
|
||||
"test:integration": "jest --no-cache --maxWorkers=50% --bail --detectOpenHandles --forceExit --logHeapUsage -- integration-tests/__tests__/**/*.spec.ts"
|
||||
},
|
||||
"dependencies": {
|
||||
"ulid": "^2.3.0"
|
||||
|
||||
@@ -130,8 +130,19 @@ export default class LocalEventBusService extends AbstractEventBusModuleService
|
||||
await this.clearGroupedEvents(eventGroupId)
|
||||
}
|
||||
|
||||
async clearGroupedEvents(eventGroupId: string) {
|
||||
this.groupedEventsMap_.delete(eventGroupId)
|
||||
async clearGroupedEvents(
|
||||
eventGroupId: string,
|
||||
{ eventNames }: { eventNames?: string[] } = {}
|
||||
) {
|
||||
if (eventNames?.length) {
|
||||
const groupedEvents = this.groupedEventsMap_.get(eventGroupId) || []
|
||||
const eventsToKeep = groupedEvents.filter(
|
||||
(event) => !eventNames!.includes(event.name)
|
||||
)
|
||||
this.groupedEventsMap_.set(eventGroupId, eventsToKeep)
|
||||
} else {
|
||||
this.groupedEventsMap_.delete(eventGroupId)
|
||||
}
|
||||
}
|
||||
|
||||
subscribe(
|
||||
|
||||
@@ -0,0 +1,147 @@
|
||||
import {
|
||||
CommonEvents,
|
||||
composeMessage,
|
||||
Modules,
|
||||
} from "@medusajs/framework/utils"
|
||||
import { moduleIntegrationTestRunner } from "@medusajs/test-utils"
|
||||
import { IEventBusModuleService } from "@medusajs/types"
|
||||
|
||||
moduleIntegrationTestRunner<IEventBusModuleService>({
|
||||
moduleName: Modules.EVENT_BUS,
|
||||
moduleOptions: {
|
||||
redis: {
|
||||
host: "localhost",
|
||||
port: 6379,
|
||||
},
|
||||
},
|
||||
testSuite: ({ service: eventBus }) => {
|
||||
describe("Event Bus Redis Service", () => {
|
||||
it("should emit an event", async () => {
|
||||
const subscriber = jest.fn()
|
||||
eventBus.subscribe("test", subscriber)
|
||||
|
||||
await eventBus.emit(
|
||||
composeMessage("test", {
|
||||
data: {
|
||||
test: "test",
|
||||
},
|
||||
action: CommonEvents.CREATED,
|
||||
source: "test",
|
||||
object: "test",
|
||||
})
|
||||
)
|
||||
|
||||
expect(subscriber).toHaveBeenCalledWith({
|
||||
data: {
|
||||
test: "test",
|
||||
},
|
||||
metadata: {
|
||||
source: "test",
|
||||
object: "test",
|
||||
action: "created",
|
||||
},
|
||||
name: "test",
|
||||
})
|
||||
|
||||
eventBus.unsubscribe("test", subscriber)
|
||||
})
|
||||
|
||||
it("should release grouped events", async () => {
|
||||
const subscriber = jest.fn()
|
||||
eventBus.subscribe("test", subscriber)
|
||||
|
||||
await eventBus.emit(
|
||||
composeMessage("test", {
|
||||
data: {
|
||||
test: "test",
|
||||
},
|
||||
context: {
|
||||
eventGroupId: "123",
|
||||
},
|
||||
action: CommonEvents.CREATED,
|
||||
source: "test",
|
||||
object: "test",
|
||||
})
|
||||
)
|
||||
|
||||
expect(subscriber).toHaveBeenCalledTimes(0)
|
||||
|
||||
await eventBus.releaseGroupedEvents("123")
|
||||
|
||||
expect(subscriber).toHaveBeenCalledTimes(1)
|
||||
|
||||
expect(subscriber).toHaveBeenCalledWith({
|
||||
data: {
|
||||
test: "test",
|
||||
},
|
||||
metadata: {
|
||||
source: "test",
|
||||
eventGroupId: "123",
|
||||
object: "test",
|
||||
action: "created",
|
||||
},
|
||||
name: "test",
|
||||
})
|
||||
|
||||
eventBus.unsubscribe("test", subscriber)
|
||||
})
|
||||
|
||||
it("should clear grouped events", async () => {
|
||||
const subscriber = jest.fn()
|
||||
eventBus.subscribe("test", subscriber)
|
||||
|
||||
await eventBus.emit(
|
||||
composeMessage("test", {
|
||||
data: {
|
||||
test: "test",
|
||||
},
|
||||
context: {
|
||||
eventGroupId: "123",
|
||||
},
|
||||
action: CommonEvents.CREATED,
|
||||
source: "test",
|
||||
object: "test",
|
||||
})
|
||||
)
|
||||
|
||||
expect(subscriber).toHaveBeenCalledTimes(0)
|
||||
|
||||
await eventBus.clearGroupedEvents("123")
|
||||
await eventBus.releaseGroupedEvents("123")
|
||||
|
||||
expect(subscriber).toHaveBeenCalledTimes(0)
|
||||
|
||||
eventBus.unsubscribe("test", subscriber)
|
||||
})
|
||||
|
||||
it("should clear grouped events with event names", async () => {
|
||||
const subscriber = jest.fn()
|
||||
eventBus.subscribe("test", subscriber)
|
||||
|
||||
await eventBus.emit(
|
||||
composeMessage("test", {
|
||||
data: {
|
||||
test: "test",
|
||||
},
|
||||
context: {
|
||||
eventGroupId: "123",
|
||||
},
|
||||
action: CommonEvents.CREATED,
|
||||
source: "test",
|
||||
object: "test",
|
||||
})
|
||||
)
|
||||
|
||||
await eventBus.clearGroupedEvents("123", {
|
||||
eventNames: ["test"],
|
||||
})
|
||||
|
||||
await eventBus.releaseGroupedEvents("123")
|
||||
|
||||
expect(subscriber).toHaveBeenCalledTimes(0)
|
||||
|
||||
eventBus.unsubscribe("test", subscriber)
|
||||
})
|
||||
})
|
||||
},
|
||||
})
|
||||
@@ -33,7 +33,8 @@
|
||||
"scripts": {
|
||||
"watch": "tsc --build --watch",
|
||||
"build": "rimraf dist && tsc --build",
|
||||
"test": "jest --silent --bail --maxWorkers=50% --forceExit"
|
||||
"test": "jest --silent --bail --maxWorkers=50% --forceExit",
|
||||
"test:integration": "jest --no-cache --maxWorkers=50% --bail --detectOpenHandles --forceExit --logHeapUsage -- integration-tests/__tests__/**/*.spec.ts"
|
||||
},
|
||||
"dependencies": {
|
||||
"bullmq": "5.13.0",
|
||||
|
||||
@@ -218,11 +218,49 @@ export default class RedisEventBusService extends AbstractEventBusModuleService
|
||||
await this.clearGroupedEvents(eventGroupId)
|
||||
}
|
||||
|
||||
async clearGroupedEvents(eventGroupId: string) {
|
||||
async clearGroupedEvents(
|
||||
eventGroupId: string,
|
||||
{
|
||||
eventNames,
|
||||
}: {
|
||||
eventNames?: string[]
|
||||
} = {}
|
||||
) {
|
||||
if (!eventGroupId) {
|
||||
return
|
||||
}
|
||||
|
||||
if (eventNames?.length) {
|
||||
/**
|
||||
* If any event names are provided, we keep all events except the ones that match the event
|
||||
* names. which allow to partially clear an event group.
|
||||
*/
|
||||
|
||||
const eventsToKeep = await this.eventBusRedisConnection_
|
||||
.lrange(`staging:${eventGroupId}`, 0, -1)
|
||||
.then((result) => {
|
||||
return result
|
||||
.map((jsonString) => JSON.parse(jsonString))
|
||||
.filter((event) => !eventNames.includes(event.name))
|
||||
})
|
||||
|
||||
// Create a pipeline
|
||||
const pipeline = this.eventBusRedisConnection_.pipeline()
|
||||
|
||||
// Empty the current list
|
||||
pipeline.del(`staging:${eventGroupId}`)
|
||||
|
||||
// Add the remaining events to the list
|
||||
pipeline.rpush(
|
||||
`staging:${eventGroupId}`,
|
||||
...eventsToKeep.map((event) => JSON.stringify(event))
|
||||
)
|
||||
|
||||
await pipeline.exec()
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
await this.eventBusRedisConnection_.unlink(`staging:${eventGroupId}`)
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user