- Get Started
- Product
- Resources
- Tools & SDKs
- Framework
- Reference
- Get Started
- Product
- Resources
- Tools & SDKs
- Framework
- Reference
How to Create an Event Module
In this guide, you’ll learn how to create an Event Module.
1. Create Module Directory#
Start by creating a new directory for your module. For example, src/modules/my-event
.
2. Create the Event Service#
Create the file src/modules/my-event/service.ts
that holds the implementation of the event service.
The Event Module's main service must extend the AbstractEventBusModuleService
class imported from @medusajs/framework/utils
:
1import { AbstractEventBusModuleService } from "@medusajs/framework/utils"2import { Message } from "@medusajs/types"3 4class MyEventService extends AbstractEventBusModuleService {5 async emit<T>(data: Message<T> | Message<T>[], options: Record<string, unknown>): Promise<void> {6 throw new Error("Method not implemented.")7 }8 async releaseGroupedEvents(eventGroupId: string): Promise<void> {9 throw new Error("Method not implemented.")10 }11 async clearGroupedEvents(eventGroupId: string): Promise<void> {12 throw new Error("Method not implemented.")13 }14}15 16export default MyEventService
The service implements the required methods based on the desired publish/subscribe logic.
eventToSubscribersMap_ Property#
The AbstractEventBusModuleService
has a field eventToSubscribersMap_
, which is a JavaScript Map. The map's keys are the event names, whereas the value of each key is an array of subscribed handler functions.
In your custom implementation, you can use this property to manage the subscribed handler functions:
emit Method#
The emit
method is used to push an event from the Medusa application into your messaging system. The subscribers to that event would then pick up the message and execute their asynchronous tasks.
An example implementation:
1class MyEventService extends AbstractEventBusModuleService {2 async emit<T>(data: Message<T> | Message<T>[], options: Record<string, unknown>): Promise<void> {3 const events = Array.isArray(data) ? data : [data]4 5 for (const event of events) {6 console.log(`Received the event ${event.name} with data ${event.data}`)7 8 // TODO push the event somewhere9 }10 }11 // ...12}
The emit
method receives the following parameters:
data
object or array of objectsThe emitted event(s).
data
object or array of objectsreleaseGroupedEvents Method#
Grouped events are useful when you have distributed transactions where you need to explicitly group, release, and clear events upon lifecycle transaction events.
If your Event Module supports grouped events, this method is used to emit all events in a group, then clear that group.
For example:
1class MyEventService extends AbstractEventBusModuleService {2 protected groupedEventsMap_: Map<string, Message[]>3 4 constructor() {5 // @ts-ignore6 super(...arguments)7 8 this.groupedEventsMap_ = new Map()9 }10 11 async releaseGroupedEvents(eventGroupId: string): Promise<void> {12 const groupedEvents = this.groupedEventsMap_.get(eventGroupId) || []13 14 for (const event of groupedEvents) {15 const { options, ...eventBody } = event16 17 // TODO emit event18 }19 20 await this.clearGroupedEvents(eventGroupId)21 }22 23 // ...24}
The releaseGroupedEvents
receives the group ID as a parameter.
In the example above, you add a groupedEventsMap_
property to store grouped events. Then, in the method, you emit the events in the group, then clear the grouped events using the clearGroupedEvents
which you'll learn about next.
To add events to the grouped events map, you can do it in the emit
method:
1class MyEventService extends AbstractEventBusModuleService {2 // ...3 async emit<T>(data: Message<T> | Message<T>[], options: Record<string, unknown>): Promise<void> {4 const events = Array.isArray(data) ? data : [data]5 6 for (const event of events) {7 console.log(`Received the event ${event.name} with data ${event.data}`)8 9 if (event.metadata.eventGroupId) {10 const groupedEvents = this.groupedEventsMap_.get(11 event.metadata.eventGroupId12 ) || []13 14 groupedEvents.push(event)15 16 this.groupedEventsMap_.set(event.metadata.eventGroupId, groupedEvents)17 continue18 }19 20 // TODO push the event somewhere21 }22 }23}
clearGroupedEvents Method#
If your Event Module supports grouped events, this method is used to remove the events of a group.
For example:
The method accepts the group's name as a parameter.
In the method, you delete the group from the groupedEventsMap_
property (added in the previous section), deleting the stored events of it as well.
3. Create Module Definition File#
Create the file src/modules/my-event/index.ts
with the following content:
This exports the module's definition, indicating that the MyEventService
is the main service of the module.
4. Use Module#
To use your Event Module, add it to the modules
object exported as part of the configurations in medusa-config.ts
. An Event Module is added under the eventBus
key.
For example: