UNPKG

homebridge

Version:
115 lines 5.43 kB
/** * Server Lifecycle Manager * * Handles start(), stop(), cleanup(), waitForServerReady(), * runServer(), createServerNodeWithRecovery(), and storage setup. */ import type { ServerNode } from '@matter/main'; import type { MatterAccessoryCache } from '../accessoryCache.js'; import type { MatterServerConfig } from '../sharedTypes.js'; import type { CommissioningDeps, CommissioningManager } from './CommissioningManager.js'; import type { FabricManager } from './FabricManager.js'; import { Endpoint, ServerNode as MatterServerNode } from '@matter/main'; import { AggregatorEndpoint as AggregatorEndpointType } from '@matter/main/endpoints'; export interface ServerLifecycleDeps { config: MatterServerConfig; commissioningManager: CommissioningManager; fabricManager: FabricManager; getCommissioningDeps: () => CommissioningDeps; getAccessoryCache: () => MatterAccessoryCache | null; setAccessoryCache: (cache: MatterAccessoryCache) => void; /** * Rebuilds cached accessories into the aggregator. Called after the * aggregator exists but BEFORE the server node goes online, so that a * commissioned controller reconnecting during startup never observes a * shrunken parts list (which makes controllers treat the missing endpoints * as removed devices and e.g. discard their room assignments). */ restoreAccessoriesFromCache?: () => Promise<void>; setServerNode: (node: ServerNode | null) => void; getServerNode: () => ServerNode | null; setAggregator: (agg: Endpoint<typeof AggregatorEndpointType> | null) => void; getAggregator: () => Endpoint<typeof AggregatorEndpointType> | null; setIsRunning: (running: boolean) => void; getIsRunning: () => boolean; cleanupHandlers: Array<() => void | Promise<void>>; getShutdownHandler: () => (() => Promise<void>) | null; setShutdownHandler: (handler: (() => Promise<void>) | null) => void; onStop: () => Promise<void>; } export declare class ServerLifecycle { matterStoragePath?: string; /** * Whether a ServerNode creation failure is a transient storage-lock contention * (a previous instance still releasing the lock) rather than a hard failure. * * matter.js already reclaims stale locks left by a crashed owner, so only a * live previous instance produces "locked by another process". The * "already locked by this process" variant is a bug, not a race, so it is * deliberately not treated as transient. */ private isTransientStorageLock; /** * Create a ServerNode, retrying on transient storage-lock contention. * * Without this, a quick restart where the previous process is still releasing * the storage lock throws straight out of start(), which disables Matter for * the entire process lifetime with no retry (a transient condition turned into * a hard failure). */ private createServerNode; /** * Create ServerNode with automatic recovery from corrupted storage */ createServerNodeWithRecovery(nodeOptions: Parameters<typeof MatterServerNode.create>[0], sanitizedId: string): Promise<ServerNode>; /** * Set up and validate storage */ setupStorage(config: MatterServerConfig): Promise<MatterAccessoryCache>; /** * Start the Matter server */ start(deps: ServerLifecycleDeps): Promise<void>; /** * Run the server after devices have been added (for external accessory and * deferred-online modes) */ runServer(deps: ServerLifecycleDeps): Promise<void>; /** * Start the server node, wait for it to be ready, load cache, and update commissioning info. * Shared by both start() (non-external mode) and runServer() (deferred external mode). */ private startServerNode; /** * Wait for the server to be ready */ waitForServerReady(deps: ServerLifecycleDeps, maxWaitTime?: number): Promise<void>; /** * Stop the Matter server. * * External-accessory mode runs `start()` (which registers SIGINT/SIGTERM * handlers and creates the ServerNode) but defers `runServer()` until * after accessory registration — between those two steps `isRunning` is * still false. A check of just `isRunning` would skip cleanup and leave * the process handlers + half-initialised server node leaked when a * publish failure called `stop()` in its catch block. Tear down any * resources we actually allocated, regardless of `isRunning`. */ stop(deps: ServerLifecycleDeps, accessories: Map<string, any>): Promise<void>; /** * Cleanup resources. * * `preserveNodeReference` is set by stop() when `serverNode.close()` failed — * matter.js may still be holding the port, and dropping the reference would * leave no way to retry the close. In that case the SIGINT/SIGTERM shutdown * handler is also kept registered: the sole caller * (ExternalMatterAccessoryPublisher) never retries stop(), so removing the * handler would leave the still-bound node with no graceful-shutdown hook * for the rest of the process lifetime. The cleanupHandlers are always run * because they are independent of the node reference. */ cleanup(deps: ServerLifecycleDeps, options?: { preserveNodeReference?: boolean; }): Promise<void>; } //# sourceMappingURL=ServerLifecycle.d.ts.map