The most basic and unopinionated implementation of GCP PubSub transport for NestJS microservices.
The publisher should not care who will handle the event and by which pattern, it only knows the topic. So, no hardcoded patterns in PubSub messages: on publishing events pass the topic-name
as a pattern, and on subscription pass topic-name/subscription-name
string as a pattern.
ack()
is called automatically when no errors are thrown while handling, otherwise nack()
is called.
No topics and subscriptions are created automatically. Because we care about security.
No request-response messaging support and it won't be added, as it's better to use appropriate RPC transports
npm i nestjs-gcp-pubsub @google-cloud/pubsub
import { GCPPubSubStrategy } from 'nestjs-gcp-pubsub';
NestFactory.createMicroservice(
AppModule,
{
strategy: new GCPPubSubStrategy({
// Props of { ClientConfig } from '@google-cloud/pubsub'
projectId: 'my-project-id',
// Optional deserializer, please see
// implementation in the sources.
// Default deserializer converts message's
// data (Buffer type) to string and
// parse it as JSON
deserializer: new MyDeserializer();
// Optional map of subscription options
// by <topic-name/subscription-name> pattern
subscriptionOpts: {
'my-topic/my-subscription': {
// Props of { SubscriptionOptions }
// from '@google-cloud/pubsub'
batching: { maxMessages: 10 },
}
};
});
},
)
import { ClientsModule } from '@nestjs/microservices';
import { GCPPubSubClient, GCPPubSubClientOptions } from 'nestjs-gcp-pubsub';
export const clientToken = Symbol();
@Module({
imports: [
ClientsModule.register([
{
name: clientToken,
customClass: GCPPubSubClient,
options: <GCPPubSubClientOptions>{
// Optional serializer, please see
// implementation in the sources.
// Default serializer converts emitted
// data to a JSON-string and pass it
// as a Buffer to outgoing Message's
// data field.
serializer: new MySerializer(),
// Optional map of topic options by
// topic-name
topicOpts: {
'my-topic': {
// Props of { PublishOptions }
// from '@google-cloud/pubsub'
messageOrdering: true,
}
},
},
},
]),
],
})
class AppModule {}
import { ClientProxy, EventPattern } from '@nestjs/microservices';
import { GCPPubSubContext } from 'nestjs-gcp-pubsub';
@Controller()
class TestController {
constructor(
// token that passed to ClientsModule.register
@Inject(clientToken)
private readonly client: ClientProxy
) {}
// to get only payload you don't need decorators
@EventPattern('my-topic/my-subscription')
handle(payload: MyType) {
//
}
// with context you have to use decorators
@EventPattern('my-topic/my-subscription-two')
handle(
@Payload() payload: MyType,
@Ctx() ctx: GCPPubSubContext
) {
//
}
async emit() {
await this.client.emit('my-topic', data as MyType).toPromise();
}
}