@hocuspocus/common
Version:
shared code for multiple Hocuspocus packages
125 lines (124 loc) • 4.47 kB
TypeScript
import type { Extension, Hocuspocus, afterLoadDocumentPayload, afterStoreDocumentPayload, afterUnloadDocumentPayload, beforeBroadcastStatelessPayload, beforeUnloadDocumentPayload, onAwarenessUpdatePayload, onChangePayload, onConfigurePayload, onStoreDocumentPayload } from "@hocuspocus/server";
import { type ExecutionResult, type Lock, Redlock } from "@sesamecare-oss/redlock";
import type { Cluster, ClusterNode, ClusterOptions, RedisOptions } from "ioredis";
import RedisClient from "ioredis";
export type RedisInstance = RedisClient | Cluster;
export interface Configuration {
/**
* Redis port
*/
port: number;
/**
* Redis host
*/
host: string;
/**
* Redis Cluster
*/
nodes?: ClusterNode[];
/**
* Duplicate from an existed Redis instance
*/
redis?: RedisInstance;
/**
* Redis instance creator
*/
createClient?: () => RedisInstance;
/**
* Options passed directly to Redis constructor
*
* https://github.com/luin/ioredis/blob/master/API.md#new-redisport-host-options
*/
options?: ClusterOptions | RedisOptions;
/**
* An unique instance name, required to filter messages in Redis.
* If none is provided an unique id is generated.
*/
identifier: string;
/**
* Namespace for Redis keys, if none is provided 'hocuspocus' is used
*/
prefix: string;
/**
* The maximum time for the Redis lock in ms (in case it can’t be released).
*/
lockTimeout: number;
/**
* A delay before onDisconnect is executed. This allows last minute updates'
* sync messages to be received by the subscription before it's closed.
*/
disconnectDelay: number;
}
export declare class Redis implements Extension {
/**
* Make sure to give that extension a higher priority, so
* the `onStoreDocument` hook is able to intercept the chain,
* before documents are stored to the database.
*/
priority: number;
configuration: Configuration;
redisTransactionOrigin: string;
pub: RedisInstance;
sub: RedisInstance;
instance: Hocuspocus;
redlock: Redlock;
locks: Map<string, {
lock: Lock;
release?: Promise<ExecutionResult>;
}>;
messagePrefix: Buffer;
private pendingAfterStoreDocumentResolves;
constructor(configuration: Partial<Configuration>);
onConfigure({ instance }: onConfigurePayload): Promise<void>;
private getKey;
private pubKey;
private subKey;
private lockKey;
private encodeMessage;
private decodeMessage;
/**
* Once a document is loaded, subscribe to the channel in Redis.
*/
afterLoadDocument({ documentName, document, }: afterLoadDocumentPayload): Promise<unknown>;
/**
* Publish the first sync step through Redis.
*/
private publishFirstSyncStep;
/**
* Let’s ask Redis who is connected already.
*/
private requestAwarenessFromOtherInstances;
/**
* Before the document is stored, make sure to set a lock in Redis.
* That’s meant to avoid conflicts with other instances trying to store the document.
*/
onStoreDocument({ documentName }: onStoreDocumentPayload): Promise<void>;
/**
* Release the Redis lock, so other instances can store documents.
*/
afterStoreDocument({ documentName, socketId, }: afterStoreDocumentPayload): Promise<void>;
/**
* Handle awareness update messages received directly by this Hocuspocus instance.
*/
onAwarenessUpdate({ documentName, awareness, added, updated, removed, document, }: onAwarenessUpdatePayload): Promise<number | undefined>;
/**
* Handle incoming messages published on subscribed document channels.
* Note that this will also include messages from ourselves as it is not possible
* in Redis to filter these.
*/
private handleIncomingMessage;
/**
* if the ydoc changed, we'll need to inform other Hocuspocus servers about it.
*/
onChange(data: onChangePayload): Promise<any>;
/**
* Delay unloading to allow syncs to finish
*/
beforeUnloadDocument(data: beforeUnloadDocumentPayload): Promise<void>;
afterUnloadDocument(data: afterUnloadDocumentPayload): Promise<void>;
beforeBroadcastStateless(data: beforeBroadcastStatelessPayload): Promise<number>;
/**
* Kill the Redlock connection immediately.
*/
onDestroy(): Promise<void>;
}