1 of 12

Services @Rocket.Chat

2 of 12

What is a service?

  • In base terms, a Class containing code
  • Services can be internal or external
  • Services can be defined inside Rocket.Chat or as Packages (see: Microservices)
  • Services can communicate through something called “Brokers”

​

3 of 12

What’s a broker?

  • Brokers are a way of communicating
  • They’re in charge of calls, events and communicating with other “nodes”
  • In Rocket.Chat, we have
    • LocalBroker (apps/meteor/server/sdk/lib/LocalBroker.ts)
    • NetworkBroker (apps/meteor/ee/server/NetworkBroker.ts)

​

4 of 12

LocalBroker

  • LocalBroker is the one used when Rocket.Chat runs as a “Monolith”
  • It extends IBroker class, which is the “base” of all brokers
  • It uses asyncLocalStorage to run service calls without loosing context ☺
  • All calls in here happen “in memory”
    • That means: all services are bundled in the monolith

​

5 of 12

NetworkBroker

  • As its name says, communication here happens via “network”
  • How this happens depends on the “Transporter”
    • A transporter is the way of communicating with “external” nodes. An external node is a service that doesn’t run in the same process as the monolith
    • Transporter could be TCP, NATS, Redis, MQTT, AMPQ, Kafka or a custom one (like, our “local” transporter

​

6 of 12

I have been talking for a while and haven’t presented an important guy

7 of 12

Moleculer

  • The lib we use to communicate with “network” services
  • And the base of the microservice architecture we have ☺
    • A ton of ideas on how services are run were made like that so they’re compatible with this guy, even when running local services

8 of 12

More on moleculer

  • It behaves like an RPC
    • So, it doesn’t execute things on a service
    • It tells a service which action to execute, via a string (with some internal parsing)
  • When it has the action (let’s say “authorization.canAccessRoom”)
    • It goes on the broker to find the “namespace”
      • Namespace is the part before the .
    • Then it calls a service (authorization) with the action (canAccessRoom) and waits the response (or not)
  • If there’s multiple instances (which happens) of the same service, it uses a balancing strategy.
    • In our case, the good ol’ round robin is used

9 of 12

How we use it at RC?

  • On the “call” action for networkbroker, we have a “broker.call” line.
  • This broker we’re calling is not our own broker, it’s actually moleculer broker
    • You can find this at apps/meteor/ee/server/startup/broker.ts
  • The moleculer broker receives the “transporter” we use. Normally, a NATS or a TCP transporter are used, for simplicity
    • In production, NATS is the one

​

10 of 12

So, how do we create services?

11 of 12

Why using services?

  • Looks better than having the code everywhere :troll:
  • Serves better as a logical separation of the code
  • Depending on the case, services can run as external processes, which gives a bit more of performance
  • Internal services are good too, as they help to pack similar behaviors on a single place

​

12 of 12

Final things

  • Don’t use meteor on an external service ☺ (the ones outside of Rocket.Chat)
  • Do them in typescript (do I have to say this?)
  • Do them beautifully