A simple Dapr module for NestJS framework with a focus on pubsub.
$ npm install --save @mrdiggles/nest-dapr
- Install and set up Dapr as described here: https://docs.dapr.io/getting-started
- Note: this library uses programmatic subscriptions
- You can reference this sample project
- Configure the
DaprModule
in your root module
@Module({
imports: [
DaprModule.forRoot({
client: {
host: 'localhost',
port: 3101, // i.e. --app-port <PORT>
},
server: {
host: 'localhost',
port: 3102, // i.e. --dapr-http-port <PORT>
},
}),
...
],
})
export class AppModule {}
- Register a Dapr pubsub in an app module
@Module({
imports: [
DaprModule.registerPubsub({
pubsubName: 'pubsub',
}),
],
...
})
export class MyAppModule {}
- Use the
DaprSubscriber
andDaprSubscribe
in a provider
@Injectable()
@DaprSubscriber('pubsub')
export class PubsubDemo {
@DaprSubscribe({ topic: 'orders' })
async handleOrdersTopic(payload: any) {
// Do stuff with the topic payload
}
...
}
Dynamic module that sets up the connection between your app and the Dapr sidecar. Should be imported into your root module.
Sample usage:
@Module({
imports: [
DaprModule.forRoot({
client: {
host: 'localhost',
port: 3101, // i.e. --app-port <PORT>
},
server: {
host: 'localhost',
port: 3102, // i.e. --dapr-http-port <PORT>
},
}),
...
],
})
export class AppModule {}
Dynamic module that injects DaprClient
. Required to use with InjectDaprClient
.
@Module({
imports: [
DaprModule.registerClient()
],
...
})
export class MyAppModule {}
Dynamic module that registers an app module to a Dapr pubsub. Required to use the decorators DaprSubscriber
, DaprSubscribe
, and InjectDaprPubSub
@Module({
imports: [
DaprModule.registerPubsub({
pubsubName: <PUBSUB NAME>,
}),
],
...
})
export class MyAppModule {}
Decorator for a provider that declares which pubsub it should be able to connect to.
@Injectable()
@DaprSubscriber(<NAME OF PUBSUB>)
export class PubsubDemo {
...
}
Decorator for a handler function that subscribes to a topic.
@DaprSubscribe({ topic: 'orders' })
async handleOrdersTopic(payload: any) {
// Do something with the payload
}
You can also configure error handling by passing in an options object
@DaprSubscribe({
topic: 'flaky-topic',
options: {
// The topic where Dapr should put failed messages
deadLetterTopic: 'example-dead-letter-topic',
// Instructs Dapr to retry before publishing it to DLT
failMethod: DaprPubSubStatusEnum.RETRY,
// Instructs Dapr to not retry and publish it into DLT
// failMethod: DaprPubSubStatusEnum.DROP,
},
})
async handleFlakyTopic(payload: FlakyTopicPayload) {
// Do something with the payload
}
Decorator to inject the raw Dapr client. Requires DaprModule.registerClient
to have been imported.
@Injectable()
class MyProvider {
constructor(@InjectDaprClient() private client: DaprClient) {}
async someFunction() {
// Configuration management: https://docs.dapr.io/developing-applications/building-blocks/configuration/
this.client.configuration
// Secrets management: https://docs.dapr.io/developing-applications/building-blocks/secrets/
this.client.secret
// Pubsub (if you prefer your own implementation): https://docs.dapr.io/developing-applications/building-blocks/pubsub/
this.client.pubsub
}
...
}
Decorator to inject the Dapr pubsub client. Requires DaprModule.registerPubsub
to have been imported.
@Injectable()
class MyProvider {
constructor(@InjectDaprPubSub(<PUBSUB NAME>) private pubsub: DaprPubsub<T>) {}
async someFunction() {
this.pubsub.publish(<TOPIC NAME>, <PAYLOAD>);
}
...
}