import { Logger } from 'pino'; import { IPollingManagerConfig, IPollingTaskOptions, IPollingTaskState, IPollingQueueInfo, IPollingSystemStats, IPollingManager } from '../types/public.js'; import { TaskController } from './task-controller.js'; /** * PollingManager is the main class responsible for managing multiple polling tasks. * It handles task registration, lifecycle control (start/stop/pause), priority-based queuing, * concurrent execution safety via per-slave mutex, and comprehensive logging. * * RISK-1 fix: Uses per-slave-id mutex instead of a single global mutex, * allowing concurrent execution for different slave devices on the same transport. */ declare class PollingManager implements IPollingManager { private config; tasks: Map; private executionQueue; private slaveMutexes; private defaultMutex; private isProcessing; private paused; logger: Logger; constructor(config?: IPollingManagerConfig); /** * Returns (or creates) a mutex for a specific slave ID. * RISK-1: Allows concurrent execution for different slaves. */ private _getSlaveMutex; /** * Determines the slave ID for a task (if any) for mutex selection. * Tasks can optionally declare a `slaveId` in their options. */ private _getTaskSlaveId; private _validateTaskOptions; addTask(options: IPollingTaskOptions): void; /** * RISK-6 fix: updateTask now waits for current execution to finish * before destroying and recreating the task. */ updateTask(id: string, newOptions: IPollingTaskOptions): Promise; removeTask(id: string): void; /** * BUG-1 fix: restartTask calls start() synchronously after stop(), * no unnecessary setTimeout wrapper. */ restartTask(id: string): void; startTask(id: string): void; stopTask(id: string): void; pauseTask(id: string): void; resumeTask(id: string): void; setTaskInterval(id: string, interval: number): void; isTaskRunning(id: string): boolean; isTaskPaused(id: string): boolean; getTaskState(id: string): IPollingTaskState | null; hasTask(id: string): boolean; getTaskIds(): string[]; /** * RISK-4 fix: clearAll no longer sets paused=true permanently. * After clearing, the manager is ready to accept new tasks. */ clearAll(): void; /** * BUG-1 fix: restartAllTasks calls start() synchronously, no setTimeout. */ restartAllTasks(): void; pauseAllTasks(): void; resumeAllTasks(): void; startAllTasks(): void; stopAllTasks(): void; getQueueInfo(): IPollingQueueInfo; getSystemStats(): IPollingSystemStats; enqueueTask(task: TaskController): void; removeFromQueue(taskId: string): void; private _sleep; /** * Main queue processing loop. * RISK-1 fix: Uses per-slave mutex so different slaves can execute concurrently. * RISK-5 fix: Removed setTimeout in finally — just call _processQueue directly * which is guarded by isProcessing flag. */ private _processQueue; /** * Executes a function immediately with exclusive access using the default mutex. * This method is intended to be used by ModbusClient or other components * that need to ensure atomicity of read/write operations while polling is active. */ executeImmediate(fn: () => Promise): Promise; /** * Executes a function immediately with exclusive access for a specific slave. * RISK-1 extension: Allows immediate commands to coexist with polling for other slaves. */ executeImmediateForSlave(slaveId: string, fn: () => Promise): Promise; setLogLevel(level: string): void; disableAllLoggers(): void; } export default PollingManager;