Skip to content

chore: NATS broker for micro services - #35305

Draft
sampaiodiego wants to merge 18 commits into
developfrom
nats-broker
Draft

chore: NATS broker for micro services#35305
sampaiodiego wants to merge 18 commits into
developfrom
nats-broker

Conversation

@sampaiodiego

@sampaiodiego sampaiodiego commented Feb 21, 2025

Copy link
Copy Markdown
Member

https://rocketchat.atlassian.net/browse/RDI-278

Proposed changes (including videos or screenshots)

This is currently a PoC. The idea is to provide a broker for our services architecture that relies only on NATS, so we make use of all its features.

These are tracked items that are still missing:

  • events
    • listening
    • broadcasting
    • Life cycle events
    • Node events
      • Node connected
      • Node disconnected
  • tracing
  • metrics
  • server list
  • reliability
  • error handling
  • namespaces

Issue(s)

Steps to test or reproduce

Further comments


This pull request introduces significant changes to the Rocket.Chat repository, specifically targeting the integration of a NATS broker for microservices. The key modifications include:

  1. Renaming and Refactoring:

    • The NetworkBroker has been renamed to MoleculerBroker in the MoleculerBroker.ts file. Additionally, the method discovery logic has been extracted into a new getInstanceMethods function to enhance code organization.
  2. NATS Broker Implementation:

    • A new NatsBroker.ts file has been added, implementing a NATS-based broker service. This service includes capabilities for event handling, service creation, and message broadcasting.
  3. Test Updates:

    • The test file MoleculerBroker.test.ts has been updated to replace NetworkBroker with MoleculerBroker, ensuring that the test functionality for service destruction remains intact.
  4. Code Organization:

    • The index.ts file has been simplified by moving broker implementation details to separate files. It now exports MoleculerBroker, NatsBroker, and the startBroker function.
  5. Moleculer Configuration:

    • A new moleculer.ts file introduces a configuration for the Moleculer service broker, including custom error handling, serialization, and various settings managed through environment variables.
  6. API Class Update:

    • The Api class in Api.ts has been updated to include a new started property, along with related changes to manage the broker's start method.

These changes aim to enhance the microservices architecture within the Rocket.Chat platform by integrating a robust NATS broker and improving the existing broker infrastructure.

@dionisio-bot

dionisio-bot Bot commented Feb 21, 2025

Copy link
Copy Markdown
Contributor

Looks like this PR is not ready to merge, because of the following issues:

  • This PR is missing the 'stat: QA assured' label
  • This PR is missing the required milestone or project

Please fix the issues and try again

If you have any trouble, please check the PR guidelines

@changeset-bot

changeset-bot Bot commented Feb 21, 2025

Copy link
Copy Markdown

⚠️ No Changeset found

Latest commit: 1dca717

Merging this PR will not cause a version bump for any packages. If these changes should not result in a new version, you're good to go. If these changes should result in a version bump, you need to add a changeset.

This PR includes no changesets

When changesets are added to this PR, you'll see the packages that this PR includes changesets for and the associated semver types

Click here to learn what changesets are, and how to add one.

Click here if you're a maintainer who wants to add a changeset to this PR

@codecov

codecov Bot commented Feb 21, 2025

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 85.19637% with 49 lines in your changes missing coverage. Please review.
✅ Project coverage is 69.36%. Comparing base (2a7de45) to head (1dca717).

Additional details and impacted files

Impacted file tree graph

@@             Coverage Diff             @@
##           develop   #35305      +/-   ##
===========================================
+ Coverage    69.33%   69.36%   +0.03%     
===========================================
  Files         4255     4259       +4     
  Lines       168644   168954     +310     
  Branches     30052    30144      +92     
===========================================
+ Hits        116929   117200     +271     
- Misses       46534    46567      +33     
- Partials      5181     5187       +6     
Flag Coverage Δ
unit 71.32% <85.19%> (+0.04%) ⬆️

Flags with carried forward coverage won't be shown. Click here to find out more.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

@ggazzo

ggazzo commented Feb 26, 2025

