UNPKG

@citrineos/util

Version:

The OCPP util module which supplies helpful utilities like cache and queue connectors, etc.

65 lines (64 loc) 3.44 kB
import type { IConnectionManager, IMessage, IMessageConfirmation, IMessageSender, OcppRequest, OcppResponse } from '@citrineos/base'; import { AbstractMessageSender, MessageState, OcppError } from '@citrineos/base'; import type { ILogObj } from 'tslog'; import { Logger } from 'tslog'; type AnyMessage = IMessage<OcppRequest | OcppResponse | OcppError>; /** * A decorator around any {@link IMessageSender} that adds resilience when the * underlying message broker is unavailable. * * Behaviour when the broker is **disconnected**: * - **Call messages** (`MessageState.Request`): a `maxCallLengthSeconds` timeout is * started. When it fires the optional {@link onCallTimeout} callback is invoked * (e.g. to close the charger's WebSocket) and the pending entry is removed from * memory to prevent retry accumulation. * - **All other messages** (`MessageState.Response` / `MessageState.Unknown`): the * message is held in an in-memory buffer and replayed in order once the broker * reconnects. * * Behaviour when the broker **reconnects**: * - All buffered non-Call messages are flushed in order through the inner sender. * - In-flight Call timeouts continue to run (they will still close the WS connection * because the Call was never delivered to a module). */ export declare class BrokerAwareMessageSender extends AbstractMessageSender implements IMessageSender { private readonly _inner; private readonly _connectionManager; private readonly _maxCallLengthSeconds; /** Pending non-Call messages waiting to be flushed after reconnection. */ private _buffer; /** * Active Call timeouts keyed by connection identifier (`tenantId:stationId`). * When a timeout fires the entry is deleted and `_onCallTimeout` is invoked. */ private _callTimeouts; /** * Optional callback invoked when a Call times out while the broker is down. * Typically used to close the corresponding WebSocket connection. * Can be set after construction to avoid circular dependency issues. */ onCallTimeout?: (stationId: string, tenantId: number) => Promise<void>; constructor(_inner: IMessageSender, _connectionManager: IConnectionManager, _maxCallLengthSeconds: number, logger?: Logger<ILogObj>); sendRequest(message: IMessage<OcppRequest>, payload?: OcppRequest): Promise<IMessageConfirmation>; sendResponse(message: IMessage<OcppResponse | OcppError>, payload?: OcppResponse | OcppError): Promise<IMessageConfirmation>; send(message: AnyMessage, payload?: OcppRequest | OcppResponse | OcppError, state?: MessageState): Promise<IMessageConfirmation>; shutdown(): Promise<void>; /** * Starts a `maxCallLengthSeconds` timer for a Call that cannot be delivered * because the broker is down. On expiry the optional {@link onCallTimeout} * callback is invoked and the timeout entry is cleaned up. * * Returns `{ success: true }` so the router does not immediately send a * CallError – the charger will wait until the connection is closed by the timer. */ private _handleDisconnectedCall; /** Adds a non-Call message to the in-memory buffer. */ private _bufferMessage; /** * Replays all buffered messages through the inner sender. * If the broker drops again mid-flush the remaining messages are re-buffered. */ private _flushBuffer; private _clearAllCallTimeouts; } export {};