Skip to content

Lock

Contract

@modularityjs/lock defines the abstract LockService:

typescript
abstract class LockService {
  abstract acquire(key: string, ttlMs: number): Promise<boolean>;
  abstract release(key: string): Promise<void>;
}

Drivers

Memory (@modularityjs/lock-memory)

Single-process in-memory lock. For development and testing.

typescript
import { LockModule } from '@modularityjs/core';
import { LockMemoryModule } from '@modularityjs/lock-memory';

const modules = [LockModule, LockMemoryModule];

Redis (@modularityjs/lock-redis)

Distributed lock using SET NX PX with Lua-based safe release (owner token pattern). Requires @modularityjs/redis.

typescript
import { LockModule } from '@modularityjs/core';
import { LockRedisModule } from '@modularityjs/lock-redis';
import { RedisModule } from '@modularityjs/redis';

const modules = [
  RedisModule.forRoot({ host: 'localhost' }),
  LockModule,
  LockRedisModule,
];

Usage

typescript
import { Inject, Injectable, LockService } from '@modularityjs/core';

@Injectable()
class PaymentService {
  constructor(@Inject(LockService) private readonly lock: LockService) {}

  async processPayment(orderId: string): Promise<void> {
    const acquired = await this.lock.acquire(`payment:${orderId}`, 30_000);
    if (!acquired) {
      throw new Error('Payment already being processed');
    }

    try {
      // critical section
    } finally {
      await this.lock.release(`payment:${orderId}`);
    }
  }
}