ocpp-ws-io 2.1.7 → 2.1.8

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,161 @@
1
+ import { E as EventAdapterInterface } from './types-BZXEmDQ1.mjs';
2
+
3
+ interface RedisLikeClient {
4
+ publish(channel: string, message: string): Promise<number | unknown | undefined>;
5
+ subscribe(channel: string, ...args: unknown[]): Promise<unknown | undefined>;
6
+ unsubscribe(channel: string, ...args: unknown[]): Promise<unknown | undefined>;
7
+ on?(event: "message", callback: (channel: string, message: string) => void): unknown;
8
+ disconnect?(): Promise<void> | void;
9
+ quit?(): Promise<unknown> | undefined;
10
+ isOpen?: boolean;
11
+ }
12
+ interface StreamMessage {
13
+ id: string;
14
+ data: Record<string, string>;
15
+ }
16
+ interface StreamEntry {
17
+ stream: string;
18
+ messages: StreamMessage[];
19
+ }
20
+ interface RedisPubSubDriver {
21
+ publish(channel: string, message: string): Promise<void>;
22
+ subscribe(channel: string, handler: (message: string) => void): Promise<void>;
23
+ unsubscribe(channel: string): Promise<void>;
24
+ disconnect(): Promise<void>;
25
+ set(key: string, value: string, ttlSeconds?: number): Promise<void>;
26
+ get(key: string): Promise<string | null>;
27
+ mget(keys: string[]): Promise<(string | null)[]>;
28
+ del(key: string): Promise<void>;
29
+ /**
30
+ * Batch set multiple presence keys with TTL in a single pipeline.
31
+ * Falls back to sequential sets if pipelining is unavailable.
32
+ */
33
+ setPresenceBatch(entries: {
34
+ key: string;
35
+ value: string;
36
+ ttlSeconds: number;
37
+ }[]): Promise<void>;
38
+ /**
39
+ * Set a TTL on an existing key (for ephemeral stream channel leases).
40
+ */
41
+ expire(key: string, ttlSeconds: number): Promise<void>;
42
+ /**
43
+ * Subscribe to connection error events for rehydration.
44
+ * Returns an unsubscribe function.
45
+ */
46
+ onError?(handler: (err: Error) => void): () => void;
47
+ /**
48
+ * Subscribe to reconnection events.
49
+ * Returns an unsubscribe function.
50
+ */
51
+ onReconnect?(handler: () => void): () => void;
52
+ xadd(stream: string, args: Record<string, string>, maxLen?: number): Promise<string>;
53
+ xaddBatch(messages: {
54
+ stream: string;
55
+ args: Record<string, string>;
56
+ }[], maxLen?: number): Promise<void>;
57
+ xread(streams: {
58
+ key: string;
59
+ id: string;
60
+ }[], count?: number, block?: number): Promise<StreamEntry[] | null>;
61
+ xlen(stream: string): Promise<number>;
62
+ }
63
+
64
+ interface RedisAdapterOptions {
65
+ /** Redis client for publishing */
66
+ pubClient: RedisLikeClient;
67
+ /** Redis client for subscribing (must be a separate connection) */
68
+ subClient: RedisLikeClient;
69
+ /** Redis client for blocking stream operations (recommended for reliability) */
70
+ blockingClient?: RedisLikeClient;
71
+ /** Optional key prefix for channels (default: 'ocpp-ws-io:') */
72
+ prefix?: string;
73
+ /** StreamMaxLen for trimming (default: 1000) */
74
+ streamMaxLen?: number;
75
+ /**
76
+ * TTL in seconds for ephemeral stream keys (default: 300).
77
+ * Prevents abandoned channel keys from leaking memory in Redis.
78
+ */
79
+ streamTtlSeconds?: number;
80
+ /**
81
+ * Presence TTL in seconds (default: 300).
82
+ * Used for batch presence heartbeat pipeline.
83
+ */
84
+ presenceTtlSeconds?: number;
85
+ /**
86
+ * Number of Redis connections to pool for write operations (default: 1).
87
+ * Higher values distribute load via round-robin, eliminating TCP head-of-line blocking.
88
+ * Pub/Sub subscriptions always use the primary driver (pool index 0).
89
+ * - `1` = current single-connection behavior (backward compatible)
90
+ * - `N` = round-robin across N connections for xadd/set/publish
91
+ *
92
+ * When poolSize > 1, additional pub/blocking clients are created by the factory.
93
+ * Provide `driverFactory` to control how additional drivers are created.
94
+ */
95
+ poolSize?: number;
96
+ /**
97
+ * Factory function to create additional driver instances for the pool.
98
+ * Each call should return a fresh, independent set of Redis connections.
99
+ * Required when `poolSize > 1`.
100
+ */
101
+ driverFactory?: () => RedisPubSubDriver;
102
+ }
103
+ /**
104
+ * Redis adapter for cross-process event distribution.
105
+ *
106
+ * Supports `ioredis` and `node-redis` (v4+).
107
+ * Uses Redis Streams for reliable unicast (node-to-node) and Pub/Sub for broadcast.
108
+ */
109
+ declare class RedisAdapter implements EventAdapterInterface {
110
+ private _driver;
111
+ private _prefix;
112
+ private _streamMaxLen;
113
+ private _streamTtlSeconds;
114
+ private _presenceTtlSeconds;
115
+ private _handlers;
116
+ private _streamOffsets;
117
+ private _streams;
118
+ private _polling;
119
+ private _closed;
120
+ private _sequenceCounters;
121
+ private _unsubError?;
122
+ private _unsubReconnect?;
123
+ private _presenceCache;
124
+ private _driverPool;
125
+ private _nextPoolIndex;
126
+ constructor(options: RedisAdapterOptions);
127
+ /** Get the next driver from the pool (round-robin) */
128
+ private _getPoolDriver;
129
+ publish(channel: string, data: unknown): Promise<void>;
130
+ publishBatch(messages: {
131
+ channel: string;
132
+ data: unknown;
133
+ }[]): Promise<void>;
134
+ subscribe(channel: string, handler: (data: unknown) => void): Promise<void>;
135
+ unsubscribe(channel: string): Promise<void>;
136
+ disconnect(): Promise<void>;
137
+ private _handleMessage;
138
+ private _ensurePolling;
139
+ private _pollLoop;
140
+ setPresence(identity: string, nodeId: string, ttl: number): Promise<void>;
141
+ getPresence(identity: string): Promise<string | null>;
142
+ getPresenceBatch(identities: string[]): Promise<(string | null)[]>;
143
+ removePresence(identity: string): Promise<void>;
144
+ metrics(): Promise<Record<string, unknown>>;
145
+ /**
146
+ * Set multiple presence entries in a single Redis pipeline.
147
+ * Reduces N network round-trips to 1 for bulk presence updates.
148
+ */
149
+ setPresenceBatch(entries: {
150
+ identity: string;
151
+ nodeId: string;
152
+ ttl?: number;
153
+ }[]): Promise<void>;
154
+ /**
155
+ * Re-syncs all cached presence entries to Redis after a reconnection.
156
+ * Called automatically when the Redis client reconnects.
157
+ */
158
+ private _rehydratePresence;
159
+ }
160
+
161
+ export { type RedisPubSubDriver as R, type StreamEntry as S, RedisAdapter as a, type RedisAdapterOptions as b };
@@ -0,0 +1,161 @@
1
+ import { E as EventAdapterInterface } from './types-BZXEmDQ1.js';
2
+
3
+ interface RedisLikeClient {
4
+ publish(channel: string, message: string): Promise<number | unknown | undefined>;
5
+ subscribe(channel: string, ...args: unknown[]): Promise<unknown | undefined>;
6
+ unsubscribe(channel: string, ...args: unknown[]): Promise<unknown | undefined>;
7
+ on?(event: "message", callback: (channel: string, message: string) => void): unknown;
8
+ disconnect?(): Promise<void> | void;
9
+ quit?(): Promise<unknown> | undefined;
10
+ isOpen?: boolean;
11
+ }
12
+ interface StreamMessage {
13
+ id: string;
14
+ data: Record<string, string>;
15
+ }
16
+ interface StreamEntry {
17
+ stream: string;
18
+ messages: StreamMessage[];
19
+ }
20
+ interface RedisPubSubDriver {
21
+ publish(channel: string, message: string): Promise<void>;
22
+ subscribe(channel: string, handler: (message: string) => void): Promise<void>;
23
+ unsubscribe(channel: string): Promise<void>;
24
+ disconnect(): Promise<void>;
25
+ set(key: string, value: string, ttlSeconds?: number): Promise<void>;
26
+ get(key: string): Promise<string | null>;
27
+ mget(keys: string[]): Promise<(string | null)[]>;
28
+ del(key: string): Promise<void>;
29
+ /**
30
+ * Batch set multiple presence keys with TTL in a single pipeline.
31
+ * Falls back to sequential sets if pipelining is unavailable.
32
+ */
33
+ setPresenceBatch(entries: {
34
+ key: string;
35
+ value: string;
36
+ ttlSeconds: number;
37
+ }[]): Promise<void>;
38
+ /**
39
+ * Set a TTL on an existing key (for ephemeral stream channel leases).
40
+ */
41
+ expire(key: string, ttlSeconds: number): Promise<void>;
42
+ /**
43
+ * Subscribe to connection error events for rehydration.
44
+ * Returns an unsubscribe function.
45
+ */
46
+ onError?(handler: (err: Error) => void): () => void;
47
+ /**
48
+ * Subscribe to reconnection events.
49
+ * Returns an unsubscribe function.
50
+ */
51
+ onReconnect?(handler: () => void): () => void;
52
+ xadd(stream: string, args: Record<string, string>, maxLen?: number): Promise<string>;
53
+ xaddBatch(messages: {
54
+ stream: string;
55
+ args: Record<string, string>;
56
+ }[], maxLen?: number): Promise<void>;
57
+ xread(streams: {
58
+ key: string;
59
+ id: string;
60
+ }[], count?: number, block?: number): Promise<StreamEntry[] | null>;
61
+ xlen(stream: string): Promise<number>;
62
+ }
63
+
64
+ interface RedisAdapterOptions {
65
+ /** Redis client for publishing */
66
+ pubClient: RedisLikeClient;
67
+ /** Redis client for subscribing (must be a separate connection) */
68
+ subClient: RedisLikeClient;
69
+ /** Redis client for blocking stream operations (recommended for reliability) */
70
+ blockingClient?: RedisLikeClient;
71
+ /** Optional key prefix for channels (default: 'ocpp-ws-io:') */
72
+ prefix?: string;
73
+ /** StreamMaxLen for trimming (default: 1000) */
74
+ streamMaxLen?: number;
75
+ /**
76
+ * TTL in seconds for ephemeral stream keys (default: 300).
77
+ * Prevents abandoned channel keys from leaking memory in Redis.
78
+ */
79
+ streamTtlSeconds?: number;
80
+ /**
81
+ * Presence TTL in seconds (default: 300).
82
+ * Used for batch presence heartbeat pipeline.
83
+ */
84
+ presenceTtlSeconds?: number;
85
+ /**
86
+ * Number of Redis connections to pool for write operations (default: 1).
87
+ * Higher values distribute load via round-robin, eliminating TCP head-of-line blocking.
88
+ * Pub/Sub subscriptions always use the primary driver (pool index 0).
89
+ * - `1` = current single-connection behavior (backward compatible)
90
+ * - `N` = round-robin across N connections for xadd/set/publish
91
+ *
92
+ * When poolSize > 1, additional pub/blocking clients are created by the factory.
93
+ * Provide `driverFactory` to control how additional drivers are created.
94
+ */
95
+ poolSize?: number;
96
+ /**
97
+ * Factory function to create additional driver instances for the pool.
98
+ * Each call should return a fresh, independent set of Redis connections.
99
+ * Required when `poolSize > 1`.
100
+ */
101
+ driverFactory?: () => RedisPubSubDriver;
102
+ }
103
+ /**
104
+ * Redis adapter for cross-process event distribution.
105
+ *
106
+ * Supports `ioredis` and `node-redis` (v4+).
107
+ * Uses Redis Streams for reliable unicast (node-to-node) and Pub/Sub for broadcast.
108
+ */
109
+ declare class RedisAdapter implements EventAdapterInterface {
110
+ private _driver;
111
+ private _prefix;
112
+ private _streamMaxLen;
113
+ private _streamTtlSeconds;
114
+ private _presenceTtlSeconds;
115
+ private _handlers;
116
+ private _streamOffsets;
117
+ private _streams;
118
+ private _polling;
119
+ private _closed;
120
+ private _sequenceCounters;
121
+ private _unsubError?;
122
+ private _unsubReconnect?;
123
+ private _presenceCache;
124
+ private _driverPool;
125
+ private _nextPoolIndex;
126
+ constructor(options: RedisAdapterOptions);
127
+ /** Get the next driver from the pool (round-robin) */
128
+ private _getPoolDriver;
129
+ publish(channel: string, data: unknown): Promise<void>;
130
+ publishBatch(messages: {
131
+ channel: string;
132
+ data: unknown;
133
+ }[]): Promise<void>;
134
+ subscribe(channel: string, handler: (data: unknown) => void): Promise<void>;
135
+ unsubscribe(channel: string): Promise<void>;
136
+ disconnect(): Promise<void>;
137
+ private _handleMessage;
138
+ private _ensurePolling;
139
+ private _pollLoop;
140
+ setPresence(identity: string, nodeId: string, ttl: number): Promise<void>;
141
+ getPresence(identity: string): Promise<string | null>;
142
+ getPresenceBatch(identities: string[]): Promise<(string | null)[]>;
143
+ removePresence(identity: string): Promise<void>;
144
+ metrics(): Promise<Record<string, unknown>>;
145
+ /**
146
+ * Set multiple presence entries in a single Redis pipeline.
147
+ * Reduces N network round-trips to 1 for bulk presence updates.
148
+ */
149
+ setPresenceBatch(entries: {
150
+ identity: string;
151
+ nodeId: string;
152
+ ttl?: number;
153
+ }[]): Promise<void>;
154
+ /**
155
+ * Re-syncs all cached presence entries to Redis after a reconnection.
156
+ * Called automatically when the Redis client reconnects.
157
+ */
158
+ private _rehydratePresence;
159
+ }
160
+
161
+ export { type RedisPubSubDriver as R, type StreamEntry as S, RedisAdapter as a, type RedisAdapterOptions as b };