diff --git a/plugins/events-backend/README.md b/plugins/events-backend/README.md index af9812eab7..2288c91f2e 100644 --- a/plugins/events-backend/README.md +++ b/plugins/events-backend/README.md @@ -6,7 +6,7 @@ This plugin provides the wiring of all extension points for managing events as defined by [plugin-events-node](../events-node) including backend plugin `EventsPlugin` and `EventsBackend`. -Additionally, it uses a simple in-memory implementation for +Additionally, it uses a simple in-process implementation for the `EventBroker` by default which you can replace with a more sophisticated implementation of your choice as you need (e.g., via module). @@ -24,7 +24,13 @@ to the used event broker. yarn add --cwd packages/backend @backstage/plugin-events-backend ``` -You will need to add the following to the backend configuration `#makeCreateEnv`. +### Event Broker + +First you will need to add and implementation of the `EventBroker` interface to the backend plugin environment. +This will allow event broker instance any backend plugins to publish and subscribe to events in order to communicate +between them. + +Add the following to `makeCreateEnv` ```diff // packages/backend/src/index.ts @@ -38,10 +44,69 @@ Then update plugin environment to include the event broker. + eventBroker: EventBroker; ``` -Add a file [`packages/backend/src/plugins/events.ts`](../../packages/backend/src/plugins/events.ts) -to your Backstage project. +### Publishing and Subscribing to events with the broker -There, you can add all publishers, subscribers, etc. you want. +Backend plugins are passed the event broker in the plugin environment at startup of the application. The plugin can +make use of this to communicate between parts of the application. + +Here is an example of a plugin publishing a payload to a topic. + +```typescript jsx +export default async function createPlugin( + env: PluginEnvironment, +): Promise { + env.eventBroker.publish({ + topic: 'publish.example', + eventPayload: { message: 'Hello, World!' }, + metadata: {}, + }); +} +``` + +Here is an example of a plugin subscribing to a topic. + +```typescript jsx +export default async function createPlugin( + env: PluginEnvironment, +): Promise { + env.eventBroker.subscribe([ + { + supportsEventTopics: ['publish.example'], + onEvent: async (params: EventParams) => { + env.logger.info(`receieved ${params.topic} event`); + }, + }, + ]); +} +``` + +### Implementing an `EventSubscriber` class + +More complex solutions might warrent the creation of a class that implements the `EventSubscriber` interface. e.g. + +```typescript jsx +import { EventSubscriber } from "./EventSubscriber"; + +class ExampleSubscriber implements EventSubscriber { + ... + + supportsEventTopics() { + return ['publish.example'] + } + + async onEvent(params: EventParams) { + env.logger.info(`receieved ${params.topic} event`) + } +} +``` + +### Events Backend + +The events backend plugin provides a router to handler http events and publish the http requests onto the event +broker. + +To configure it add a file [`packages/backend/src/plugins/events.ts`](../../packages/backend/src/plugins/events.ts) +to your Backstage project. Additionally, add the events plugin to your backend. @@ -56,46 +121,7 @@ Additionally, add the events plugin to your backend. // [...] ``` -### With Event-based Entity Providers - -In case you use event-based `EntityProviders`, -you will need to add the subscription to the catalog plugin creation: - -```diff -// packages/backend/src/plugins/catalog.ts -+ -``` - -In case you don't have this dependency added yet: - -```bash -# From your Backstage root directory -yarn add --cwd packages/backend @backstage/plugin-events-backend -``` - -```diff -// packages/backend/src/plugins/catalog.ts - import { CatalogBuilder } from '@backstage/plugin-catalog-backend'; -+import { DemoEventBasedEntityProvider } from './DemoEventBasedEntityProvider'; - import { ScaffolderEntitiesProcessor } from '@backstage/plugin-scaffolder-backend'; - import { Router } from 'express'; - import { PluginEnvironment } from '../types'; - - export default async function createPlugin( - env: PluginEnvironment, - ): Promise { - const builder = await CatalogBuilder.create(env); - builder.addProcessor(new ScaffolderEntitiesProcessor()); -+ const demoProvider = new DemoEventBasedEntityProvider(logger, ['example']); -+ env.eventBroker.subscribe(demoProvider); -+ builder.addEntityProvider(demoProvider); - const { processingEngine, router } = await builder.build(); - await processingEngine.start(); - return router; - } -``` - -## Configuration +#### Configuration In order to create HTTP endpoints to receive events for a certain topic, you need to add them at your configuration: @@ -125,6 +151,34 @@ in combination with suitable event subscribers. However, it is not limited to these use cases. +### Event-based Entity Providers + +You can implement the `EventSubscriber` interface on an `EntityProviders` to allow it to handle events from other plugins e.g. the event backend plugin +mentioned above. + +Assuming you have configured the `eventBroker` into the `PluginEnvironment` you can pass the broker to the entity provider for it to subscribe. + +```diff +// packages/backend/src/plugins/catalog.ts + import { CatalogBuilder } from '@backstage/plugin-catalog-backend'; ++import { DemoEventBasedEntityProvider } from './DemoEventBasedEntityProvider'; + import { ScaffolderEntitiesProcessor } from '@backstage/plugin-scaffolder-backend'; + import { Router } from 'express'; + import { PluginEnvironment } from '../types'; + + export default async function createPlugin( + env: PluginEnvironment, + ): Promise { + const builder = await CatalogBuilder.create(env); + builder.addProcessor(new ScaffolderEntitiesProcessor()); ++ const demoProvider = new DemoEventBasedEntityProvider({ logger: env.logger, topics: ['example'], eventBroker: env.eventBroker }); ++ builder.addEntityProvider(demoProvider); + const { processingEngine, router } = await builder.build(); + await processingEngine.start(); + return router; + } +``` + ## Use Cases ### Custom Event Broker