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 🙏

© 2025 – Pkg Stats / Ryan Hefner

distrilock

v1.0.2

Published

[![codecov](https://codecov.io/gh/jlucaso1/distrilock/graph/badge.svg)](https://codecov.io/gh/jlucaso1/distrilock) [![NPM Version](https://img.shields.io/npm/v/distrilock.svg)](https://www.npmjs.com/package/distrilock) [![License: MIT](https://img.shields

Readme

distrilock: Distributed Locks with Redis in TypeScript

codecov NPM Version License: MIT

A TypeScript implementation of the Redlock algorithm for distributed locks using Redis. This library helps manage resources in a mutually exclusive way across different processes or services.

It is based on the concepts outlined in the official Redis documentation: Distributed Locks with Redis.

Features

  • Implements the Redlock algorithm for fault-tolerant distributed locking.
  • Supports multiple Redis instances for high availability.
  • Safe lock release using Lua scripts.
  • Automatic retry mechanism with jitter for lock acquisition.
  • Lock extension capability.
  • Clean, modern TypeScript API.

Installation

Assuming the package is published as distrilock (as per package.json):

bun install distrilock ioredis
# or
npm install distrilock ioredis
# or
yarn add distrilock ioredis

This library requires ioredis as a peer dependency for Redis communication.

Basic Usage

Here's a simple example of how to acquire and release a lock:

import type { RedisOptions } from "ioredis";
import { Redlock, type AcquiredLock } from "distrilock"; // Assuming published as 'distrilock'

const delay = (ms: number) => new Promise(resolve => setTimeout(resolve, ms));

async function example() {
  // Configuration for your Redis master instances
  const redisConfigs: RedisOptions[] = [
    { host: 'localhost', port: 7000 },
    { host: 'localhost', port: 7001 },
    { host: 'localhost', port: 7002 },
    // Add more Redis master instances if your setup requires (e.g., N=5)
  ];

  // Initialize Redlock
  // Ensure you have at least N/2 + 1 Redis master instances running.
  // These should be independent masters, not replicas, for Redlock's fault tolerance.
  const redlock = new Redlock(redisConfigs, {
    retryCount: 3,    // Number of times to retry locking (default: 3)
    retryDelay: 200,  // Base delay (ms) between retries (default: 200)
    retryJitter: 50,  // Max random jitter (ms) to add to retryDelay (default: 100)
    clockDriftFactor: 0.01, // Factor for clock drift (default: 0.01)
  });

  const resourceName = 'my-critical-resource';
  const lockTTL = 10000; // Lock time-to-live: 10 seconds

  let lock: AcquiredLock | null = null;
  try {
    console.log(`Attempting to acquire lock for "${resourceName}"...`);
    // Acquire the lock
    lock = await redlock.acquire(resourceName, lockTTL);
    console.log(`Lock acquired for "${resourceName}"! Effective validity: ${lock.validity}ms. Value: ${lock.value}`);

    // --- Perform critical work that requires the lock ---
    console.log("Performing critical work...");
    // Simulate work, ensuring it's less than lock.validity
    await delay(Math.min(5000, lock.validity / 2));
    console.log("Critical work finished.");

    // --- Optionally extend the lock if more time is needed ---
    /*
    if (lock) { // Check if lock is still held
      const newTTL = 15000; // Extend for another 15 seconds from now
      try {
        console.log("Attempting to extend lock...");
        lock = await redlock.extend(lock, newTTL);
        console.log(`Lock extended! New effective validity: ${lock.validity}ms.`);
        await delay(Math.min(7000, lock.validity / 2)); // Simulate more work
        console.log("Extended work finished.");
      } catch (extendError) {
        console.error(`Failed to extend lock: ${(extendError as Error).message}`);
        // Handle failure to extend: the original lock might still be valid or might have expired.
        // The application must decide how to proceed.
      }
    }
    */

  } catch (error) {
    console.error(`Failed to acquire lock or error during critical work: ${(error as Error).message}`);
    // Handle lock acquisition failure or errors during the critical section
  } finally {
    if (lock) {
      console.log(`Releasing lock for "${resourceName}"...`);
      try {
        await lock.release(); // Use the release method on the lock object
        console.log("Lock released.");
      } catch (releaseError) {
        console.error(`Error releasing lock: ${(releaseError as Error).message}`);
      }
    }
    // Close all Redis connections when Redlock is no longer needed
    await redlock.quit();
    console.log("Redlock connections closed.");
  }
}

example().catch(console.error);

Understanding Redlock

It's highly recommended to understand the principles, guarantees, and trade-offs of the Redlock algorithm before using this library in production. Please refer to the official Redis documentation for a detailed explanation:

Pay close attention to sections on safety, liveness, fault tolerance, and the discussion on clock drift and fencing tokens.

API

(You would typically expand this section with more details about the Redlock class methods and options, and the AcquiredLock interface.)

new Redlock(clientConfigs, options?)

  • clientConfigs: An array of ioredis.Redis instances or ioredis.RedisOptions.
  • options:
    • retryCount?: number (default: 3)
    • retryDelay?: number (ms, default: 200)
    • retryJitter?: number (ms, default: 100)
    • clockDriftFactor?: number (default: 0.01)

redlock.acquire(resource, ttl, options?)

  • resource: string - Identifier for the resource to lock.
  • ttl: number (ms) - Time-to-live for the lock.
  • options?:
    • retryCount?: number
    • retryDelay?: number
    • retryJitter?: number
    • lockValue?: string (internal use, mainly for extensions)
  • Returns: Promise<AcquiredLock>

lock.release()

  • Releases the acquired lock.
  • Returns: Promise<void>

redlock.extend(lock, ttl)

  • lock: AcquiredLock - The currently held lock to extend.
  • ttl: number (ms) - The new time-to-live from the moment of extension.
  • Returns: Promise<AcquiredLock>

redlock.quit()

  • Closes all underlying Redis connections.
  • Returns: Promise<void>

Development & Testing

This project uses Bun for development and testing.

To install dependencies:

bun install

To run tests (requires Redis instances as defined in docker-compose.yml):

# Start Redis instances in another terminal
docker-compose up

# Run tests
bun test

License

MIT


This project was created using bun init. Bun is a fast all-in-one JavaScript runtime.