UNPKG

hamok

Version:

Lightweight Distributed Object Storage on RAFT consensus algorithm

300 lines 12.2 kB
import { EventEmitter } from 'events'; import { RaftEngine, RaftEngineConfig } from './raft/RaftEngine'; import { HamokMessage } from './messages/HamokMessage'; import { LogEntry } from './raft/LogEntry'; import { RaftStateName } from './raft/RaftState'; import { HamokMap } from './collections/HamokMap'; import { HamokConnectionConfig } from './collections/HamokConnection'; import { HamokCodec } from './common/HamokCodec'; import { BaseMap } from './collections/BaseMap'; import { HamokGrid } from './HamokGrid'; import { HamokQueue } from './collections/HamokQueue'; import { HamokEmitter, HamokEmitterEventMap } from './collections/HamokEmitter'; import { RaftLogs } from './raft/RaftLogs'; import { HamokRecord, HamokRecordObject } from './collections/HamokRecord'; import { RemoteMap } from './collections/RemoteMap'; import { HamokRemoteMap } from './collections/HamokRemoteMap'; export type HamokJoinProcessParams = { /** * Timeout in milliseconds for fetching the remote peers. * * DEFAULT: 5000 */ fetchRemotePeerTimeoutInMs?: number; /** * The maximum number of retries for fetching the remote peers. * -1 - means infinite retries * 0 - means no retries * * DEFAULT: 3 */ maxRetry?: number; }; export type HamokObjectConfig<AppData extends Record<string, unknown> = Record<string, unknown>> = { /** * Indicate if the Hamok should stop automatically when there are no remote peers. */ /** * The timeout in milliseconds for waiting for the remote storage state. * * DEFAULT: 1000 */ remoteStorageStateWaitingTimeoutInMs: number; /** * A custom appData object to be used by the application utilizes Hamok. */ appData?: AppData; }; /** * Configuration settings for the Hamok constructor, extending RaftEngineConfig and HamokConfig. */ export type HamokConfig<AppData extends Record<string, unknown> = Record<string, unknown>> = RaftEngineConfig & Partial<HamokObjectConfig<AppData>> & { /** * Optional. The expiration time in milliseconds for log entries. * Log entries older than this duration may be purged. * Only applicable when a custom RaftLogs is NOT provided. * * DEFAULT: 300000 (5 minutes) */ logEntriesExpirationTimeInMs?: number; /** * Optional. A map of initial log entries to be used by the system. * The key is the log index, and the value is the LogEntry. */ initialLogEntries?: Map<number, LogEntry>; /** * The period in milliseconds to send notifications to the source(s) about ongoing requests * to prevent timeouts. This is applicable when a requestId is explicitly added to the ongoing * requests set by calling addOngoingRequestId(). Notifications stop when removeOngoingRequestId * is called. It is crucial to call this explicitly in any case as comlink does not handle * automatically stopping notifications for explicitly postponed requests. */ ongoingRequestsSendingPeriodInMs: number; /** * Optional. A custom implementation of RaftLogs to store log entries. */ raftLogs?: RaftLogs; }; export type HamokConnectionBuilderBaseConfig = Pick<HamokConnectionConfig, 'requestTimeoutInMs' | 'remoteStorageStateWaitingTimeoutInMs'> & { maxOutboundMessageKeys: number; maxOutboundMessageValues: number; }; /** * Configuration settings for building a Hamok record. */ export type HamokRecordBuilderConfig<T extends HamokRecordObject> = Partial<HamokConnectionBuilderBaseConfig> & { /** * The unique identifier for the record. */ recordId: string; /** * Optional. A map of payload codecs for encoding and decoding record properties. * The key is a property of the record, and the value is a codec for that property. */ payloadCodecs?: Map<keyof T, HamokCodec<T[keyof T], string>>; /** * Optional. An initial object to be used as the base state of the record. */ initialObject?: Partial<T>; /** * Optional. A function to determine equality between two values. * Used for custom equality checking. */ equalValues?: (a: T[keyof T], b: T[keyof T]) => boolean; }; /** * Configuration settings for building a Hamok map. */ export type HamokMapBuilderConfig<K, V> = Partial<HamokConnectionBuilderBaseConfig> & { /** * The unique identifier for the map. */ mapId: string; /** * Optional. A codec for encoding and decoding keys in the map. */ keyCodec?: HamokCodec<K, Uint8Array>; /** * Optional. A codec for encoding and decoding values in the map. */ valueCodec?: HamokCodec<V, Uint8Array>; /** * Optional. A base map to be used as the initial state of the map. */ baseMap?: BaseMap<K, V>; /** * Optional. A function to determine equality between two values. * Used for custom equality checking. */ equalValues?: (a: V, b: V) => boolean; }; /** * Configuration settings for building a Hamok remote map. */ export type HamokRemoteMapBuilderConfig<K, V> = Omit<HamokMapBuilderConfig<K, V>, 'baseMap'> & { /** * The remote map to be used to store the data. */ remoteMap: RemoteMap<K, V>; /** * Flag indicate if the events should be emitted by the event emitter or not. * It also reduces the communication overhead if not needed, as for emitting events * the leader should send a message to all followers to emit an event. * In such case when it's not necessary (like cache maintenance) it can be disabled. */ noEvents?: boolean; }; /** * Configuration settings for building a Hamok queue. */ export type HamokQueueBuilderConfig<T> = Partial<HamokConnectionBuilderBaseConfig> & { /** * The unique identifier for the queue. */ queueId: string; /** * Optional. A codec for encoding and decoding items in the queue. */ codec?: HamokCodec<T, Uint8Array>; /** * Optional. A base map to be used as the initial state of the queue. */ baseMap?: BaseMap<number, T>; }; /** * Configuration settings for building a Hamok emitter. */ export type HamokEmitterBuilderConfig<T extends HamokEmitterEventMap> = Partial<HamokConnectionBuilderBaseConfig> & { /** * The unique identifier for the emitter. */ emitterId: string; /** * Optional. A map of payload codecs for encoding and decoding event payloads. * The key is an event type, and the value is a codec for that event type. */ payloadsCodec?: Map<keyof T, { encode: (...args: unknown[]) => string; decode: (data: string) => unknown[]; }>; /** * Optional.Indicate if the emitter automatically cleans up and unssubscribes from events * remote peers gone offline. Only leader endpoint does this. */ autoClean?: boolean; }; export type HamokFetchRemotePeersResponse = { remotePeers: string[]; minNumberOfLogs?: number; smallestCommitIndex?: number; }; export type HamokEventMap = { follower: []; candidate: []; leader: []; message: [message: HamokMessage]; 'remote-peer-joined': [peerId: string]; 'remote-peer-left': [peerId: string]; 'leader-changed': [leaderId: string | undefined, prevLeader: string | undefined]; 'state-changed': [newState: RaftStateName, prevState: RaftStateName]; commit: [commitIndex: number, message: HamokMessage]; heartbeat: []; error: [error: Error]; 'no-heartbeat-from': [remotePeerId: string]; 'unsynced-peer': [remotePeerId: string]; joined: []; rejoining: []; left: []; close: []; }; export type HamokStorageType = 'record' | 'map' | 'remoteMap' | 'emitter' | 'queue'; export type HamokSharedStorageMap = HamokMap<string, { type: HamokStorageType; count: number; }>; export declare interface Hamok { on<U extends keyof HamokEventMap>(event: U, listener: (...args: HamokEventMap[U]) => void): this; once<U extends keyof HamokEventMap>(event: U, listener: (...args: HamokEventMap[U]) => void): this; emit<U extends keyof HamokEventMap>(event: U, ...args: HamokEventMap[U]): boolean; } export declare class Hamok<AppData extends Record<string, unknown> = Record<string, unknown>> extends EventEmitter { readonly config: HamokObjectConfig<AppData>; readonly raft: RaftEngine; readonly storages: Map<string, HamokRecord<any> | HamokMap<any, any> | HamokQueue<any> | HamokRemoteMap<any, any> | HamokEmitter<any, Record<string, unknown>>>; private _closed; private _run; private _raftTimer?; private readonly _remoteHeartbeats; private readonly _codec; readonly grid: HamokGrid; private _joining?; constructor(providedConfig?: Partial<HamokConfig<AppData>>); get appData(): AppData; get localPeerId(): string; get remotePeerIds(): ReadonlySet<string>; get leader(): boolean; get ready(): Promise<this>; get state(): RaftStateName; get run(): boolean; get activeRemoteHeartbeats(): IterableIterator<string>; get closed(): boolean; close(): void; get stats(): { /** * Number of requests sent out from the grid, but waiting for response from remote peer */ numberOfPendingRequests: number; /** * Number of requests received by this peer and queued for processing (for example requests to be waited to be committed by the leader) */ numberOfOngoingRequests: number; /** * Number of responses received by this peer and queued for processing as the response were chunked */ numberOfPendingResponses: number; /** * Number of remote peers this peer is connected to */ numberOfRemotePeers: number; /** * Number of bytes used by the raft logs in memory */ raftLogsBytesInMemory: number; }; private _acceptCommit; addRemotePeerId(remoteEndpointId: string): void; removeRemotePeerId(remotePeerId: string): void; private _acceptLeaderChanged; /** * Wait until the commit head (the most recent spread commit by the leader) is reached * @returns */ waitUntilCommitHead(): Promise<void>; waitUntilLeader(timeoutInMs?: number): Promise<void>; createMap<K, V>(options: HamokMapBuilderConfig<K, V>): HamokMap<K, V>; getOrCreateMap<K, V>(options: HamokMapBuilderConfig<K, V>, callback?: (alreadyExisted: boolean) => void): HamokMap<K, V>; createRemoteMap<K, V>(options: HamokRemoteMapBuilderConfig<K, V>): HamokRemoteMap<K, V>; getOrCreateRemoteMap(options: HamokRemoteMapBuilderConfig<unknown, unknown>, callback?: (alreadyExisted: boolean) => void): HamokRemoteMap<unknown, unknown>; createRecord<T extends HamokRecordObject>(options: HamokRecordBuilderConfig<T>): HamokRecord<T>; getOrCreateRecord<T extends HamokRecordObject>(options: HamokRecordBuilderConfig<T>, callback?: (alreadyExisted: boolean) => void): HamokRecord<T>; createQueue<T>(options: HamokQueueBuilderConfig<T>): HamokQueue<T>; getOrCreateQueue<T>(options: HamokQueueBuilderConfig<T>, callback?: (alreadyExisted: boolean) => void): HamokQueue<T>; createEmitter<T extends HamokEmitterEventMap, M extends Record<string, unknown> = Record<string, unknown>>(options: HamokEmitterBuilderConfig<T>): HamokEmitter<T, M>; getOrCreateEmitter<T extends HamokEmitterEventMap>(options: HamokEmitterBuilderConfig<T>, callback?: (alreadyExisted: boolean) => void): HamokEmitter<T>; submit(entry: HamokMessage): Promise<void>; accept(message: HamokMessage, commitIndex?: number): void; leave(): Promise<void>; join(params?: HamokJoinProcessParams): Promise<void>; private _join; private _startRaftEngine; private _stopRaftEngine; private _sendEndpointNotification; private _acceptGridMessage; broadcastEndpointNotification(): void; private _emitMessage; private _createStorageConnection; private _acceptKeepAliveHamokMessage; private _checkRemoteHeartbeats; private _sendJoinMsg; } //# sourceMappingURL=Hamok.d.ts.map