Copy link
Copy Markdown
Member

@kody start-review

@kody-ai

kody-ai Bot commented Feb 26, 2025

Copy link
Copy Markdown

Code Review Completed! 🔥

The code review was successfully completed based on your current configurations.

Kody Guide: Usage and Configuration
Interacting with Kody
  • Request a Review: Ask Kody to review your PR manually by adding a comment with the @kody start-review command at the root of your PR.

  • Provide Feedback: Help Kody learn and improve by reacting to its comments with a 👍 for helpful suggestions or a 👎 if improvements are needed.

Current Kody Configuration
Review Options

The following review options are enabled or disabled:

Options Enabled
Security
Code Style
Kody Rules
Refactoring
Error Handling
Maintainability
Potential Issues
Documentation And Comments
Performance And Optimization

Access your configuration settings here.

Comment on lines +12 to +17
const serviceEvents = new Set<{
eventName: keyof EventSignatures;
listeners: {
(...args: any[]): void;
}[];
}>();

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

kody code-reviewPotential Issues

private serviceEvents = new Set<{
	eventName: keyof EventSignatures;
	listeners: {
		(...args: any[]): void;
	}[];
}>();

Potential memory leaks due to global serviceEvents Set

This issue appears in multiple locations:

  • ee/packages/network-broker/src/NatsBroker.ts: Lines 12-17

Please move serviceEvents to the class instance and implement cleanup in destroyService

Talk to Kody by mentioning @kody

Was this suggestion helpful? React with 👍 or 👎 to help Kody learn from this interaction.


import { MoleculerBroker } from './MoleculerBroker';

const {

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

kody code-reviewError Handling

function validateEnvConfig(config: Record<string, string>) {
  const numberFields = ['REQUEST_TIMEOUT', 'HEARTBEAT_INTERVAL', 'HEARTBEAT_TIMEOUT', 'RETRY_FACTOR', 'RETRY_MAX_DELAY'];
  const booleanFields = ['RETRY_ENABLED', 'BULKHEAD_ENABLED', 'MS_METRICS'];

  for (const field of numberFields) {
    if (isNaN(parseInt(config[field]))) {
      throw new Error(`Invalid ${field} value: must be a number`);
    }
  }

  for (const field of booleanFields) {
    if (![undefined, 'true', 'false'].includes(config[field])) {
      throw new Error(`Invalid ${field} value: must be 'true' or 'false'`);
    }
  }

  return config;
}

const config = validateEnvConfig(process.env);

Missing function description comments

This issue appears in multiple locations:

  • ee/packages/network-broker/src/moleculer.ts: Lines 9-32
  • ee/packages/network-broker/src/getInstanceMethods.ts: Lines 3-3

Please add detailed function description comments for better code understanding

Talk to Kody by mentioning @kody

Was this suggestion helpful? React with 👍 or 👎 to help Kody learn from this interaction.

Comment on lines +87 to +89
} catch (e) {
console.error('error', e);
}

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

kody code-reviewError Handling

} catch (e) {
	const error = e instanceof Error ? e : new Error('Unknown error');
	console.error('Service method execution failed:', error);
	if (msg?.respond) {
		msg.respond(TE.encode(EJSON.stringify({ error: error.message })));
	}
}

Insufficient error handling in service methods

This issue appears in multiple locations:

  • ee/packages/network-broker/src/NatsBroker.ts: Lines 87-89
  • ee/packages/network-broker/src/NatsBroker.ts: Lines 121-123

Please improve error handling in service methods with proper error propagation

Talk to Kody by mentioning @kody

Was this suggestion helpful? React with 👍 or 👎 to help Kody learn from this interaction.

};

export class NetworkBroker implements IBroker {
export class MoleculerBroker implements IBroker {

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

kody code-reviewDocumentation and Comments

/**
 * Implementation of IBroker using Moleculer service broker
 * for handling service communication and event distribution.
 */
export class MoleculerBroker implements IBroker {

Inadequate type definitions for error handling

This issue appears in multiple locations:

