@hotmeshio/hotmesh 0.6.1 → 0.7.0

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.
Files changed (55) hide show
  1. package/README.md +179 -142
  2. package/build/modules/enums.d.ts +7 -0
  3. package/build/modules/enums.js +16 -1
  4. package/build/modules/utils.d.ts +27 -0
  5. package/build/modules/utils.js +52 -1
  6. package/build/package.json +10 -8
  7. package/build/services/connector/providers/postgres.js +3 -0
  8. package/build/services/hotmesh/index.d.ts +66 -15
  9. package/build/services/hotmesh/index.js +84 -15
  10. package/build/services/memflow/index.d.ts +100 -14
  11. package/build/services/memflow/index.js +100 -14
  12. package/build/services/memflow/worker.d.ts +97 -0
  13. package/build/services/memflow/worker.js +217 -0
  14. package/build/services/memflow/workflow/proxyActivities.d.ts +74 -3
  15. package/build/services/memflow/workflow/proxyActivities.js +81 -4
  16. package/build/services/router/consumption/index.d.ts +2 -1
  17. package/build/services/router/consumption/index.js +38 -2
  18. package/build/services/router/error-handling/index.d.ts +3 -3
  19. package/build/services/router/error-handling/index.js +48 -13
  20. package/build/services/router/index.d.ts +1 -0
  21. package/build/services/router/index.js +2 -1
  22. package/build/services/store/index.d.ts +3 -2
  23. package/build/services/store/providers/postgres/kvtypes/hash/basic.js +36 -6
  24. package/build/services/store/providers/postgres/kvtypes/hash/expire.js +12 -2
  25. package/build/services/store/providers/postgres/kvtypes/hash/scan.js +30 -10
  26. package/build/services/store/providers/postgres/kvtypes/list.js +68 -10
  27. package/build/services/store/providers/postgres/kvtypes/string.js +60 -10
  28. package/build/services/store/providers/postgres/kvtypes/zset.js +92 -22
  29. package/build/services/store/providers/postgres/postgres.d.ts +3 -3
  30. package/build/services/store/providers/redis/_base.d.ts +3 -3
  31. package/build/services/store/providers/redis/ioredis.js +17 -7
  32. package/build/services/stream/providers/postgres/kvtables.js +76 -23
  33. package/build/services/stream/providers/postgres/lifecycle.d.ts +19 -0
  34. package/build/services/stream/providers/postgres/lifecycle.js +54 -0
  35. package/build/services/stream/providers/postgres/messages.d.ts +56 -0
  36. package/build/services/stream/providers/postgres/messages.js +253 -0
  37. package/build/services/stream/providers/postgres/notifications.d.ts +59 -0
  38. package/build/services/stream/providers/postgres/notifications.js +357 -0
  39. package/build/services/stream/providers/postgres/postgres.d.ts +110 -11
  40. package/build/services/stream/providers/postgres/postgres.js +196 -488
  41. package/build/services/stream/providers/postgres/scout.d.ts +68 -0
  42. package/build/services/stream/providers/postgres/scout.js +233 -0
  43. package/build/services/stream/providers/postgres/stats.d.ts +49 -0
  44. package/build/services/stream/providers/postgres/stats.js +113 -0
  45. package/build/services/sub/providers/postgres/postgres.js +37 -5
  46. package/build/services/sub/providers/redis/ioredis.js +13 -2
  47. package/build/services/sub/providers/redis/redis.js +13 -2
  48. package/build/services/worker/index.d.ts +1 -0
  49. package/build/services/worker/index.js +2 -0
  50. package/build/types/hotmesh.d.ts +42 -2
  51. package/build/types/index.d.ts +3 -3
  52. package/build/types/memflow.d.ts +32 -0
  53. package/build/types/provider.d.ts +16 -0
  54. package/build/types/stream.d.ts +92 -1
  55. package/package.json +10 -8
