Skip to content

Commit

Permalink
docs: add emit events + types documentation (#10026)
Browse files Browse the repository at this point in the history
* docs: add emit events + types documentation

* vale fixes
  • Loading branch information
shahednasser authored Nov 13, 2024
1 parent 7a26e12 commit f151fb3
Show file tree
Hide file tree
Showing 3 changed files with 155 additions and 9 deletions.
Original file line number Diff line number Diff line change
@@ -1,22 +1,50 @@
import { CodeTabs, CodeTab } from "docs-ui"

export const metadata = {
title: `${pageNumber} Emit an Event`,
title: `${pageNumber} Emit Workflow and Service Events`,
}

# {metadata.title}

In this chapter, you'll learn how to emit an event in a workflow.
In this chapter, you'll learn about event types and how to emit an event in a service or workflow.

## Event Types

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:

1. Worflow event: an event that's emitted in a workflow after a commerce feature is performed. For example, Medusa emits the `order.placed` event after a cart is completed.
2. Service event: an event that's emitted to track, trace, or debug processes under the hood. For example, you can emit an event with an audit trail.

### Which Event Type to Use?

**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:

## Emit Event Step
1. When a user creates a blog post and you're emitting an event to send a newsletter email.
2. When you finish syncing products to a third-party system and you want to notify the admin user of new products added.
3. When a customer purchases a digital product and you want to generate and send it to them.

Medusa provides an `emitEventStep` helper step in the `@medusajs/medusa/core-flows` package that emits an event.
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.

When you emit an event, you specify the event's name and data payload to pass with the event.
Some examples of service events:

1. When you're tracing data manipulation and changes, and you want to track every time some custom data is changed.
2. When you're syncing data with a search engine.

---

## Emit Event in a Workflow

To emit a workflow event, use the `emitEventStep` helper step provided in the `@medusajs/medusa/core-flows` package.

For example:

export const highlights = [
["13", "emitEventStep", "Emit an event."],
["14", `"custom.created"`, "The name of the event to emit."],
["14", `eventName`, "The name of the event to emit."],
["15", "data", "The data payload to pass with the event."]
]

Expand All @@ -37,12 +65,129 @@ const helloWorldWorkflow = createWorkflow(
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 emit is emitted and any subscribers listening to the event are executed.
### Test it Out

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.

---

## Emit Event in a Service

To emit a service event:

1. Resolve `event_bus` from the module's container in your service's constructor:

<CodeTabs group="service_type">
<CodeTab label="Extending Service Factory" value="service_factory">

```ts title="src/modules/hello/service.ts" highlights={["9"]}
import { IEventBusService } from "@medusajs/framework/types"
import { MedusaService } from "@medusajs/framework/utils"

class HelloModuleService extends MedusaService({
MyCustom,
}){
protected eventBusService_: AbstractEventBusModuleService

constructor({ event_bus }) {
super(...arguments)
this.eventBusService_ = event_bus
}
}
```

</CodeTab>
<CodeTab label="Without Service Factory" value="no_service_factory">

```ts title="src/modules/hello/service.ts" highlights={["6"]}
import { IEventBusService } from "@medusajs/framework/types"

class HelloModuleService {
protected eventBusService_: AbstractEventBusModuleService

constructor({ event_bus }) {
this.eventBusService_ = event_bus
}
}
```

</CodeTab>
</CodeTabs>

2. Use the event bus service's `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."]
]

```ts title="src/modules/hello/service.ts" highlights={serviceHighlights}
class HelloModuleService {
// ...
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.

3. By default, the Event Module's service isn't injected into your module's container. To add it to the container, pass it in the module's registration object in `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."],
]

```ts title="medusa-config.ts" highlights={depsHighlight}
import { Modules } from '@medusajs/framework/utils'

module.exports = defineConfig({
// ...
modules: [
{
resolve: "./src/modules/hello",
dependencies: [
Modules.EVENT_BUS
]
}
]
})
```

The `dependencies` property accepts an array of module registration keys. The specified modules' main services are injected into the module's container.

That's how you can resolve it in your module's main service's constructor.

### Test it Out

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.
2 changes: 1 addition & 1 deletion www/apps/book/generated/edit-dates.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ export const generatedEditDates = {
"app/learn/advanced-development/events-and-subscribers/data-payload/page.mdx": "2024-07-16T17:12:05+01:00",
"app/learn/advanced-development/data-models/default-properties/page.mdx": "2024-09-19T07:32:06.118Z",
"app/learn/advanced-development/workflows/advanced-example/page.mdx": "2024-09-11T10:46:59.975Z",
"app/learn/advanced-development/events-and-subscribers/emit-event/page.mdx": "2024-09-30T08:43:53.125Z",
"app/learn/advanced-development/events-and-subscribers/emit-event/page.mdx": "2024-11-11T15:17:58.045Z",
"app/learn/advanced-development/workflows/conditions/page.mdx": "2024-09-30T08:43:53.128Z",
"app/learn/advanced-development/modules/module-link-directions/page.mdx": "2024-07-24T09:16:01+02:00",
"app/learn/advanced-development/admin/page.mdx": "2024-10-07T12:39:13.178Z",
Expand Down
3 changes: 2 additions & 1 deletion www/apps/book/sidebar.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -392,8 +392,9 @@ export const sidebar = numberSidebarItems(
title: "Events Data Payload",
},
{
type: "link",
path: "/learn/advanced-development/events-and-subscribers/emit-event",
title: "Emit an Event",
title: "Emit Event",
},
],
},
Expand Down

0 comments on commit f151fb3

Please sign in to comment.