Comments (15)
I've just encountered almost exactly the same use case as @andrucz. Multi-tenant app, need to inject tenant information into the context, but cannot get paramdecorators to work. Has anyone managed to work around this?
from nestjs.
With the release of Nest 6, there is supposed to be support for external context being integrated properly with the Nest request pipeline. Once #26 is complete it should be possible to revisit this and complete implementation
from nestjs.
hi @WonderPanda are there any updates on this issue?
from nestjs.
@WonderPanda, thankyou for your quick reply, yes the interceptor works very well, but I have some problem with the custom decorator.
For example:
export const ReportMessage = createParamDecorator((data: unknown, context: ExecutionContext) => {
return context.switchToHttp().getRequest().msg;
});
@RabbitSubscribe({
exchange: '---',
routingKey: '',
queue: '---',
})
@UseInterceptors(new InboxValidationInterceptor())
async updateLeadStatus(@ReportMessage() message: {}): Promise<Nack> {
...
}
The decorator ReportMessage is never called, the message object contains all request data and not only msg object.
from nestjs.
@mabuonomo Interceptors definitely work and are flexible enough that they can represent pretty much any of the other enhancers.
Is there specific functionality that you would like to integrate?
from nestjs.
@mabuonomo I'm not sure off the top of my head whether or not it will be easy for custom decorators to be used when processing incoming messages.
However, what you are showing in your custom decorator will never be possible as RabbitMQ does not use an HTTP Context for message passing
from nestjs.
Hi @WonderPanda what about injection scoped (especially interested in request
scope). Like somehow trigger amqpConnection
dependent services and controllers to be reinstantiated?
from nestjs.
@tataqwerty Can you please elaborate on your use case? Messages received over RabbitMQ are not tied to an HTTP request so it doesn't really make sense to ever try and make them request scoped. I don't even think it would be possible from a technical standpoint.
Everyone's app is different though so if you have a specific use case where this is important please share it here
from nestjs.
@WonderPanda I have a specific example that I am running into and @mabuonomo was going down the same path I am going down (and to no avail).
Basically, rather than just getting the message in our consumers, we want to receive some sort of context. In our specific example, we want to set an integrationId(or more simply a groupId), but this grouping is figured out inside of the consumer, not beforehand. So, right now we have an interceptor that hijacks the ampq channel message(the second arg) and adds our custom context class, i.e. channel.context = new MyClass().
Inside of the consuming function, rather than having to do channel.context.setIntegrationId(), we'd prefer to just get the context object, and deal with it. Great! Perfect use case for a paramDecorator. Unfortunately, it seems parameter decorators don't get exectuted AT ALL.
import { createParamDecorator, ExecutionContext } from '@nestjs/common'
export const MessageContextParam = createParamDecorator((data, ctx: ExecutionContext) => {
const context = ctx.getArgByIndex(1)
return context.context
})
When used with the following function for example, the decorator is not executed. Just as an FYI I have a decorator wrapper that wraps both our rabbitSubscribe, and our interceptor together, but it still happens even when using just rabbitSubscribe
@MessageBusService.subscribe({
exchange: messageBusConstants.exchanges.changeTracker.exchangeName,
routingKey: [ChangeTrackerEvents.EXECUTE.valueOf()],
queue: 'change_tracker_do_migration',
queueOptions: {
durable: true,
},
})
async doMigration(
event: MessageBusMessage<MigrationEvent>,
_,
@MessageContextParam() context: MessageContext,
)
Ideally, we would be able to just pass/reassign the 2nd arg in our inteceptor, but that's currently not possible in nestjs, and middlewares won't work with rabbitsubscribe I would assume, since it's hooked specifically to http requests.
from nestjs.
@JacobT14 I can definitely see the use case for this and think it woulds be a fantastic addition. Unfortunately I've had almost no time lately to look into improvements on the RabbitMQ side of things as I'm no longer using it for my day job which makes it difficult to context switch and prioritize. Any chance you feel like taking a crack at implementing a custom context for RabbitMQ messages? It should definitely be possible just needs a bit of investigation on the NestJS internals
from nestjs.
@WonderPanda I'll be honest, I'm somewhat new to nestjs, so I'm not really sure where I would start. The closest I would get would be just figuring out the reflection stuff inside of the handleMessage function(essentially just following how they handle it internally), but I'm not sure if that's actually what needs to happen. So, if you provide some initial guidance I might look into it, otherwise I have worked around it so I'm not blocked or anything. I'm just not sure if there's a way for us to hook into what they have as far as injecting it, or if we need to duplicate what they are doing.
from nestjs.
@JacobT14 No worries, my first hunch would be to take a look at the ExternalContextCreator
as its how we currently wire up the RabbitMQ handlers to the NestJS pipeline
Nest has a few built in context types for HTTP, RPC, and GraphQL already so I definitely think it should be possible to extend what we're currently doing to give a much deeper integration that is specifically tailored to RabbitMQ
Unfortunately its not exactly a documented API, I had to do a bunch of source diving in the NestJS code base originally to figure out how to get this far
from nestjs.
I'm working on a multi-tenant app and would like to use a guard to inject information about the tenant in the execution context and access it in the handler using a param decorator. That works well using the built-in NestJS microservices module, but I had to switch to this library as it supports pub/sub. I just realized param decorators don't get executed at all. @JacobT14 how did you work around it?
from nestjs.
I am thinking we can take advantage of consumer tags. I create a queue and register handlers myself. Ideally connection.createSubscriber()
will give me the consumer tags, so I can map it to the tenant i am creating the queue for.
But it seems that the returned consumer tag is undefined for connection.createSubscriber(handler, mergedConfig, discoveredMethod.methodName);
I will need investigate more.
Yeah i found my problem, i need add this connectionInitOptions: { wait: true },
to my RabbitMQConfig
, when i dynamically setup rabbit mq
from nestjs.
@huantaoliu would you mind sharing some examples?
from nestjs.
Related Issues (20)
- @golevelup/ts-jest default mocks return an empty object which is inconsistent with jest.fn() which returns undefined.
- @golevelup/nestjs-rabbitmq- error when publish message: Channel closed
- ts-jest - When function is called with a mock, toHaveBeenCalledWith() always succeed even when it should not
- rabbitmq: allow per subscriber/handler deserializer customization HOT 1
- RabbitMQ AmqpConnection access from child module
- Wildcard routing stopped working. RabbitMQ
- rabbitmq: support specifying exchange per routing key in RabbitSubscribe
- Single Channel Configuration Across Multiple @RabbitSubscribe Decorators Not Working as Expected
- No delivery mode option on AmqpConnection.request method HOT 2
- RabbitMQ: RabbitSubscribe using a handler name without corresponding handler config asserts randomized queues HOT 3
- rabbitmq: consumerTags are not cleaned up on connection/channel disconnect
- rabbitmq: canceled consumers are resumed if connection/channel reconnects HOT 1
- rabbitmq: direct sending to queue without the need for exchanges HOT 1
- rabbitmq: binding a queue to exchange without a routingKey
- ts-jest: Cannot create mock of a class which has private dependencies in constructor
- rabbitmq: handlers didn't works in app-non-pub HOT 1
- golevelup/nestjs-stripe: project can not compile
- Stripe Test Webhook
- Stripe webhooks - "undefined" is not valid JSON HOT 2
- How should I use this within RabbitSubscribe method?
Recommend Projects
-
React
A declarative, efficient, and flexible JavaScript library for building user interfaces.
-
Vue.js
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
-
Typescript
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
-
TensorFlow
An Open Source Machine Learning Framework for Everyone
-
Django
The Web framework for perfectionists with deadlines.
-
Laravel
A PHP framework for web artisans
-
D3
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
-
Recommend Topics
-
javascript
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
-
web
Some thing interesting about web. New door for the world.
-
server
A server is a program made to process requests and deliver data to clients.
-
Machine learning
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
-
Visualization
Some thing interesting about visualization, use data art
-
Game
Some thing interesting about game, make everyone happy.
Recommend Org
-
Facebook
We are working to build community through open source technology. NB: members must have two-factor auth.
-
Microsoft
Open source projects and samples from Microsoft.
-
Google
Google ❤️ Open Source for everyone.
-
Alibaba
Alibaba Open Source for everyone
-
D3
Data-Driven Documents codes.
-
Tencent
China tencent open source team.
from nestjs.