@@ -0,0 +1,357 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.getNotificationTimeout = exports.getFallbackInterval = exports.NotificationManager = void 0;
4
+ const enums_1 = require("../../../../modules/enums");
5
+ const kvtables_1 = require("./kvtables");
6
+ /**
7
+ * Manages PostgreSQL LISTEN/NOTIFY for stream message notifications.
8
+ * Handles static state shared across all service instances using the same client.
9
+ */
10
+ class NotificationManager {
11
+ constructor(client, getTableName, getFallbackInterval, logger) {
12
+ this.client = client;
13
+ this.getTableName = getTableName;
14
+ this.getFallbackInterval = getFallbackInterval;
15
+ this.logger = logger;
16
+ // Instance-level tracking
17
+ this.instanceNotificationConsumers = new Set();
18
+ this.notificationHandlerBound = this.handleNotification.bind(this);
19
+ }
20
+ /**
21
+ * Set up notification handler for this client (once per client).
22
+ */
23
+ setupClientNotificationHandler(serviceInstance) {
24
+ if (NotificationManager.clientNotificationHandlers.get(this.client)) {
25
+ return;
26
+ }
27
+ // Initialize notification consumer map for this client
28
+ if (!NotificationManager.clientNotificationConsumers.has(this.client)) {
29
+ NotificationManager.clientNotificationConsumers.set(this.client, new Map());
30
+ }
31
+ // Set up the notification handler
32
+ this.client.on('notification', this.notificationHandlerBound);
33
+ // Mark this client as having a notification handler
34
+ NotificationManager.clientNotificationHandlers.set(this.client, true);
35
+ }
36
+ /**
37
+ * Start fallback poller for missed notifications (once per client).
38
+ */
39
+ startClientFallbackPoller(checkForMissedMessages) {
40
+ if (NotificationManager.clientFallbackPollers.has(this.client)) {
41
+ return;
42
+ }
43
+ const interval = this.getFallbackInterval();
44
+ const fallbackIntervalId = setInterval(() => {
45
+ checkForMissedMessages().catch((error) => {
46
+ this.logger.error('postgres-stream-fallback-poller-error', { error });
47
+ });
48
+ }, interval);
49
+ NotificationManager.clientFallbackPollers.set(this.client, fallbackIntervalId);
50
+ }
51
+ /**
52
+ * Check for missed messages (fallback polling).
53
+ * Handles errors gracefully to avoid noise during shutdown.
54
+ */
55
+ async checkForMissedMessages(fetchMessages) {
56
+ const now = Date.now();
57
+ // Check for visible messages using notify_visible_messages function
58
+ try {
59
+ const tableName = this.getTableName();
60
+ const schemaName = tableName.split('.')[0];
61
+ const result = await this.client.query(`SELECT ${schemaName}.notify_visible_messages() as count`);
62
+ const notificationCount = result.rows[0]?.count || 0;
63
+ if (notificationCount > 0) {
64
+ this.logger.info('postgres-stream-visibility-notifications', {
65
+ count: notificationCount,
66
+ });
67
+ }
68
+ }
69
+ catch (error) {
70
+ // Silently ignore errors during shutdown (client closed, etc.)
71
+ // Function might not exist in older schemas
72
+ if (error.message?.includes('Client was closed')) {
73
+ // Client is shutting down, silently return
74
+ return;
75
+ }
76
+ this.logger.debug('postgres-stream-visibility-function-unavailable', {
77
+ error: error.message,
78
+ });
79
+ }
80
+ // Traditional fallback check for active notification consumers
81
+ const clientNotificationConsumers = NotificationManager.clientNotificationConsumers.get(this.client);
82
+ if (!clientNotificationConsumers) {
83
+ return;
84
+ }
85
+ // Check consumers that haven't been checked recently
86
+ for (const [consumerKey, instanceMap,] of clientNotificationConsumers.entries()) {
87
+ for (const [instance, consumer] of instanceMap.entries()) {
88
+ if (consumer.isListening &&
89
+ now - consumer.lastFallbackCheck > this.getFallbackInterval()) {
90
+ try {
91
+ const messages = await fetchMessages(instance, consumer);
92
+ if (messages.length > 0) {
93
+ this.logger.debug('postgres-stream-fallback-messages', {
94
+ streamName: consumer.streamName,
95
+ groupName: consumer.groupName,
96
+ messageCount: messages.length,
97
+ });
98
+ consumer.callback(messages);
99
+ }
100
+ consumer.lastFallbackCheck = now;
101
+ }
102
+ catch (error) {
103
+ // Silently ignore errors during shutdown
104
+ if (error.message?.includes('Client was closed')) {
105
+ // Client is shutting down, stop checking this consumer
106
+ consumer.isListening = false;
107
+ return;
108
+ }
109
+ this.logger.error('postgres-stream-fallback-error', {
110
+ streamName: consumer.streamName,
111
+ groupName: consumer.groupName,
112
+ error,
113
+ });
114
+ }
115
+ }
116
+ }
117
+ }
118
+ }
119
+ /**
120
+ * Handle incoming PostgreSQL notification.
121
+ */
122
+ handleNotification(notification) {
123
+ try {
124
+ // Only handle stream notifications
125
+ if (!notification.channel.startsWith('stream_')) {
126
+ this.logger.debug('postgres-stream-ignoring-sub-notification', {
127
+ channel: notification.channel,
128
+ payloadPreview: notification.payload.substring(0, 100),
129
+ });
130
+ return;
131
+ }
132
+ this.logger.debug('postgres-stream-processing-notification', {
133
+ channel: notification.channel,
134
+ });
135
+ const payload = JSON.parse(notification.payload);
136
+ const { stream_name, group_name } = payload;
137
+ if (!stream_name || !group_name) {
138
+ this.logger.warn('postgres-stream-invalid-notification', {
139
+ notification,
140
+ });
141
+ return;
142
+ }
143
+ const consumerKey = this.getConsumerKey(stream_name, group_name);
144
+ const clientNotificationConsumers = NotificationManager.clientNotificationConsumers.get(this.client);
145
+ if (!clientNotificationConsumers) {
146
+ return;
147
+ }
148
+ const instanceMap = clientNotificationConsumers.get(consumerKey);
149
+ if (!instanceMap) {
150
+ return;
151
+ }
152
+ // Trigger immediate message fetch for all instances with this consumer
153
+ for (const [instance, consumer] of instanceMap.entries()) {
154
+ if (consumer.isListening) {
155
+ const serviceInstance = instance;
156
+ if (serviceInstance.fetchAndDeliverMessages) {
157
+ serviceInstance.fetchAndDeliverMessages(consumer);
158
+ }
159
+ }
160
+ }
161
+ }
162
+ catch (error) {
163
+ this.logger.error('postgres-stream-notification-parse-error', {
164
+ notification,
165
+ error,
166
+ });
167
+ }
168
+ }
169
+ /**
170
+ * Set up notification consumer for a stream/group.
171
+ */
172
+ async setupNotificationConsumer(serviceInstance, streamName, groupName, consumerName, callback) {
173
+ const startTime = Date.now();
174
+ const consumerKey = this.getConsumerKey(streamName, groupName);
175
+ const channelName = (0, kvtables_1.getNotificationChannelName)(streamName, groupName);
176
+ // Get or create notification consumer map for this client
177
+ let clientNotificationConsumers = NotificationManager.clientNotificationConsumers.get(this.client);
178
+ if (!clientNotificationConsumers) {
179
+ clientNotificationConsumers = new Map();
180
+ NotificationManager.clientNotificationConsumers.set(this.client, clientNotificationConsumers);
181
+ }
182
+ // Get or create instance map for this consumer key
183
+ let instanceMap = clientNotificationConsumers.get(consumerKey);
184
+ if (!instanceMap) {
185
+ instanceMap = new Map();
186
+ clientNotificationConsumers.set(consumerKey, instanceMap);
187
+ // Set up LISTEN for this channel (only once per channel)
188
+ try {
189
+ const listenStart = Date.now();
190
+ await this.client.query(`LISTEN "${channelName}"`);
191
+ this.logger.debug('postgres-stream-listen-start', {
192
+ streamName,
193
+ groupName,
194
+ channelName,
195
+ listenDuration: Date.now() - listenStart,
196
+ });
197
+ }
198
+ catch (error) {
199
+ this.logger.error('postgres-stream-listen-error', {
200
+ streamName,
201
+ groupName,
202
+ channelName,
203
+ error,
204
+ });
205
+ throw error; // Propagate error to caller
206
+ }
207
+ }
208
+ // Register consumer for this instance
209
+ const consumer = {
210
+ streamName,
211
+ groupName,
212
+ consumerName,
213
+ callback,
214
+ isListening: true,
215
+ lastFallbackCheck: Date.now(),
216
+ };
217
+ instanceMap.set(serviceInstance, consumer);
218
+ // Track this consumer for cleanup
219
+ this.instanceNotificationConsumers.add(consumerKey);
220
+ this.logger.debug('postgres-stream-notification-setup-complete', {
221
+ streamName,
222
+ groupName,
223
+ instanceCount: instanceMap.size,
224
+ setupDuration: Date.now() - startTime,
225
+ });
226
+ }
227
+ /**
228
+ * Stop notification consumer for a stream/group.
229
+ */
230
+ async stopNotificationConsumer(serviceInstance, streamName, groupName) {
231
+ const consumerKey = this.getConsumerKey(streamName, groupName);
232
+ const clientNotificationConsumers = NotificationManager.clientNotificationConsumers.get(this.client);
233
+ if (!clientNotificationConsumers) {
234
+ return;
235
+ }
236
+ const instanceMap = clientNotificationConsumers.get(consumerKey);
237
+ if (!instanceMap) {
238
+ return;
239
+ }
240
+ const consumer = instanceMap.get(serviceInstance);
241
+ if (consumer) {
242
+ consumer.isListening = false;
243
+ instanceMap.delete(serviceInstance);
244
+ // Remove from instance tracking
245
+ this.instanceNotificationConsumers.delete(consumerKey);
246
+ // If no more instances for this consumer key, stop listening
247
+ if (instanceMap.size === 0) {
248
+ clientNotificationConsumers.delete(consumerKey);
249
+ const channelName = (0, kvtables_1.getNotificationChannelName)(streamName, groupName);
250
+ try {
251
+ await this.client.query(`UNLISTEN "${channelName}"`);
252
+ this.logger.debug('postgres-stream-unlisten', {
253
+ streamName,
254
+ groupName,
255
+ channelName,
256
+ });
257
+ }
258
+ catch (error) {
259
+ this.logger.error('postgres-stream-unlisten-error', {
260
+ streamName,
261
+ groupName,
262
+ channelName,
263
+ error,
264
+ });
265
+ }
266
+ }
267
+ }
268
+ }
269
+ /**
270
+ * Clean up notification consumers for this instance.
271
+ * Stops fallback poller FIRST to prevent race conditions during shutdown.
272
+ */
273
+ async cleanup(serviceInstance) {
274
+ const clientNotificationConsumers = NotificationManager.clientNotificationConsumers.get(this.client);
275
+ // FIRST: Stop fallback poller to prevent queries during cleanup
276
+ const fallbackIntervalId = NotificationManager.clientFallbackPollers.get(this.client);
277
+ if (fallbackIntervalId) {
278
+ clearInterval(fallbackIntervalId);
279
+ NotificationManager.clientFallbackPollers.delete(this.client);
280
+ }
281
+ if (clientNotificationConsumers) {
282
+ // Remove this instance from all consumer maps
283
+ for (const consumerKey of this.instanceNotificationConsumers) {
284
+ const instanceMap = clientNotificationConsumers.get(consumerKey);
285
+ if (instanceMap) {
286
+ const consumer = instanceMap.get(serviceInstance);
287
+ if (consumer) {
288
+ consumer.isListening = false;
289
+ instanceMap.delete(serviceInstance);
290
+ // If no more instances for this consumer, stop listening
291
+ if (instanceMap.size === 0) {
292
+ clientNotificationConsumers.delete(consumerKey);
293
+ const channelName = (0, kvtables_1.getNotificationChannelName)(consumer.streamName, consumer.groupName);
294
+ try {
295
+ await this.client.query(`UNLISTEN "${channelName}"`);
296
+ this.logger.debug('postgres-stream-cleanup-unlisten', {
297
+ streamName: consumer.streamName,
298
+ groupName: consumer.groupName,
299
+ channelName,
300
+ });
301
+ }
302
+ catch (error) {
303
+ // Silently ignore errors during shutdown
304
+ if (!error.message?.includes('Client was closed')) {
305
+ this.logger.error('postgres-stream-cleanup-unlisten-error', {
306
+ streamName: consumer.streamName,
307
+ groupName: consumer.groupName,
308
+ channelName,
309
+ error,
310
+ });
311
+ }
312
+ }
313
+ }
314
+ }
315
+ }
316
+ }
317
+ }
318
+ // Clear instance tracking
319
+ this.instanceNotificationConsumers.clear();
320
+ // If no more consumers exist for this client, clean up static resources
321
+ if (clientNotificationConsumers && clientNotificationConsumers.size === 0) {
322
+ // Remove client from static maps
323
+ NotificationManager.clientNotificationConsumers.delete(this.client);
324
+ NotificationManager.clientNotificationHandlers.delete(this.client);
325
+ // Fallback poller already stopped above
326
+ // Remove notification handler
327
+ if (this.client.removeAllListeners) {
328
+ this.client.removeAllListeners('notification');
329
+ }
330
+ else if (this.client.off && this.notificationHandlerBound) {
331
+ this.client.off('notification', this.notificationHandlerBound);
332
+ }
333
+ }
334
+ }
335
+ /**
336
+ * Get consumer key from stream and group names.
337
+ */
338
+ getConsumerKey(streamName, groupName) {
339
+ return `${streamName}:${groupName}`;
340
+ }
341
+ }
342
+ // Static maps shared across all instances with the same client
343
+ NotificationManager.clientNotificationConsumers = new Map();
344
+ NotificationManager.clientNotificationHandlers = new Map();
345
+ NotificationManager.clientFallbackPollers = new Map();
346
+ exports.NotificationManager = NotificationManager;
347
+ /**
348
+ * Get configuration values for notification settings.
349
+ */
350
+ function getFallbackInterval(config) {
351
+ return config?.postgres?.notificationFallbackInterval || enums_1.HMSH_ROUTER_POLL_FALLBACK_INTERVAL;
352
+ }
353
+ exports.getFallbackInterval = getFallbackInterval;
354
+ function getNotificationTimeout(config) {
355
+ return config?.postgres?.notificationTimeout || 5000; // Default: 5 seconds
356
+ }
357
+ exports.getNotificationTimeout = getNotificationTimeout;
@@ -5,24 +5,123 @@ import { KeyStoreParams, StringAnyType } from '../../../../types';
5
5
  import { PostgresClientType } from '../../../../types/postgres';
