Strapi and Nats Streaming Server (pub/sub messaging)

Pretty straight forward actually. I went with a more elaborate approach of creating a wrapper for NATS so I could create a singleton but the actual implementation is as follows.

I created an events folder to house all of my nats related logic.

In the primary config/functions/bootstrap.js

module.exports = () => {
  process.nextTick(async () => {
// use nextTick to ensure that global strapi is available for logging purposes
    await natsWrapper.connect(
      process.env.clusterId,
      process.env.clientId,
      process.env.natsUrl
    );

// also a good place to initialize listeners if needed
  });
};

Then in the events/nats-wrapper.js

const nats = require("node-nats-streaming");

class NatsWrapper {
  _client;

  get client() {
   // ... singleton logic
  }

  connect(clusterId, clientId, url) {
    this._client = nats.connect(clusterId, clientId, { url });

    return new Promise((resolve, reject) => {
      this.client.on("connect", () => {
        // ... if good connection resolve
      });
      this.client.on("error", (err) => {
        // no connection then reject
      });
    });
  }
}
const natsWrapper = new NatsWrapper();

module.exports = natsWrapper;

Then in my case, If I wanted to send an event on entity create or update etc…, I can simply import a publisher in the models lifecycle methods and send it off.

Personally, I use a shared common module that contains core logic for all my services so I can just subclass out listeners or publishers and leave all of the heavy lifting to my module.

This is still very much a WIP but it seems to work well enough.

I am still working on how to perform graceful shutdown and a few other minor things but this seems to work well for me. Best of luck, and let me know if you have any other questions.

1 Like