synapse-storage
Version:
Набор инструментов для управления состоянием и апи-запросами
98 lines (97 loc) • 4.74 kB
TypeScript
interface WorkerChannelMessage<T = unknown> {
channelName?: string;
type: string;
payload?: T;
senderId: string;
targetId?: string;
timestamp: number;
op?: string;
requestId?: string;
error?: string;
}
type MessageHandler<T> = (message: WorkerChannelMessage<T>) => void | Promise<void>;
type SyncRequestHandler<T> = () => T | Promise<T>;
/** Вид воркера: 'relay' — stateless pub/sub (по умолчанию), 'store' — stateful key-value стор с RPC. */
export type WorkerKind = 'relay' | 'store';
interface WorkerChannelOptions {
workerUrl?: string | URL;
/** Вид воркера. По умолчанию 'relay' (обратная совместимость с middleware). */
workerKind?: WorkerKind;
/** Таймаут RPC-запроса ({@link WorkerChannel.request}) и requestSync, мс. По умолчанию 1000. */
requestTimeoutMs?: number;
}
/**
* Транспорт поверх SharedWorker/MessagePort, зеркалящий публичный API
* SyncBroadcastChannel. Позволяет middleware и адаптерам хранилища использовать
* оба класса взаимозаменяемо.
*
* Мультиплексирование: N хранилищ делят ОДИН SharedWorker и разделяются по
* channelName. Если SharedWorker недоступен — прозрачно делегируем в
* SyncBroadcastChannel. Если недоступен и BroadcastChannel — no-op (SSR-safe).
*/
export declare class WorkerChannel<T = unknown> {
private readonly channelName;
private readonly tabId;
private messageHandlers;
private syncHandler?;
private readonly syncTimeoutMs;
private readonly workerKind;
private pendingSyncRequests;
private pendingRequests;
private mode;
private port?;
private fallback?;
private localStore?;
constructor(channelName: string, options?: WorkerChannelOptions);
/**
* Пытается создать SharedWorker и привязать порт. Конструктор `new SharedWorker`
* может БРОСИТЬ синхронно (CSP `worker-src` без `blob:` → SecurityError). В этом
* случае честно логируем и возвращаем false — вызывающий прозрачно уходит в фолбэк
* (BroadcastChannel в relay-режиме, in-process стор в store-режиме), а не роняет
* конструирование адаптера/middleware.
*
* @returns true если SharedWorker успешно подключён, иначе false (нужен фолбэк).
*/
private tryConnectSharedWorker;
/** Фактический режим транспорта (для честного `capabilities`/диагностики, R9). */
get transportMode(): 'worker' | 'fallback' | 'noop' | 'local';
private error;
private registerPort;
private handleMessage;
private handleError;
private safePostMessage;
private postMessage;
/**
* Подписка на сообщения канала
*/
subscribe(handler: MessageHandler<T>): () => boolean;
/**
* Установка обработчика запросов на синхронизацию
*/
setSyncHandler(handler: SyncRequestHandler<T>): void;
/**
* Отправка сообщения всем подписчикам
*/
broadcast(type: string, payload?: T): void;
/**
* Запрос синхронизации данных с других вкладок
*/
requestSync(): Promise<T | null>;
/**
* RPC-запрос к STORE-бэкенду (workerKind: 'store'). Отправляет операцию с уникальным
* requestId и резолвится ответом. По таймауту ({@link WorkerChannelOptions.requestTimeoutMs},
* по умолчанию 1000мс) — reject.
*
* В worker-режиме payload проходит structured clone через postMessage. В local-режиме
* мы клонируем payload/результат вручную — так и валидируется клонируемость, и данные
* изолируются (как через границу воркера).
*/
request<Res = unknown>(type: string, payload?: unknown): Promise<Res>;
/** Уведомляет соседние in-process экземпляры того же канала о мутации (кроме себя). */
private notifyLocalPeers;
/**
* Закрытие канала
*/
close(): void;
}
export {};