6
6
  import { PublishMessageConfig, StreamConfig, StreamMessage, StreamStats } from '../../../../types/stream';
7
7
  import { ProviderClient, ProviderTransaction } from '../../../../types/provider';
8
+ /**
9
+ * PostgreSQL Stream Service
10
+ *
11
+ * High-performance stream message provider using PostgreSQL with LISTEN/NOTIFY.
12
+ *
13
+ * ## Module Organization
14
+ *
15
+ * This service is organized into focused modules following KISS principles:
16
+ * - `postgres.ts` (this file) - Main orchestrator and service interface
17
+ * - `kvtables.ts` - Schema deployment and table management
18
+ * - `messages.ts` - Message CRUD operations (publish, fetch, ack, delete)
19
+ * - `stats.ts` - Statistics and query operations
20
+ * - `scout.ts` - Scout role coordination for polling visible messages
21
+ * - `notifications.ts` - LISTEN/NOTIFY notification system with static state management
22
+ * - `lifecycle.ts` - Stream and consumer group lifecycle operations
23
+ *
24
+ * ## Lifecycle
25
+ *
26
+ * ### Initialization (`init`)
27
+ * 1. Deploy PostgreSQL schema (tables, indexes, triggers, functions)
28
+ * 2. Create ScoutManager for coordinating visibility timeout polling
29
+ * 3. Create NotificationManager for LISTEN/NOTIFY event handling
30
+ * 4. Set up notification handler (once per client, shared across instances)
31
+ * 5. Start fallback poller (backup for missed notifications)
32
+ * 6. Start router scout poller (for visibility timeout processing)
33
+ *
34
+ * ### Shutdown (`cleanup`)
35
+ * 1. Stop router scout polling loop
36
+ * 2. Release scout role if held
37
+ * 3. Stop notification consumers for this instance
38
+ * 4. UNLISTEN from channels when last instance disconnects
39
+ * 5. Clean up fallback poller when last instance disconnects
40
+ * 6. Remove notification handlers when last instance disconnects
41
+ *
42
+ * ## Notification System (LISTEN/NOTIFY)
43
+ *
44
+ * ### Real-time Message Delivery
45
+ * - PostgreSQL trigger on INSERT sends NOTIFY when messages are immediately visible
46
+ * - Messages with visibility timeout are NOT notified on INSERT
47
+ * - Multiple service instances share the same client and notification handlers
48
+ * - Static state ensures only ONE LISTEN per channel across all instances
49
+ *
50
+ * ### Components
51
+ * - **Notification Handler**: Listens for PostgreSQL NOTIFY events
52
+ * - **Fallback Poller**: Polls every 30s (default) for missed messages
53
+ * - **Router Scout**: Active role-holder polls visible messages frequently (~100ms)
54
+ * - **Visibility Function**: `notify_visible_messages()` checks for expired timeouts
55
+ *
56
+ * ## Scout Role (Visibility Timeout Processing)
57
+ *
58
+ * When messages are published with visibility timeouts (delays), they need to be
59
+ * processed when they become visible. The scout role ensures this happens efficiently:
60
+ *
61
+ * 1. **Role Acquisition**: One instance per app acquires "router" scout role
62
+ * 2. **Fast Polling**: Scout polls `notify_visible_messages()` every ~100ms
63
+ * 3. **Notification**: Function triggers NOTIFY for streams with visible messages
64
+ * 4. **Role Rotation**: Role expires after interval, another instance can claim it
65
+ * 5. **Fallback**: Non-scouts sleep longer, try to acquire role periodically
66
+ *
67
+ * ## Message Flow
68
+ *
69
+ * ### Publishing
70
+ * 1. Messages inserted into partitioned table
71
+ * 2. If immediately visible → INSERT trigger sends NOTIFY
72
+ * 3. If visibility timeout → no NOTIFY (scout will handle when visible)
73
+ *
74
+ * ### Consuming (Event-Driven)
75
+ * 1. Consumer calls `consumeMessages` with notification callback
76
+ * 2. Service executes LISTEN on channel `stream_{name}_{group}`
77
+ * 3. On NOTIFY → fetch messages → invoke callback
78
+ * 4. Initial fetch done immediately (catch any queued messages)
79
+ *
80
+ * ### Consuming (Polling)
81
+ * 1. Consumer calls `consumeMessages` without callback
82
+ * 2. Service directly queries and reserves messages
83
+ * 3. Returns messages synchronously
84
+ *
85
+ * ## Reliability Guarantees
86
+ *
87
+ * - **Notification Fallback**: Poller catches missed notifications every 30s
88
+ * - **Visibility Scout**: Ensures delayed messages are processed when visible
89
+ * - **Graceful Degradation**: Falls back to polling if LISTEN fails
90
+ * - **Shared State**: Multiple instances coordinate via static maps
91
+ * - **Race Condition Safe**: SKIP LOCKED prevents message duplication
92
+ *
93
+ * @example
94
+ * ```typescript
95
+ * // Initialize service
96
+ * const service = new PostgresStreamService(client, storeClient, config);
97
+ * await service.init('namespace', 'appId', logger);
98
+ *
99
+ * // Event-driven consumption (recommended)
100
+ * await service.consumeMessages('stream', 'group', 'consumer', {
101
+ * notificationCallback: (messages) => {
102
+ * // Process messages in real-time
103
+ * }
104
+ * });
105
+ *
106
+ * // Polling consumption
107
+ * const messages = await service.consumeMessages('stream', 'group', 'consumer', {
108
+ * batchSize: 10
109
+ * });
110
+ *
111
+ * // Cleanup on shutdown
112
+ * await service.cleanup();
113
+ * ```
114
+ */
8
115
  declare class PostgresStreamService extends StreamService<PostgresClientType & ProviderClient, any> {
9
116
  namespace: string;
10
117
  appId: string;
11
118
  logger: ILogger;
12
- private static clientNotificationConsumers;
13
- private static clientNotificationHandlers;
14
- private static clientFallbackPollers;
15
- private instanceNotificationConsumers;
16
- private notificationHandlerBound;
119
+ private scoutManager;
120
+ private notificationManager;
17
121
  constructor(streamClient: PostgresClientType & ProviderClient, storeClient: ProviderClient, config?: StreamConfig);
18
122
  init(namespace: string, appId: string, logger: ILogger): Promise<void>;
19
- private setupClientNotificationHandler;
20
- private startClientFallbackPoller;
21
123
  private isNotificationsEnabled;
22
- private getFallbackInterval;
23
- private getNotificationTimeout;
24
124
  private checkForMissedMessages;
25
- private handleNotification;
26
125
  private fetchAndDeliverMessages;
27
126
  private getConsumerKey;
28
127
  mintKey(type: KeyType, params: KeyStoreParams): string;
@@ -51,7 +150,7 @@ declare class PostgresStreamService extends StreamService<PostgresClientType & P
51
150
  * allows calls to the stream to be roped into a single SQL transaction.
52
151
  */
53
152
  publishMessages(streamName: string, messages: string[], options?: PublishMessageConfig): Promise<string[] | ProviderTransaction>;
54
- _publishMessages(streamName: string, messages: string[]): {
153
+ _publishMessages(streamName: string, messages: string[], options?: PublishMessageConfig): {
55
154
  sql: string;
56
155
  params: any[];
57
156
  };