Giter Site home page Giter Site logo

buzzertech / jerryquu Goto Github PK

View Code? Open in Web Editor NEW
3.0 2.0 0.0 509 KB

A fast, reliable redis-based email queue for Node.js written in Typescript

License: MIT License

TypeScript 45.39% JavaScript 54.61%
email-queue nodejs redis-queue pubsub fast redis queue typescript nodemailer-queue

jerryquu's Introduction

JerryQuu

CircleCI semantic-release npm npm

JerryQuu is a fast, reliable redis-based email queue for Node.js applications. The library has cool features such as a custom handler, retries, etc. Also, this library explicitly has zero dependencies.

Features

  • Implements a FIFO queuing mechanism with the help of Redis.
  • Use any redis client of your choice until it supports keyspace events
  • If any of the message couldn't be sent by Nodemailer, JerryQuu adds the message back to the queue so that it can be processed again. By default, JerryQuu has a maximum retry limit of 4.
  • You can write your own custom handler to handle messages.

Why use JerryQuu over something like Amazon SQS ?

If you are building a small project and you don't want to get into handling something like SQS and you already are utilizing redis in some or the other way in your app, use JerryQuu. I built this tool for a small side project of mine and thought it would be cool for someone who doesn't want to get into SQS but wants to integrate a fast queuing system in their Node.js application

Installation

npm install jerryquu

Usage

Step by step

JerryQuu requires you to provide a client to handle redis operation. Make sure the redis client you choose supports redis's subscription pattern.

I personally recommend IORedis because it is easy to use and has a robust api.

  const IoRedis = require('ioredis');
  const Redis = new IoRedis(); // Redis Client 1 (for basic operations)
  const SubscriberRedis = new IoRedis(); // Redis Client 2 (for subscribing to events when messages are added)

JerryQuu relies on Nodemailer to send messages. It expects you to provide it with a transporter (we will be covering that below). It supports any kind of transporter you provide.

  const Nodemailer = require('nodemailer');
  const transport = Nodemailer.createTransport();

Import EmailQueue from JerryQuu

  const JerryQuu = require('jerryquu');
  const EmailQueue = JerryQuu.EmailQueue;

You can create subsequent number of instances of Email Queue for the number of queues you would need. One use case where you could need multiple instances is when you need multiple queues for eg. confirmation emails, password reset, etc.

  const confirmationEmailsQueue = new EmailQueue({
    redis: Redis,
    subscriber: SubscriberRedis,
    transport: transport
  });

  const passResetEmailQueue = new EmailQueue({
    redis: Redis,
    subscriber: SubscriberRedis,
    transport: transport
  });

After creating an instance of EmailQueue, you have to register a namespace. Namespace in JerryQuu is nothing but a variable key which we use to store your messages in redis. Per instance, you could only register one namespace. Because, it is ideal to have one namespace per instance to segregate messages properly and avoiding loss of data.

confirmationEmailsQueue.registerNamespace('confirmationEmail');
passResetEmailQueue.registerNamespace('passResetEmailQueue');

Now, the queue are ready to use. You can push a message like this myqueue.pushMessage(message) where message is basically the object you would generally pass to transport.sendMail(message)

  confirmationEmailsQueue.pushMessage({
    to: '[email protected]',
    from: '[email protected]',
    subject: 'Hey, thanks for registering!',
    html: '<b>Thank you for registering</b>',
    text: 'Thank you for registering'
  });

  passResetEmailQueue.pushMessage({
    to: '[email protected]',
    from: '[email protected]',
    subject: 'Password reset',
    html: '<b>Reset your password</b>',
    text: 'Reset your password'
  })

Basic Example

const EmailQueue = require('jerryquu').EmailQueue;
const Redis = require('ioredis');
const Nodemailer = require('Nodemailer');

const transport = Nodemailer.createTransport();

const queue = new EmailQueue({
  redis: new Redis(), // we use separate instance for doing operations such as get, set, lpush, rpush, etc
  subscriber: new Redis() // we use a separate instance subscriber for listening to events
  transport: transport // provide a nodemailer transport to send your emails
});

queue.registerNamespace('MyTestQueue'); // Registering a namespace helps to maintain a separate space for all your queue messages in the redis db

// Pushes your message to the queue
queue.pushMessage({
  to: '[email protected]',
  from: '[email protected]',
  subject: 'Test Mail',
  html: '<html>Hello world</html>',
  text: 'Hello world'
});

Custom handler

If you would like to handle the queue yourself, JerryQuu allows you to do that by passing a handler while registering a namespace

const handler = function (namespace, ctx) {
  const opts = ctx.opts;

  opts.redis.lrange(namespace, 0, -1, function (err, messages) {
    if (err) {
      throw err;
    }

    messages.forEach(function (message) {
    // make sure you parse the message because since we use a list to store the messages, we stringify the object before adding it to the queue
     message = JSON.parse(message);
     console.log(message);
    });
  });
}

myTestQueue.registerNamespace('customHandlerQueue', handler);

API references

EmailQueue

interface IEmailQueueOpts {
    /** A separate instance of redis to work with the queue */
    redis: RedisClient;
    /** A separate instance of redis to subscribe to events internally */
    subscriberRedis: RedisClient;
    /** Default retries is set to 4 */
    maxRetries?: number;
    /** Nodemailer Transport **/
    transport: Nodemailer.Transport;
}

interface IHandlerCtx {
  redis: RedisClient,
  transport: Nodemailer.transport
}

constructor(opts: IEmailQueueOpts);

queueHandler(namespace: string, ctx: { opts: IHandlerCtx } );

registerNamespace(namespace: string, handler?: queueHandler);

Feel free to contribute

I would like to have some of you guys contribute to this repo and improve this module altogether. Any issues, PR or any sort of contribution is appreciated :)

License

MIT

jerryquu's People

Contributors

buzzertech avatar dependabot-preview[bot] avatar

Stargazers

 avatar  avatar  avatar

Watchers

 avatar  avatar

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo 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.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.