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

leverage

v0.1.3

Published

Leverage is a thin wrapper around the `redis` client that integrates your lua scripts as methods AND supports reliable and fault tolerant Pub/Sub on top of redis.

Downloads

16

Readme

leverage

Version npmBuild StatusDependenciesCoverage Status

Leverage is an abstraction on top of the fabulous redis client for Node.js. It makes it much easier to work with lua scripting in Redis as well as provide some some missing features in Redis through the power of lua scripting.

Installation

The package should be installed through npm, which is installed by default when you download node.js

npm install leverage --save

Usage

To introduce these methods, the module searches for a lua or leverage folder in the root of your application folder (which contains the node_modules folder that has this module installed). It only accepts files with a .lua extension. These files will be introduced as methods on the Leverage prototype. So if you have a hello.lua file in the leverage folder we will automatically make a leverage.hello() method.

Because we are introducing the scripts as methods in the Leverage.prototype there are a couple of names that blocked for usage or they would destroy the modules internals. We've made sure that most of internals of this module are namespaced user the _ property but there are however a couple methods exposed on the prototype:

  • _ Our private internal namespace for logic and options.
  • readyState Which indicates if everything is loaded correctly.
  • publish For our improved Pub/Sub.
  • subscribe For our improved Pub/Sub.
  • unsubscribe Unsubscribe from our Pub/Sub channel.
  • destroy For closing all used/wrapped Redis connections.
  • All EventEmitter methods and it's private properties

And just to be save, don't use methods that are prefixed with an underscore which will just protect you possible private node internals. Other then these properties and methods your save to anything you want as we will just remove all forbidden chars, numbers from your script name and transform it to lowercase.

To initialize the module you need to provide it with at least one active Redis connection:

var Leverage = require('leverage')
  , redis = require('redis').createClient();

var leverage = new Leverage(redis, { optional options });

If you want to leverage the improved Pub/Sub capabilities you should supply 2 different clients. 1 connection will be used to publish the messages and execute the commands while the other connection will be used to subscribe and there for block the connection for writing.

var Leverage = require('leverage')
  , pub = require('redis').createClient()
  , sub = require('redis').createClient();

var leverage = new Leverage(pub, sub, { optional options });

It might be possible that you want to add scripts from a different folder then our pre-defined folder locations. We've added a Leverage.introduce which you can use to add scripts. The scripts that are added should be added to the Leverage.scripts array and you should add the scripts BEFORE you construct a new Leverage instance.

var Leverage = require('leverage');

//
// Give the method the path of your lua files and the object or in our case the
// prototype where you want to introduce the methods.
//
var scripts = Leverage.introduce('/path/to/your/custom/directory', Leverage.prototype);

//
// IMPORTANT: Add the returned array of added scripts to our Leverage.scipts as
// are checked during the bootstapping of the Leverage instance.
//
Leverage.scripts = Leverage.scripts.concat(scripts);

FYI: The Leverage.introduce methods returns an array with following data structure:

{
  name: 'hello',
  args: {
    KEYS: 2,
    ARGV: 2
  },
  path: '/usr/wtf/path/to/file/hello.lua',
  code: 'local foo = KEYS[0]\nlocal bar = KEYS[1] .. etc ..'
}

We we attempt to load in the lua scripts in to the Redis server we attempt to parse the script to automatically detect how many keys that should be send to the server. If your code isn't to magical it should just parse it correctly and set the amount of KEYS and ARGV's of your script. There might be edge cases where you are iterating over the keys and args or we just fail to correctly parse your lua code because you a frigging lua wizard. For these edge cases you can supply every generated method with a number. This number should represent the amount of KEYS you are sending to your scripts.

leverage.customscript(2, 'KEY1', 'KEY2', 'ARGS', 'ARGS', fn);

But doing this every time can be a bit wasteful that's why you can also just tell us once and the module will memorize it for you so all other calls will just use the same amount of keys.

leverage.customscript(2);
leverage.otherscript(10);
leverage.anotherscript(3);

//
// You can now call the scripts without the needed key amount argument.
//
leverage.customscript('KEY1', 'KEY2', 'ARGS', 'ARGS', fn);

Options

The following options are available, most of these apply to the improved Pub/Sub system.

Pub/Sub

Our Pub/Sub wrapper provides a reliable Pub/Sub implementation on top of the fire and forget Pub/Sub implementation of redis. This is done by leveraging (ooh see what I did there ;)) lua scripts.

leverage.publish(channel, message, [callback])

Publishing is as easy as:

leverage.publish(channel, message, function (err, id) {
  // optional error and the unique id of the message
});

The callback is optional, but I would advice you to use it so you know which id your message has and if it was send without any issues. When you publish a message the following events take place:

  1. We increase a unique counter for the given channel so we have a unique id for the message.
  2. Create a packet which contains the message and the id of the message.
  3. The package is stored as simple key/value where they key contains the channel and the unique id.
  4. The packet is published to the channel.

leverage.subscribe(channel, { options })

The subscription command has a bit of different syntax then you are used to. It accepts a second argument which can be used to configure the reliablity of the Pub/Sub channel:

leverage.subscribe('channel', { options });

The subscription command can be configured with:

When you join a channel the follwing events take place:

  1. The current id is retrieved.
  2. Older messages are retrieved if needed
  3. A packet is send back which contains all fetched messages and the current id.

Once you are subscribed to a channel the messages will be emitted on the leverage instance. There are a couple of different events emitted:

  • <channel>::message A message has been received.
  • <channel>::bailout We've received an error and are bailing out.
  • <channel>::error The channel received an error.
  • <channel>::online The channel has started processing messages.
  • <channel>::unsubscribe The channel has been unsubscribed.

<channel> is the name of the channel that you've subscribed to.

leverage.subscribe('foo').on('foo::message', function onmessage(message, id) {
  console.log('Received the following message: ', message);
  console.log('The message had the following id: ', id);
});

leverage.on('foo::bailout', function bailout(e) {
  console.log('The following error caused the bailout', e);
});

leverage.on('foo::error', function error(e) {
  console.log('We received an error', e);
  console.log('This was emitted before a bailout, if bailouts were enabled');
});

leverage.unsubscribe(channel, [callback])

Unsubscribe from the channel, nothing special here.

leverage.unsubscribe('foo', function unsubscribed(err) {
 ..
});

This also triggers the <channel>::unsubscribe event.

Note:

All these operations happen atomicly and are namespaced under the namespace that you configured Leverage with. So you cannot (and should not) publish to channels that are not wrapper by Leverage.

LICENSE

MIT