  • ee/packages/network-broker/src/MoleculerBroker.ts: Lines 21-21
  • ee/packages/network-broker/src/moleculer.ts: Lines 37-37

Please add proper type definitions for error handling to improve type safety

Talk to Kody by mentioning @kody

Was this suggestion helpful? React with 👍 or 👎 to help Kody learn from this interaction.

@coderabbitai

coderabbitai Bot commented Apr 15, 2026

Copy link
Copy Markdown
Contributor

Important

Review skipped

Draft detected.

Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro Plus

Run ID: f4e81f1e-33b3-43a9-abfb-00f06c503de0

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • 🔍 Trigger review

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@rc-layne

rc-layne Bot commented Apr 28, 2026

Copy link
Copy Markdown

🔴 Layne — 2 finding(s)

Found 2 issue(s): 1 high, 1 medium.

sampaiodiego and others added 2 commits August 21, 2026 18:11
EnterpriseCheck was a Moleculer ServiceSchema, so the policy it implements
(no scalability module means only one service instance per environment) was
unavailable to any other broker. Move the policy into licenseEnforcement and
have the mixin delegate to it, so NatsBroker can reuse it.

The failure counter is now per service instead of a module level counter
shared by every mixin instance, which is what MAX_FAILS consecutive failures
was meant to mean.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Events and service methods shared one flat subject space, so a broadcast of
`accounts.login` invoked the `accounts` service `login` method and a call to
that method was delivered to the event listeners. Methods now answer on
`rpc.<service>.<method>` and events publish on `event.<name>`.

The node id is published as micro service metadata, which is what the rest of
this change is built on:

- `nodeList()` is served from `$SRV.PING` discovery instead of returning an
  empty array, and `$node.services` is answered from the same source so
  apps-engine keeps working
- each method also answers on `node.<nodeID>.<service>.<method>`, so
  `CallingOptions.nodeID` reaches one instance rather than being load
  balanced across the queue group
- non internal services get the shared license enforcement, so selecting this
  broker no longer turns the scalability check off

Also in the same pass, because they touch the same registration path:

- requests use REQUEST_TIMEOUT rather than the nats default of one second
- `destroyService` stops the micro service, drains the event subscriptions
  and removes the instance listeners; events are tracked per instance instead
  of in a module level Set that was never pruned
- one subscription per event routed through `emit`, so listeners registered
  after startup are still reached
- NATS_URL replaces the overloaded TRANSPORTER, which compose passes through
  as an empty string and so bypassed the old destructuring default

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
sampaiodiego and others added 4 commits August 21, 2026 19:33
A throwing endpoint only logged, never answered, so the caller blocked until
the request timeout and then saw a timeout instead of the real error. Reply
with the nats micro error headers plus an EJSON body, and rehydrate it on the
calling side.

MeteorError is serialized through toJSON and restored with its error code,
reason, details and isClientSafe intact, which is what the Moleculer
CustomRegenerator does for the other broker.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
There was no coverage for NatsBroker at all. Add an in memory stand in for
NatsConnection covering the parts the broker uses - subject routing,
request/reply, the micro registry and discovery - and specs for the subject
namespaces, node scoped routing, error round trip, discovery and teardown.

The namespace specs are the regression guard: broadcasting `accounts.login`
must not invoke the `accounts` service `login` method, and calling that
method must not notify the event listeners.

Also renames the MoleculerBroker describe block, still labelled NetworkBroker
after the rename.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
The lockfile resolved two distinct nats versions, 2.28.2 for the app and the
microservices and 2.29.1 for network-broker, so two copies of the client were
installed. Pin everything to ^2.29.1.

The dev services env file had no way to select the broker, so local
microservices development could only run on moleculer.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
The e2e workflow forced BROKER=nats for every EE suite, replacing the
Moleculer coverage rather than adding to it. Take the broker as an input
defaulting to moleculer, so callers opt in per suite.

The readiness gate accepted either broker's startup log, so a silent fallback
would have passed unnoticed; it now waits for the broker that was asked for.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
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.

2 participants