/** * Sync scheduling policy. * * ## What it controls * * A {@link SyncPolicy} has two halves: * - **push** ({@link PushPolicy}) — when dirty local writes are sent to the remote. * - **pull** ({@link PullPolicy}) — when the remote is polled for new data. * * ## Choosing a policy * * The right policy depends on the backend's operational characteristics: * * | Backend type | Recommended policy | * |---|---| * | Per-record (DynamoDB, S3, IDB) | {@link INDEXED_STORE_POLICY} — `on-change` push, `manual` pull | * | Bundle (Drive, WebDAV, Git) | {@link POD_STORE_POLICY} — `debounce` push, `interval` pull | * * Consumers can override via `createNoydb({ syncPolicy: { ... } })`: * * ```ts * const db = await createNoydb({ * store: jsonFile({ dir: './data' }), * syncPolicy: { * push: { mode: 'debounce', debounceMs: 5_000 }, * pull: { mode: 'on-focus' }, * }, * }) * ``` * * ## Scheduler lifecycle * * {@link SyncScheduler} owns all timers, debounce logic, and browser lifecycle * hooks (`visibilitychange`, `pagehide`, `beforeExit`). Call `scheduler.start()` * after opening a vault and `scheduler.stop()` when closing it. The scheduler * delegates actual push/pull work to {@link SyncSchedulerCallbacks} provided * by the {@link SyncEngine}. * * @module */ /** * When push operations are triggered automatically. * * - `'manual'` — only on explicit `sync.push()` calls. * - `'on-change'` — immediately after every local write (respecting `minIntervalMs`). * - `'debounce'` — after `debounceMs` of inactivity following a write. * - `'interval'` — on a fixed timer regardless of writes. */ export type PushMode = 'manual' | 'on-change' | 'debounce' | 'interval'; /** * When pull operations are triggered automatically. * * - `'manual'` — only on explicit `sync.pull()` calls. * - `'interval'` — on a fixed `intervalMs` timer. * - `'on-focus'` — when the browser tab regains visibility. */ export type PullMode = 'manual' | 'interval' | 'on-focus'; /** * Push half of a sync policy. Controls the trigger mode and timing guards * for outbound sync operations. */ export interface PushPolicy { /** Push trigger mode. */ readonly mode: PushMode; /** Debounce delay in ms. Only used when `mode: 'debounce'`. Default: 30_000. */ readonly debounceMs?: number; /** Interval in ms between automatic pushes. Used by `'interval'` and as floor for `'debounce'`. */ readonly intervalMs?: number; /** * Hard floor between pushes regardless of mode. Prevents burst writes * from hammering the remote. Default: 0 (no floor). */ readonly minIntervalMs?: number; /** * Force a push on page unload (`pagehide` / `visibilitychange → hidden`) * in browsers, `beforeExit` in Node. Default: true for non-manual modes. */ readonly onUnload?: boolean; } /** * Pull half of a sync policy. Controls when and how often inbound sync * operations are triggered. */ export interface PullPolicy { /** Pull trigger mode. */ readonly mode: PullMode; /** Interval in ms between automatic pulls. Used by `'interval'` mode. Default: 60_000. */ readonly intervalMs?: number; } /** * Combined push + pull sync scheduling policy for a vault. * * Pass via `createNoydb({ syncPolicy })` to override the default policy * derived from the active store type. Pre-built defaults are available * as `INDEXED_STORE_POLICY` and `POD_STORE_POLICY`. */ export interface SyncPolicy { readonly push: PushPolicy; readonly pull: PullPolicy; } /** Default for per-record stores (DynamoDB, S3, file, IDB). */ export declare const INDEXED_STORE_POLICY: SyncPolicy; /** Default for bundle stores (Drive, WebDAV, Git). */ export declare const POD_STORE_POLICY: SyncPolicy; /** @deprecated Use `POD_STORE_POLICY`. */ export declare const BUNDLE_STORE_POLICY: SyncPolicy; /** * Current operational state of the `SyncScheduler`. * * - `'idle'` — no pending or active sync operations. * - `'pending'` — local writes are queued, waiting for debounce/interval to fire. * - `'pushing'` — push in progress. * - `'pulling'` — pull in progress. * - `'error'` — last sync operation failed; `lastError` holds the cause. */ export type SyncSchedulerState = 'idle' | 'pending' | 'pushing' | 'pulling' | 'error'; /** * Snapshot of the sync scheduler's state, returned by `SyncScheduler.status`. * Safe to expose in a reactive UI status indicator. */ export interface SyncSchedulerStatus { readonly state: SyncSchedulerState; readonly lastPushAt: string | null; readonly lastPullAt: string | null; readonly lastError: Error | null; readonly pendingWrites: number; } /** * Callbacks injected into `SyncScheduler` by the SyncEngine. * * The scheduler owns timers and lifecycle hooks; it delegates actual push/pull * work to these callbacks to stay decoupled from the sync implementation. */ export interface SyncSchedulerCallbacks { push(): Promise; pull(): Promise; getDirtyCount(): number; } /** * Manages sync timing according to a `SyncPolicy`. * * The scheduler owns all timers and lifecycle hooks. It delegates actual * push/pull work to callbacks provided by the SyncEngine. */ export declare class SyncScheduler { private readonly policy; private readonly callbacks; private _state; private _lastPushAt; private _lastPullAt; private _lastError; private _lastPushTime; private debounceTimer; private pushIntervalTimer; private pullIntervalTimer; private readonly boundOnVisibilityChange; private readonly boundOnBeforeExit; private readonly boundOnPageHide; private started; constructor(policy: SyncPolicy, callbacks: SyncSchedulerCallbacks); /** Current scheduler status snapshot. */ get status(): SyncSchedulerStatus; /** Start the scheduler — registers timers, event listeners. */ start(): void; /** Stop the scheduler — clears timers, removes event listeners. */ stop(): void; /** * Notify the scheduler that a local write occurred. * For `on-change` mode: triggers immediate push (respecting minIntervalMs). * For `debounce` mode: resets the debounce timer. * For `manual` / `interval`: no-op. */ notifyChange(): void; /** Force an immediate push, bypassing the scheduler. */ forcePush(): Promise; /** Force an immediate pull, bypassing the scheduler. */ forcePull(): Promise; private executePush; private executePull; private resetDebounce; private scheduleDebounce; private shouldRegisterUnload; private handleVisibilityChange; private handlePageHide; private handleBeforeExit; private handleFocusPull; private fireUnloadPush; }