UNPKG

@solid/community-server

Version:

Community Solid Server: an open and modular implementation of the Solid specifications

99 lines (98 loc) 4.71 kB
import type { ResourceIdentifier } from '../../http/representation/ResourceIdentifier'; import type { Finalizable } from '../../init/final/Finalizable'; import type { Initializable } from '../../init/Initializable'; import type { AttemptSettings } from '../LockUtils'; import type { PromiseOrValue } from '../PromiseUtil'; import type { ReadWriteLocker } from './ReadWriteLocker'; import type { ResourceLocker } from './ResourceLocker'; export interface RedisSettings { namespacePrefix?: string; username?: string; password?: string; db?: number; } /** * A Redis Locker that can be used as both: * * a Read Write Locker that uses a (single) Redis server to store the locks and counts. * * a Resource Locker that uses a (single) Redis server to store the lock. * This solution should be process-safe. The only references to locks are string keys * derived from identifier paths. * * The Read Write algorithm roughly goes as follows: * * Acquire a read lock: allowed as long as there is no write lock. On acquiring the read counter goes up. * * Acquire a write lock: allowed as long as there is no other write lock AND the read counter is 0. * * Release a read lock: decreases the read counter with 1 * * Release a write lock: unlocks the write lock * * The Resource locking algorithm uses a single mutex/lock. * * All operations, such as checking for a write lock AND read count, are executed in a single Lua script. * These scripts are used by Redis as a single new command. * Redis executes its operations in a single thread, as such, each such operation can be considered atomic. * * The operation to (un)lock will always resolve with either 1/OK/true if succeeded or 0/false if not succeeded. * Rejection with errors will be happen on actual failures. Retrying the (un)lock operations will be done by making * use of the LockUtils' {@link retryFunctionUntil} function. * * * @see [Redis Commands documentation](https://redis.io/commands/) * * @see [Redis Lua scripting documentation](https://redis.io/docs/manual/programmability/) * * @see [ioredis Lua scripting API](https://github.com/luin/ioredis#lua-scripting) */ export declare class RedisLocker implements ReadWriteLocker, ResourceLocker, Initializable, Finalizable { protected readonly logger: import("global-logger-factory").Logger<unknown>; private readonly redis; private readonly redisRw; private readonly redisLock; private readonly attemptSettings; private readonly namespacePrefix; private finalized; /** * Creates a new RedisClient * * @param redisClient - Redis connection string of a standalone Redis node * @param attemptSettings - Override default AttemptSettings * @param redisSettings - Addition settings used to create the Redis client or to interact with the Redis server */ constructor(redisClient?: string, attemptSettings?: AttemptSettings, redisSettings?: RedisSettings); /** * Generate and return a RedisClient based on the provided string * * @param redisClientString - A string that contains either a host address and a * port number like '127.0.0.1:6379' or just a port number like '6379'. */ private createRedisClient; /** * Create a scoped Redis key for Read-Write locking. * * @param identifier - The identifier object to create a Redis key for * * @returns A scoped Redis key that allows cleanup afterwards without affecting other keys. */ private getReadWriteKey; /** * Create a scoped Redis key for Resource locking. * * @param identifier - The identifier object to create a Redis key for * * @returns A scoped Redis key that allows cleanup afterwards without affecting other keys. */ private getResourceKey; /** * Wrapper function for all (un)lock operations. If the `fn()` resolves to false (after applying * {@link fromResp2ToBool}, the result will be swallowed. When `fn()` resolves to true, this wrapper * will return true. Any error coming from `fn()` will be thrown. * * @param fn - The function reference to swallow false from. */ private swallowFalse; withReadLock<T>(identifier: ResourceIdentifier, whileLocked: () => PromiseOrValue<T>): Promise<T>; withWriteLock<T>(identifier: ResourceIdentifier, whileLocked: () => PromiseOrValue<T>): Promise<T>; acquire(identifier: ResourceIdentifier): Promise<void>; release(identifier: ResourceIdentifier): Promise<void>; initialize(): Promise<void>; finalize(): Promise<void>; /** * Remove any lock still open */ private clearLocks; }