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

ketama

v1.0.0

Published

A hash ring implementation using libketama-like hashing.

Downloads

295

Readme

ketama

Actions Status

Ketama is a JavaScript/TypeScript implementation of the libketama hash ring. The primary advantage of ketama-style hashing is that it reduces the amount of work which is shuffled to other servers when the hashring membership changes.

npm install --save ketama

Then go forth with confidence:

// alternatively: const { HashRing } = require('ketama');
import { HashRing } from 'ketama';

const ring = new HashRing();

ring.addNode('127.0.0.1'); // add with default weight
ring.addNode('127.0.0.2', 2); // weight of 2 = twice as likely to choose this one

export function onDoWork(input) {
  // hashes the input and choses a server based on it:
  const server = ring.getNode(input);
  doWorkOn(server);
}

export function doWorkOnMultipleServers(input) {
  // picks two "replica" servers from the ring to do work on
  for (const server of ring.getNodes(input, 2)) {
    doWorkOn(server);
  }
}

Table of Contents

HashRing([nodes], [hashFunction])

Creates a new HashRing, optionally with the initial set of nodes. The nodes can be either a string, or an object with a string property "key" which will be used internally to hash against, for example:

new HashRing(['127.0.0.1', { key: '127.0.0.2', port: 1337 }]);

When giving the nodes in the constructor, you can specify a weight by providing an object with the node and its weight. Weights are proportional; a node with a weight of 2 is twice as likely to be chosen than one with the default weight of 1. For example:

new HashRing([
  { node: '127.0.0.1', weight: 2 },
  { node: { key: '127.0.0.2', port: 1337 }, weight: 3
]);

Finally, you can also specify the hashing function to use. This can be either the name of an algorithm the require('crypto').createHash implements, or a custom function that returns an int32 given a Buffer. Defaults to sha1. For example:

new HashRing([], 'md5'); // hash with md5 instead
new HashRing([], buf => myCustomHash().readInt32BE()); // custom function

hashRing.addNode(node[, weight])

Adds a new node to the existing hashring. The node can be either a string, or an object with a string property "key" which will be used internally to hash against.

ring.addNode('127.0.0.1');
ring.addNode({ key: '127.0.0.2', port: 1337 });

You can optionally specify a weight as the second argument. Weights are proportional; a node with a weight of 2 is twice as likely to be chosen than one with the default weight of 1.

If the node already exists, it is replaced; for example, you can call addNode multiple times to update a node's weight.

hashRing.removeNode(node)

Removes a node previously added to the hash ring.

ring.removeNode('127.0.0.1');

No-op if the node is not in the ring.

hashRing.getNode(input)

Gets the node on which work should be done for the given input, which should be either a string or buffer. Returns the object or string originally given to addNode or new HashRing(), or returns undefined if the ring is empty.

const server = ring.getNode(inputData);
doWorkOn(server);

hashRing.getNodes(input, replicas)

Gets the "replicas" number of nodes that should handle the input, which should be either a string or buffer. The returned array length wiill equal the number of replicas, except if there are fewer nodes available than replicas requested, in which case all nodes are returned.

for (const server of ring.getNodes(input, 2)) {
  doWorkOn(server);
}