@solid/community-server
Version:
Community Solid Server: an open and modular implementation of the Solid specifications
99 lines (98 loc) • 4.71 kB
TypeScript
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;
}