Skip to content

feat(microservices): Allow custom exchangeType as string for plugin compatibility #15057

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Conversation

ChangmoKang
Copy link
Contributor

@ChangmoKang ChangmoKang commented May 2, 2025

PR Checklist

Please check if your PR fulfills the following requirements:

PR Type

What kind of change does this PR introduce?

  • Bugfix
  • Feature
  • Code style update (formatting, local variables)
  • Refactoring (no functional changes, no api changes)
  • Build related changes
  • CI related changes
  • Other... Please describe:

What is the current behavior?

Currently, only the default exchange types can be used.

Issue Number: N/A

What is the new behavior?

Make exchangeType configurable as a generic string instead of strict union, enabling support for plugins like rabbitmq-delayed-message-exchange which use non-standard types (e.g., x-delayed-message, x-local-random).

# Exchange Type Plugin Key Features Min. RabbitMQ
1 x‑delayed-message rabbitmq_delayed_message_exchange Schedules or retries messages via the x-delay header—removes the need for TTL‑DLX stacks 3.6.0+
2 x‑consistent-hash rabbitmq_consistent_hash_exchange Consistent‑hash key‑to‑queue load‑balancing with minimal key relocation when consumers scale 3.7.0+
3 x‑modulus-hash rabbitmq_sharding Simple hash(key) mod N sharding for linear throughput growth 3.8.0+
4 x‑random rabbitmq_random_exchange Picks one queue at random among those bound with the same routing key—lightweight load spread 3.6.0+
5 x‑local-random Local Random Exchange Docs Routes only to queues on the publisher’s node, then random‑selects—cuts network hops 4.0.0+
6 x‑lvc (Last Value Cache) rabbitmq_lvc_exchange Stores the latest message per routing key; new bindings receive that snapshot instantly 3.6.0+
7 x‑recent-history rabbitmq_recent_history_exchange Keeps the last N (default 20) messages and replays them—ideal for chat or log viewers 3.6.0+
8 x‑rtopic (Reverse Topic) rabbitmq_rtopic_exchange Lets publishers use wildcards (*#) while bindings stay static—publisher‑driven multicast 3.6.0+
9 x‑management rabbitmq_management_exchange Invokes the Management HTTP API via pure AMQP frames—handy behind firewalls 3.6.0+

rabbitmqui-exchangeType

Does this PR introduce a breaking change?

  • Yes
  • No

Other information

@coveralls
Copy link

coveralls commented May 2, 2025

Pull Request Test Coverage Report for Build db5aa2fa-ca53-4757-a161-3dca69eec471

Details

  • 0 of 0 changed or added relevant lines in 0 files are covered.
  • No unchanged relevant lines lost coverage.
  • Overall coverage remained the same at 88.923%

Totals Coverage Status
Change from base Build c99d332b-8204-48ec-bc18-15971298dd6e: 0.0%
Covered Lines: 7177
Relevant Lines: 8071

💛 - Coveralls

@ChangmoKang ChangmoKang force-pushed the microservices-configuration-rmqoptions branch from 5d3ba97 to ef632bf Compare May 2, 2025 22:04
@ChangmoKang ChangmoKang changed the title feat(rmq-options): allow custom exchangeType as string for plugin compatibility feat(microservices): Allow custom exchangeType as string for plugin compatibility May 2, 2025
@@ -286,7 +286,7 @@ export interface RmqOptions {
* Type of the exchange
* @default 'topic'
*/
exchangeType?: 'direct' | 'fanout' | 'topic' | 'headers';
exchangeType?: string;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
exchangeType?: string;
exchangeType?: 'direct' | 'fanout' | 'topic' | 'headers' | string & {};

with this (ugly) hack we'd be able to preserve type intelisense

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@kamilmysliwiec That would also be good. pragmatic way to preserve Intellisense while keeping flexibility.

Maybe we could define a type and use it explicitly to make things even clearer.

// packages/microservices/external/rmq-url.interface.ts:71
type AmqpMainExchangeType = 'direct' | 'fanout' | 'topic' | 'headers';

/**
 * @publicApi
 */
export type AmqpExchangeType = AmqpMainExchangeType | (string & {});
// packages/microservices/interfaces/microservice-configuration.interface.ts:289
exchangeType?: AmqpExchangeType;

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

external is supposed to hold files (types) that are copied from the original package, so adding a new custom type there might cause unexpected issues later on

Defined a dedicated type for AMQP exchange types to enhance type safety and maintain IDE support,
replacing inline union with a named type for better readability and reusability.
@ChangmoKang
Copy link
Contributor Author

@kamilmysliwiec I’ve removed the custom type and updated the code as initially suggested to preserve IntelliSense.
Please feel free to leave a comment if there’s anything else that needs to be addressed.

@kamilmysliwiec kamilmysliwiec merged commit 92b4358 into nestjs:master May 8, 2025
3 checks passed
@kamilmysliwiec
Copy link
Member

LGTM

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants