There are many requests for creating more transport strategies for the @nestjs/microservices
package and it would be nice to track them in one single place. Since we'll very likely never work on more than 1 strategy at once, it doesn't make sense to have +5 issues opened instead.
+1 for AWS EventBridge support
I'm curious for the AWS based transports, how many are using these running inside containers or VMs, vs processing these event sources in Lambda?
We are using Lambda as our deployment model, with Nest, and it has been working well. In that approach, processing Kinesis, SNS, SQS, EventBridge, has become trivial. We simply use NestFactory.createApplicationContext
and then pass the event and context into a service class that handles the logic.
So in my case, I'm less interested in a Kinesis, SQS, SNS, EventBridge specific transport, and more interested in creating a better way for Nest to handle incoming API Gateway events in a way that does nto require spinning up an Express server in the background, and passing it over a socket (al. a aws-serverless-express
). It's unnecessary overhead (which also has odd side effects), and if our experiance with using Nest to handle stream/queue/transport processing has taught us anything, Nest should be flexible enough to also handle incoming API Gateway events without Express.
@duro this is a very good point. I am already using EventBridge without any issues and when I call a micro service I instead use createApplicationContext
and that is working well for us at the moment. It would however be nice for nest microservices to support the transport but it鈥檚 not a showstopper as you point out. Using these transports would mean wiring received events to services becomes a lot easier than manually mapping the incoming payload to the appropriate event handler. And it keeps things consistent.
It would be very nice to have a solution that when deployed did not use an instance of express inside lambda to proxy the API gateway request. I totally agree it would be more beneficial to remove this overhead with respect to new AWS related functionality vs the transports.
I do however feel that perhaps the express provided middleware functionality may be an issue here in certain scenarios but that鈥檚 just me thinking aloud.
It would be very nice to have a solution that when deployed did not use an instance of express inside lambda to proxy the API gateway request.
@TreeMan360 @duro we have this implemented for Azure already. I suppose we should be able to deliver AWS version this year too
@kamilmysliwiec I believe I looked into the Azure implementation and it was still using an express server under the hood, similar to aws-serverless-express
. Please correct me if I'm wrong.
There are 2 modes available, with and without express. @duro
Ok, just a rando that stumbled onto this framework, and have been toying around with the idea of a lambda/serverless-esque framework for a while now, and wanted to give my thoughts...
I've been using the AWS CDK for the past 6 months and feel like this might be useful here. Perhaps some new decorators that define the lambda execution environments and notification triggers that is then scanned using the CDK to generate the necessary cloudformation behind the scenes. This would make the declaration of your lambda ecosystem completely code-driven.
Not sure if it makes sense for this project, but when I came across this framework I got excited by the possibilities.
Python has a framework that somewhat follows the convention I had in mind.
https://github.com/aws/chalice
@BrutalSimplicity I am using nest with the serverless framework and in this case it鈥檚 simple to add the appropriate cloudformation to the serverless.yml. Not quite as nice as the CDK but it works very well with the severless variable model etc.
The decorators you mention would be perfect, I wouldn鈥檛 need any kind of CDK scanning to generate the infrastructure but that does also sound 馃槑.
I'm not sure supporting all of the above is the right thing to do...
It might be a big issue to support it in the long run.
Instead, I think it will be better to refactor the microservice package a bit, so it will be easier to add your own transport.
It is mostly built for that, as there are a lot of transport already, so just exposing the right stuff, documenting and maybe a little tutorial will do.
I'm sure that some transports can even be created/managed by the authors... I believe microsoft will be interested in creating and maintaining the azure service bus transport...
Instead, I think it will be better to refactor the microservice package a bit, so it will be easier to add your own transport.
Actually, it's possible already. We are tracking the docs here https://github.com/nestjs/docs.nestjs.com/issues/113
Yep, I saw the code and I saw it's possible but there's a lot of interface to implement with not documentation so I wouldn't know where to start and what there is or isn't
Great job on the docs (and on the project in general!)
A lot of custom transport strategies is of course a good thing. But I don't think we should keep them all here in main repo.
At first because soon we just are not gonna be able to support all this bloated codebase. And its size is not even the main reason. The main reason, we should care about is code. If you take a look on current existing custom transports, for example kafka, code looks not really debuggable, 'cause typings are lost, we are loading package dynamically, 'cause kafkajs
is not explicitly listed in the dependencies.
let kafkaPackage: any = {};
class ServerKafka {
public constructor(...) {
// ...
kafkaPackage = this.loadPackage('kafkajs', ServerKafka.name, () =>
require('kafkajs'),
);
}
}
Although there is a @nestjs/microservices/external/kafka.interface.ts
file with external typings, mostly for configuration, so the consumer of this transport at least gets type-safety on initialization. But anyway supporting all this external typings and dynamically loaded packages with no typings is unnecessary overhead.
So my point is, that we should focus on refactoring and implementing more flexible and transparent interface for custom transports and their usage, instead of trying to integrate every single type of transport strategy into the exiting codebase.
it would be nace a transporter to KubeMQ. since kubernets is coming bigger day by day, and kubeMQ it's awesome solution for kubernets use
Just a quick note re: documenting custom transporters. I just published (the first 3 parts of) an in-depth tutorial on building custom transporters. https://dev.to/nestjs/part-1-introduction-and-setup-1a2l
Will be working on some official docs soon.
We've been building a reusable SawtoothModule for building Hyperledger Sawtooth apps using NestJS. Sawtooth uses ZeroMQ with Protobuf for internal communication between components. @kamilmysliwiec do you want to add ZeroMQ to that list? At this stage our custom transporter only supports a Dealer/Router pattern but I'm happy to put together a PR at some point.
Not sure if this "feature request" fits here but just want to add my 3 cents about "what I'd like to have in NestJS":
I'd like to have some kind of async jobs module like the one in rails: https://edgeguides.rubyonrails.org/active_job_basics.html . So you could schedule a job (add and receive a message) very easily with API like JobsService.perform(...)
JobsService.performLater(...)
; and with the transport mechanism being abstracted away.
I know there's @nestjs/bull
package already, but it's coupled with bull. What if I want to keep my queue in SQS, Postgres, or just in-memory of the server? Also, what if I don't have an ongoing server instance (and instead, have a AWS Lambda that is launched whenever SQS event appears)?
I'm writing now some code by myself that:
# src/jobs-aws-lambda.ts
import 'source-map-support/register';
import { INestApplication } from '@nestjs/common';
import { NestFactory } from '@nestjs/core';
import { SQSHandler } from 'aws-lambda';
import { AppModule } from './app.module';
import { JobsQueueMessageHandlerService } from './jobs/jobs-queue-message-handler/jobs-queue-message-handler.service';
let cachedApp: INestApplication;
async function initApp(): Promise<INestApplication> {
if (cachedApp) {
// eslint-disable-next-line no-console
console.log('Using cached server');
return cachedApp;
}
// eslint-disable-next-line no-console
console.log('Bootstraping server');
cachedApp = await NestFactory.create(AppModule);
return cachedApp;
}
export const handler: SQSHandler = async (event, context) => {
const app = await initApp();
const handlerService = app.get(JobsQueueMessageHandlerService);
await handlerService.handleSqsEvent(event, context);
};
import { Injectable } from '@nestjs/common';
import { SQS } from 'aws-sdk';
import { Job } from './job.interface';
@Injectable()
export class JobsService {
private _sqs?: SQS;
private readonly queueUrl = process.env.JOBS_SQS_QUEUE_URL!;
get sqs(): SQS {
if (!this._sqs) {
this._sqs = new SQS();
}
return this._sqs;
}
async perform(job: Job): Promise<void> {
switch (job.type) {
case 'LOG_TEST_MESSAGE':
return new Promise<void>(resolve => {
setTimeout(() => {
// eslint-disable-next-line no-console
console.log('LOG_TEST_MESSAGE job has been done!');
resolve();
}, 3000);
});
default:
throw new TypeError(`Unknown job: ${JSON.stringify(job)}`);
}
}
async performLater(job: Job): Promise<void> {
// TODO on development environment, just run `.perform()` locally
await this.sqs
.sendMessage({
QueueUrl: this.queueUrl,
MessageBody: JSON.stringify(job),
})
.promise();
}
}
Have you considered on the nestjs roadmap, to somehow make it possible in the future to wire up those different transport mechanisms with queues and task scheduling?
I imagine that in some future, you could choose and setup your queue transport mechanism AND add messages to it just by downloading some nest adapter module and configuring it, without the need of writing that custom code which I showed above 馃槂
I have tried implement custom strategy for NATS streaming. You can review my work here https://github.com/nestjs-ex/stan-strategy. I hope it can be added to @nestjs/microservice package.
Hello folks. So I originally opened the issue about SQS and I'd like to help out.
I'm curious for the AWS based transports, how many are using these running inside containers or VMs, vs processing these event sources in Lambda?
We are using Lambda as our deployment model, with Nest, and it has been working well. In that approach, processing Kinesis, SNS, SQS, EventBridge, has become trivial. We simply use
NestFactory.createApplicationContext
and then pass the event and context into a service class that handles the logic.So in my case, I'm less interested in a Kinesis, SQS, SNS, EventBridge specific transport, and more interested in creating a better way for Nest to handle incoming API Gateway events in a way that does nto require spinning up an Express server in the background, and passing it over a socket (al. a
aws-serverless-express
). It's unnecessary overhead (which also has odd side effects), and if our experiance with using Nest to handle stream/queue/transport processing has taught us anything, Nest should be flexible enough to also handle incoming API Gateway events without Express.
Something I'd like to work on is an AWS Transports package for NestJS. Originally I was going to add SQS first but I think I'll try out EventBridge or SNS. Unless anyone has any other suggestions.
For anyone interested:
I couldn't find a full start to finish guide on how to add my own custom transport layer strategy - so I did some digging in the source code, and ended up writing this guide:
Custom Transport Layers in NestJS
https://medium.com/@uri_chandler/custom-transport-layers-in-nestjs-5a913d9a383f
Most helpful comment
@TreeMan360 @duro we have this implemented for Azure already. I suppose we should be able to deliver AWS version this year too