www/apps/book/app/learn/fundamentals/events-and-subscribers/emit-event/page.mdx
import { CodeTabs, CodeTab } from "docs-ui"
export const metadata = {
title: ${pageNumber} Emit Workflow and Service Events,
}
In this chapter, you'll learn about event types and how to emit an event in a service or workflow.
In your customization, you can emit an event, then listen to it in a subscriber and perform an asynchronus action, such as send a notification or data to a third-party system.
There are two types of events in Medusa:
order.placed event after a cart is completed.Workflow events are the most common event type in development, as most custom features and customizations are built around workflows.
Some examples of workflow events:
You should only go for a service event if you're emitting an event for processes under the hood that don't directly affect front-facing features.
Some examples of service events:
To emit a workflow event, use the emitEventStep helper step provided in the @medusajs/medusa/core-flows package. It allows you to emit an event from within a workflow, and it only emits the event after the workflow has finished successfully.
For example:
export const highlights = [
["13", "emitEventStep", "Emit an event."],
["14", eventName, "The name of the event to emit."],
["15", "data", "The data payload to pass with the event."]
]
import {
createWorkflow,
} from "@medusajs/framework/workflows-sdk"
import {
emitEventStep,
} from "@medusajs/medusa/core-flows"
const helloWorldWorkflow = createWorkflow(
"hello-world",
() => {
// ...
emitEventStep({
eventName: "custom.created",
data: {
id: "123",
// other data payload
},
})
}
)
The emitEventStep accepts an object having the following properties:
eventName: The event's name.data: The data payload as an object. You can pass any properties in the object, and subscribers listening to the event will receive this data in the event's payload.In this example, you emit the event custom.created and pass in the data payload an ID property.
If you execute the workflow, the event is emitted and you can see it in your application's logs.
Any subscribers listening to the event are executed.
You can also emit the event multiple times with emitEventStep by passing an array of objects to the data property. The event is emitted once per each object in the array.
For example:
import {
createWorkflow,
} from "@medusajs/framework/workflows-sdk"
import {
emitEventStep,
} from "@medusajs/medusa/core-flows"
const helloWorldWorkflow = createWorkflow(
"hello-world",
() => {
// ...
emitEventStep({
eventName: "custom.created",
data: [
{ id: "123" },
{ id: "456" },
{ id: "789" },
],
})
}
)
The event custom.created will be emitted three times, once per each object in the array passed to the data property. The subscriber listening to the event will be executed three times, each time receiving one of the objects in the array as the event's payload.
Event priority is available since Medusa v2.13.0.
</Note>You can specify a priority level when emitting events to control when the event is processed relative to other events in the queue. This is useful to ensure that critical business events are handled promptly, while less important events can be deferred.
To emit an event with custom priority, pass the priority property in the options parameter:
export const priorityHighlights = [ ["14", "priority", "Set the event priority to critical."] ]
import {
createWorkflow,
} from "@medusajs/framework/workflows-sdk"
import { emitEventStep } from "@medusajs/medusa/core-flows"
import { EventPriority } from "@medusajs/framework/utils"
const criticalWorkflow = createWorkflow(
"critical-operation",
() => {
emitEventStep({
eventName: "payment.processed",
data: { id: "123" },
options: {
priority: EventPriority.CRITICAL,
},
})
}
)
In the above example, the payment.processed event is emitted with the CRITICAL priority level, ensuring it is processed before other lower-priority events.
Learn more in the Event Processing Priority guide.
To emit a service event:
event_bus from the module's container in your service's constructor:import { IEventBusService } from "@medusajs/framework/types"
import { MedusaService } from "@medusajs/framework/utils"
class BlogModuleService extends MedusaService({
Post,
}){
protected eventBusService_: AbstractEventBusModuleService
constructor({ event_bus }) {
super(...arguments)
this.eventBusService_ = event_bus
}
}
import { IEventBusService } from "@medusajs/framework/types"
class BlogModuleService {
protected eventBusService_: AbstractEventBusModuleService
constructor({ event_bus }) {
this.eventBusService_ = event_bus
}
}
emit method in the service's methods to emit an event:export const serviceHighlights = [ ["6", "emit", "Emit an event."], ["7", "name", "The name of the event to emit."], ["8", "data", "The data payload to pass with the event."] ]
class BlogModuleService {
// ...
performAction() {
// TODO perform action
this.eventBusService_.emit({
name: "custom.event",
data: {
id: "123",
// other data payload
},
})
}
}
The method accepts an object having the following properties:
name: The event's name.data: The data payload as an object. You can pass any properties in the object, and subscribers listening to the event will receive this data in the event's payload.medusa-config.ts in the dependencies property:export const depsHighlight = [ ["8", "dependencies", "An array of module registration names to inject into the Module's container."], ]
import { Modules } from "@medusajs/framework/utils"
module.exports = defineConfig({
// ...
modules: [
{
resolve: "./src/modules/blog",
dependencies: [
Modules.EVENT_BUS,
],
},
],
})
export const providerHighlights = [ ["8", "dependencies", "An array of module registration names to inject into the module and provider's container."], ]
import { Modules } from "@medusajs/framework/utils"
module.exports = defineConfig({
// ...
modules: [
{
resolve: "@medusajs/medusa/payment",
dependencies: [
Modules.EVENT_BUS,
],
options: {
providers: [
{
resolve: "./src/modules/my-provider",
id: "my-provider",
options: {
// ...
},
},
],
},
},
],
})
The dependencies property accepts an array of module registration keys. The specified modules' main services are injected into the module's container.
If a module has providers, the dependencies are also injected into the providers' containers.
If you execute the performAction method of your service, the event is emitted and you can see it in your application's logs.
Any subscribers listening to the event are also executed.