npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2024 – Pkg Stats / Ryan Hefner

cumin

v0.0.5

Published

A minimalistic library for redis-based queues

Downloads

1

Readme

cumin

A minimal queue library for node.js, backed by redis. Meant for high-throughput queues. Built for graceful shutdown.

One way to build large applications is to not build large applications at all, and instead split the application into small discrete logical pieces. A common way to talk between such micro-applications is to use message queues.

Cumin is a library to put items into a queue, and to 'listen' to the queue for new entries. Ordinarily, you would use either one of the two methods in your application.

Inspired by Resque and Kue. Adapted to fit node's style of doing multiple things simultaneously in the same process, and to work for high-throughput message scenarios.

This library is in heavy use at Errorception.

Example

In app.js:

var cumin = require("cumin")();

// When, say, signup is complete...
cumin.enqueue("mailer", {
    to: "[email protected]",
    type: "signup"
});

In mailer.js:

var cumin = require("cumin")();

cumin.listen("mailer", function(mailJob, done) {
    // mailJob looks as follows:
    //
    // {
    //   to: "[email protected]",
    //   type: "signup"
    // }
    // 
    // Remember to call 'done' when you've finished the task.

    done();
});

An example can also be found in the examples directory. node examples/enqueue.js writes a messages every 10ms to a redis queue. node examples/listen.js pops from the queue and simulates a 1s long task with the message.

With async/await:

const cumin = require('cumin')();

await cumin.enqueue(...); // Await waits till enqueue is complete

cumin.listen('mailer', async mailJob => {   // Async function, no `done`.
    ...
});

Graceful shutdowns

One of the benefits of having a distributed setup like the one that cumin encourages, is that you get to shut down parts of your app so that you can do upgrades etc. without any visible impact to your users. However, because of node's eventing model, your .listener app might have already picked up multiple items from the queue and might still be processing them when you kill your app. To prevent loss of tasks that might be mid-flight, cuminadds a couple of graceful-shutdown features.

When you give either a SIGINT or a SIGTERM kill-signal to an app that is .listening to a queue, cumin will first stop accepting more items from redis. It will then wait for all in-flight jobs to complete. Only when all pending jobs have been completed does the app shut down. This ensures that you don't lose any items from your queue.

In case you want to bypass this check and kill the app anyway, you can simply send the SIGINT or SIGTERM signal a second time. The second signal will force a shutdown without regards for in-flight jobs.

Installation

$ npm install cumin

Usage

Initiialization

var cumin = require("cumin")(redisPort, redisHost, redisOptions)

Initializes the library. All parameters are optional, and default to localhost on the default redis port. These arguments are passed along to the node-redis module for connecting to redis.

cumin.enqueue(queueName, queueData, [cb])

Enqueues queueData into a queue with name queueName. You can optionally provide a callback to be called when the enqueue operation is complete. queueName should be a string following redis' key naming rules. queueData should be an object that will be JSON.stringifyied and put into the queue.

cumin.listen(queueName, function(queueItem, done) { ... });

Pops items out from the queueName queue. The callback will be called whenever an item is popped, and the queueItem will be passed in as an argument. The second argument to the callback is a function that should be called when the processing of the queue items is complete.

Pattern: Series of queues

Lets say you want to record some data to your DB. However, before you write to the DB, you want to apply a bunch of rules (for example, rate-limiting) where each rule is resource heavy. You could build each of these rules as separate applications, and simply pass messages between them. The advantage of this way of structuring your application is that each piece is versioned, deployed and scaled independent of the rest of the system - a much simpler problem to solve rather than figuring out how to scale the entire system.

var cumin = require("cumin")();

cumin.listen("queue1", function(queueItem, done) {
    if(weShouldProcess(queueItem)) {
        cumin.enqueue("queue2", queueItem);
    }

    done();
});

Now, some other application can .listen to queue2 and run its own filters and/or transforms, passing the data from queue to queue, until it finally gets written to the db. Since weShouldProcess is effectively the only thing this application does, it's easy to spin up more processes to share the load, or even run this across more physical computers, making scaling very easy. Also, in the event of a crash, the entire application doesn't crash - just one component - and messages intended for it remain recorded in redis for when it's back up. Heck, if one of your apps can be better implemented in a different language, that shouldn't be hard either!

Monitoring

cumin also stores some metadata about the queue activity in redis itself, so that you can monitor the health of the queue. Check out the cumin-monitor app for a real-time queue-monitoring tool that works with cumin.

License

MIT