@hotmeshio/hotmesh 0.5.3 → 0.5.4
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.
- package/README.md +67 -134
- package/build/index.d.ts +1 -3
- package/build/index.js +1 -5
- package/build/modules/enums.d.ts +4 -0
- package/build/modules/enums.js +5 -1
- package/build/modules/utils.d.ts +1 -9
- package/build/modules/utils.js +0 -6
- package/build/package.json +3 -4
- package/build/services/connector/factory.d.ts +2 -2
- package/build/services/connector/factory.js +11 -8
- package/build/services/connector/providers/postgres.d.ts +47 -0
- package/build/services/connector/providers/postgres.js +107 -0
- package/build/services/hotmesh/index.d.ts +8 -0
- package/build/services/hotmesh/index.js +27 -0
- package/build/services/memflow/client.d.ts +1 -1
- package/build/services/memflow/client.js +8 -6
- package/build/services/memflow/worker.js +3 -0
- package/build/services/pipe/functions/cron.js +1 -1
- package/build/services/store/providers/postgres/kvtables.js +19 -6
- package/build/services/store/providers/postgres/postgres.js +13 -2
- package/build/services/stream/providers/postgres/postgres.d.ts +6 -3
- package/build/services/stream/providers/postgres/postgres.js +169 -59
- package/build/services/sub/providers/postgres/postgres.d.ts +9 -0
- package/build/services/sub/providers/postgres/postgres.js +109 -18
- package/build/services/worker/index.js +4 -0
- package/build/types/hotmesh.d.ts +19 -5
- package/build/types/index.d.ts +0 -2
- package/env.example +11 -0
- package/index.ts +0 -4
- package/package.json +3 -4
- package/build/services/meshdata/index.d.ts +0 -795
- package/build/services/meshdata/index.js +0 -1235
- package/build/services/meshos/index.d.ts +0 -293
- package/build/services/meshos/index.js +0 -547
- package/build/types/manifest.d.ts +0 -52
- package/build/types/manifest.js +0 -2
- package/build/types/meshdata.d.ts +0 -252
- package/build/types/meshdata.js +0 -2
|
@@ -2,6 +2,7 @@
|
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.PostgresConnection = void 0;
|
|
4
4
|
const __1 = require("..");
|
|
5
|
+
const utils_1 = require("../../../modules/utils");
|
|
5
6
|
class PostgresConnection extends __1.AbstractConnection {
|
|
6
7
|
constructor() {
|
|
7
8
|
super(...arguments);
|
|
@@ -15,6 +16,54 @@ class PostgresConnection extends __1.AbstractConnection {
|
|
|
15
16
|
idleTimeoutMillis: 30000,
|
|
16
17
|
};
|
|
17
18
|
}
|
|
19
|
+
/**
|
|
20
|
+
* Get comprehensive connection statistics for monitoring taskQueue pooling effectiveness
|
|
21
|
+
*/
|
|
22
|
+
static getConnectionStats() {
|
|
23
|
+
const taskQueueDetails = Array.from(this.taskQueueConnections.entries()).map(([key, connection]) => ({
|
|
24
|
+
key,
|
|
25
|
+
connectionId: connection.getConnectionId() || 'unknown',
|
|
26
|
+
reusedCount: connection.reusedCount || 0
|
|
27
|
+
}));
|
|
28
|
+
return {
|
|
29
|
+
totalPoolClients: this.poolClientInstances.size,
|
|
30
|
+
totalConnections: this.connectionInstances.size,
|
|
31
|
+
taskQueueConnections: this.taskQueueConnections.size,
|
|
32
|
+
taskQueueDetails
|
|
33
|
+
};
|
|
34
|
+
}
|
|
35
|
+
/**
|
|
36
|
+
* Log current connection statistics - useful for debugging connection pooling
|
|
37
|
+
*/
|
|
38
|
+
static logConnectionStats(logger) {
|
|
39
|
+
const stats = this.getConnectionStats();
|
|
40
|
+
const message = `PostgreSQL Connection Stats: ${stats.totalConnections} total connections, ${stats.taskQueueConnections} taskQueue pools, ${stats.totalPoolClients} pool clients`;
|
|
41
|
+
if (logger) {
|
|
42
|
+
logger.info('postgres-connection-stats', {
|
|
43
|
+
...stats,
|
|
44
|
+
message
|
|
45
|
+
});
|
|
46
|
+
}
|
|
47
|
+
else {
|
|
48
|
+
console.log(message, stats);
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
/**
|
|
52
|
+
* Check taskQueue pooling effectiveness - returns metrics about connection reuse
|
|
53
|
+
*/
|
|
54
|
+
static getPoolingEffectiveness() {
|
|
55
|
+
const stats = this.getConnectionStats();
|
|
56
|
+
const totalReuses = stats.taskQueueDetails.reduce((sum, detail) => sum + detail.reusedCount, 0);
|
|
57
|
+
const averageReusesPerPool = stats.taskQueueConnections > 0 ? totalReuses / stats.taskQueueConnections : 0;
|
|
58
|
+
const poolingEfficiency = stats.totalConnections > 0 ? (stats.taskQueueConnections / stats.totalConnections) * 100 : 0;
|
|
59
|
+
return {
|
|
60
|
+
totalConnections: stats.totalConnections,
|
|
61
|
+
taskQueuePools: stats.taskQueueConnections,
|
|
62
|
+
totalReuses,
|
|
63
|
+
averageReusesPerPool: Math.round(averageReusesPerPool * 100) / 100,
|
|
64
|
+
poolingEfficiency: Math.round(poolingEfficiency * 100) / 100,
|
|
65
|
+
};
|
|
66
|
+
}
|
|
18
67
|
async createConnection(clientConstructor, options, config = {}) {
|
|
19
68
|
try {
|
|
20
69
|
let connection;
|
|
@@ -55,11 +104,20 @@ class PostgresConnection extends __1.AbstractConnection {
|
|
|
55
104
|
}
|
|
56
105
|
return this.poolClientInstance || this.connection;
|
|
57
106
|
}
|
|
107
|
+
/**
|
|
108
|
+
* Get the connection ID for monitoring purposes
|
|
109
|
+
*/
|
|
110
|
+
getConnectionId() {
|
|
111
|
+
return this.id;
|
|
112
|
+
}
|
|
58
113
|
static async disconnectAll() {
|
|
114
|
+
//log stats
|
|
115
|
+
//this.logConnectionStats();
|
|
59
116
|
if (!this.disconnecting) {
|
|
60
117
|
this.disconnecting = true;
|
|
61
118
|
await this.disconnectPoolClients();
|
|
62
119
|
await this.disconnectConnections();
|
|
120
|
+
this.taskQueueConnections.clear();
|
|
63
121
|
this.disconnecting = false;
|
|
64
122
|
}
|
|
65
123
|
}
|
|
@@ -81,6 +139,53 @@ class PostgresConnection extends __1.AbstractConnection {
|
|
|
81
139
|
static isPoolClient(client) {
|
|
82
140
|
return !(isNaN(client?.totalCount) && isNaN(client?.idleCount));
|
|
83
141
|
}
|
|
142
|
+
/**
|
|
143
|
+
* Creates a taskQueue-based connection key for connection pooling.
|
|
144
|
+
* This allows multiple providers (store, sub, stream) to reuse the same connection
|
|
145
|
+
* when they share the same taskQueue and database configuration.
|
|
146
|
+
*/
|
|
147
|
+
static createTaskQueueConnectionKey(taskQueue, options, provider) {
|
|
148
|
+
const configHash = (0, utils_1.hashOptions)(options);
|
|
149
|
+
const providerType = provider?.split('.')[0] || 'postgres';
|
|
150
|
+
return `${providerType}:${taskQueue || 'default'}:${configHash}`;
|
|
151
|
+
}
|
|
152
|
+
/**
|
|
153
|
+
* Gets or creates a PostgreSQL connection based on taskQueue and database configuration.
|
|
154
|
+
* If a connection already exists for the same taskQueue + config, it will be reused.
|
|
155
|
+
* This optimization reduces connection overhead for PostgreSQL providers.
|
|
156
|
+
*/
|
|
157
|
+
static async getOrCreateTaskQueueConnection(id, taskQueue, clientConstructor, options, config = {}) {
|
|
158
|
+
// Only use taskQueue pooling for PostgreSQL providers
|
|
159
|
+
if (!taskQueue || !config.provider?.startsWith('postgres')) {
|
|
160
|
+
return await this.connect(id, clientConstructor, options, config);
|
|
161
|
+
}
|
|
162
|
+
const connectionKey = this.createTaskQueueConnectionKey(taskQueue, options, config.provider);
|
|
163
|
+
// Check if we already have a connection for this taskQueue + config
|
|
164
|
+
if (this.taskQueueConnections.has(connectionKey)) {
|
|
165
|
+
const existingConnection = this.taskQueueConnections.get(connectionKey);
|
|
166
|
+
// Track reuse count for monitoring
|
|
167
|
+
existingConnection.reusedCount = (existingConnection.reusedCount || 0) + 1;
|
|
168
|
+
this.logger.debug('postgres-connection-reused', {
|
|
169
|
+
connectionKey,
|
|
170
|
+
taskQueue,
|
|
171
|
+
originalId: existingConnection.id,
|
|
172
|
+
newId: id,
|
|
173
|
+
reuseCount: existingConnection.reusedCount,
|
|
174
|
+
});
|
|
175
|
+
return existingConnection;
|
|
176
|
+
}
|
|
177
|
+
// Create new connection and cache it for the taskQueue
|
|
178
|
+
const newConnection = await this.connect(id, clientConstructor, options, config);
|
|
179
|
+
// Initialize reuse tracking
|
|
180
|
+
newConnection.reusedCount = 0;
|
|
181
|
+
this.taskQueueConnections.set(connectionKey, newConnection);
|
|
182
|
+
this.logger.debug('postgres-connection-created-for-taskqueue', {
|
|
183
|
+
connectionKey,
|
|
184
|
+
taskQueue,
|
|
185
|
+
connectionId: id,
|
|
186
|
+
});
|
|
187
|
+
return newConnection;
|
|
188
|
+
}
|
|
84
189
|
static async getTransactionClient(transactionClient) {
|
|
85
190
|
let client;
|
|
86
191
|
let type;
|
|
@@ -100,3 +205,5 @@ exports.PostgresConnection = PostgresConnection;
|
|
|
100
205
|
PostgresConnection.poolClientInstances = new Set();
|
|
101
206
|
//statically track all connections (//call 'end')
|
|
102
207
|
PostgresConnection.connectionInstances = new Set();
|
|
208
|
+
//track connections by taskQueue + database config for reuse
|
|
209
|
+
PostgresConnection.taskQueueConnections = new Map();
|
|
@@ -264,6 +264,14 @@ declare class HotMesh {
|
|
|
264
264
|
* @private
|
|
265
265
|
*/
|
|
266
266
|
doWork(config: HotMeshConfig, logger: ILogger): Promise<void>;
|
|
267
|
+
/**
|
|
268
|
+
* Initialize task queue with proper precedence:
|
|
269
|
+
* 1. Use component-specific queue if set (engine/worker)
|
|
270
|
+
* 2. Use global config queue if set
|
|
271
|
+
* 3. Use default queue as fallback
|
|
272
|
+
* @private
|
|
273
|
+
*/
|
|
274
|
+
private initTaskQueue;
|
|
267
275
|
/**
|
|
268
276
|
* Starts a workflow
|
|
269
277
|
* @example
|
|
@@ -275,6 +275,8 @@ class HotMesh {
|
|
|
275
275
|
if (config.engine.connection.readonly) {
|
|
276
276
|
config.engine.readonly = true;
|
|
277
277
|
}
|
|
278
|
+
// Initialize task queue for engine
|
|
279
|
+
config.engine.taskQueue = this.initTaskQueue(config.engine.taskQueue, config.taskQueue);
|
|
278
280
|
await factory_1.ConnectorService.initClients(config.engine);
|
|
279
281
|
this.engine = await engine_1.EngineService.init(this.namespace, this.appId, this.guid, config, logger);
|
|
280
282
|
}
|
|
@@ -308,8 +310,33 @@ class HotMesh {
|
|
|
308
310
|
* @private
|
|
309
311
|
*/
|
|
310
312
|
async doWork(config, logger) {
|
|
313
|
+
// Initialize task queues for workers
|
|
314
|
+
if (config.workers) {
|
|
315
|
+
for (const worker of config.workers) {
|
|
316
|
+
worker.taskQueue = this.initTaskQueue(worker.taskQueue, config.taskQueue);
|
|
317
|
+
}
|
|
318
|
+
}
|
|
311
319
|
this.workers = await worker_1.WorkerService.init(this.namespace, this.appId, this.guid, config, logger);
|
|
312
320
|
}
|
|
321
|
+
/**
|
|
322
|
+
* Initialize task queue with proper precedence:
|
|
323
|
+
* 1. Use component-specific queue if set (engine/worker)
|
|
324
|
+
* 2. Use global config queue if set
|
|
325
|
+
* 3. Use default queue as fallback
|
|
326
|
+
* @private
|
|
327
|
+
*/
|
|
328
|
+
initTaskQueue(componentQueue, globalQueue) {
|
|
329
|
+
// Component-specific queue takes precedence
|
|
330
|
+
if (componentQueue) {
|
|
331
|
+
return componentQueue;
|
|
332
|
+
}
|
|
333
|
+
// Global config queue is next
|
|
334
|
+
if (globalQueue) {
|
|
335
|
+
return globalQueue;
|
|
336
|
+
}
|
|
337
|
+
// Default queue as fallback
|
|
338
|
+
return enums_1.DEFAULT_TASK_QUEUE;
|
|
339
|
+
}
|
|
313
340
|
// ************* PUB/SUB METHODS *************
|
|
314
341
|
/**
|
|
315
342
|
* Starts a workflow
|
|
@@ -60,7 +60,7 @@ export declare class ClientService {
|
|
|
60
60
|
/**
|
|
61
61
|
* @private
|
|
62
62
|
*/
|
|
63
|
-
getHotMeshClient: (
|
|
63
|
+
getHotMeshClient: (taskQueue: string | null, namespace?: string) => Promise<HotMesh>;
|
|
64
64
|
/**
|
|
65
65
|
* Creates a stream where messages can be published to ensure there is a
|
|
66
66
|
* channel in place when the message arrives (a race condition for those
|
|
@@ -54,7 +54,7 @@ class ClientService {
|
|
|
54
54
|
/**
|
|
55
55
|
* @private
|
|
56
56
|
*/
|
|
57
|
-
this.getHotMeshClient = async (
|
|
57
|
+
this.getHotMeshClient = async (taskQueue, namespace) => {
|
|
58
58
|
//namespace isolation requires the connection options to be hashed
|
|
59
59
|
//as multiple intersecting databases can be used by the same service
|
|
60
60
|
//hashing options allows for reuse of the same connection without risk of
|
|
@@ -71,6 +71,7 @@ class ClientService {
|
|
|
71
71
|
const readonly = this.connection.readonly ?? undefined;
|
|
72
72
|
let hotMeshClient = hotmesh_1.HotMesh.init({
|
|
73
73
|
appId: targetNS,
|
|
74
|
+
taskQueue,
|
|
74
75
|
logLevel: enums_1.HMSH_LOGLEVEL,
|
|
75
76
|
engine: {
|
|
76
77
|
readonly,
|
|
@@ -130,7 +131,7 @@ class ClientService {
|
|
|
130
131
|
const spn = options.workflowSpan;
|
|
131
132
|
//hotmesh `topic` is equivalent to `queue+workflowname` pattern in other systems
|
|
132
133
|
const workflowTopic = `${taskQueueName}-${workflowName}`;
|
|
133
|
-
const hotMeshClient = await this.getHotMeshClient(
|
|
134
|
+
const hotMeshClient = await this.getHotMeshClient(taskQueueName, options.namespace);
|
|
134
135
|
//verify that the stream channel exists before enqueueing
|
|
135
136
|
await this.verifyStream(hotMeshClient, workflowTopic, options.namespace);
|
|
136
137
|
const payload = {
|
|
@@ -182,7 +183,8 @@ class ClientService {
|
|
|
182
183
|
* ```
|
|
183
184
|
*/
|
|
184
185
|
hook: async (options) => {
|
|
185
|
-
const
|
|
186
|
+
const taskQueue = options.taskQueue ?? options.entity;
|
|
187
|
+
const workflowTopic = `${taskQueue}-${options.entity ?? options.workflowName}`;
|
|
186
188
|
const payload = {
|
|
187
189
|
arguments: [...options.args],
|
|
188
190
|
id: options.workflowId,
|
|
@@ -192,7 +194,7 @@ class ClientService {
|
|
|
192
194
|
maximumInterval: (0, utils_1.s)(options.config?.maximumInterval || enums_1.HMSH_MEMFLOW_MAX_INTERVAL),
|
|
193
195
|
};
|
|
194
196
|
//seed search data before entering
|
|
195
|
-
const hotMeshClient = await this.getHotMeshClient(
|
|
197
|
+
const hotMeshClient = await this.getHotMeshClient(taskQueue, options.namespace);
|
|
196
198
|
const msgId = await hotMeshClient.hook(`${hotMeshClient.appId}.flow.signal`, payload, types_1.StreamStatus.PENDING, 202);
|
|
197
199
|
//todo: commit search data BEFORE enqueuing hook
|
|
198
200
|
if (options.search?.data) {
|
|
@@ -222,7 +224,7 @@ class ClientService {
|
|
|
222
224
|
*/
|
|
223
225
|
getHandle: async (taskQueue, workflowName, workflowId, namespace) => {
|
|
224
226
|
const workflowTopic = `${taskQueue}-${workflowName}`;
|
|
225
|
-
const hotMeshClient = await this.getHotMeshClient(
|
|
227
|
+
const hotMeshClient = await this.getHotMeshClient(taskQueue, namespace);
|
|
226
228
|
return new handle_1.WorkflowHandleService(hotMeshClient, workflowTopic, workflowId);
|
|
227
229
|
},
|
|
228
230
|
/**
|
|
@@ -249,7 +251,7 @@ class ClientService {
|
|
|
249
251
|
*/
|
|
250
252
|
search: async (taskQueue, workflowName, namespace, index, ...query) => {
|
|
251
253
|
const workflowTopic = `${taskQueue}-${workflowName}`;
|
|
252
|
-
const hotMeshClient = await this.getHotMeshClient(
|
|
254
|
+
const hotMeshClient = await this.getHotMeshClient(taskQueue, namespace);
|
|
253
255
|
try {
|
|
254
256
|
return await this.search(hotMeshClient, index, query);
|
|
255
257
|
}
|
|
@@ -174,6 +174,7 @@ class WorkerService {
|
|
|
174
174
|
const targetTopic = `${optionsHash}.${targetNamespace}.${activityTopic}`;
|
|
175
175
|
const hotMeshWorker = await hotmesh_1.HotMesh.init({
|
|
176
176
|
guid: config.guid ? `${config.guid}XA` : undefined,
|
|
177
|
+
taskQueue: config.taskQueue,
|
|
177
178
|
logLevel: config.options?.logLevel ?? enums_1.HMSH_LOGLEVEL,
|
|
178
179
|
appId: targetNamespace,
|
|
179
180
|
engine: { connection: providerConfig },
|
|
@@ -258,6 +259,7 @@ class WorkerService {
|
|
|
258
259
|
const targetTopic = `${optionsHash}.${targetNamespace}.${workflowTopic}`;
|
|
259
260
|
const hotMeshWorker = await hotmesh_1.HotMesh.init({
|
|
260
261
|
guid: config.guid,
|
|
262
|
+
taskQueue: config.taskQueue,
|
|
261
263
|
logLevel: config.options?.logLevel ?? enums_1.HMSH_LOGLEVEL,
|
|
262
264
|
appId: config.namespace ?? factory_1.APP_ID,
|
|
263
265
|
engine: { connection: providerConfig },
|
|
@@ -518,6 +520,7 @@ WorkerService.getHotMesh = async (workflowTopic, config, options) => {
|
|
|
518
520
|
const hotMeshClient = hotmesh_1.HotMesh.init({
|
|
519
521
|
logLevel: options?.logLevel ?? enums_1.HMSH_LOGLEVEL,
|
|
520
522
|
appId: targetNamespace,
|
|
523
|
+
taskQueue: config.taskQueue,
|
|
521
524
|
engine: {
|
|
522
525
|
connection: { ...config?.connection },
|
|
523
526
|
},
|
|
@@ -23,15 +23,21 @@ const KVTables = (context) => ({
|
|
|
23
23
|
client = transactionClient;
|
|
24
24
|
}
|
|
25
25
|
try {
|
|
26
|
-
//
|
|
26
|
+
// First, check if tables already exist (no lock needed)
|
|
27
|
+
const tablesExist = await this.checkIfTablesExist(client, appName);
|
|
28
|
+
if (tablesExist) {
|
|
29
|
+
// Tables already exist, no need to acquire lock or create tables
|
|
30
|
+
return;
|
|
31
|
+
}
|
|
32
|
+
// Tables don't exist, need to acquire lock and create them
|
|
27
33
|
const lockId = this.getAdvisoryLockId(appName);
|
|
28
34
|
const lockResult = await client.query('SELECT pg_try_advisory_lock($1) AS locked', [lockId]);
|
|
29
35
|
if (lockResult.rows[0].locked) {
|
|
30
36
|
// Begin transaction
|
|
31
37
|
await client.query('BEGIN');
|
|
32
|
-
//
|
|
33
|
-
const
|
|
34
|
-
if (
|
|
38
|
+
// Double-check tables don't exist (race condition safety)
|
|
39
|
+
const tablesStillMissing = !(await this.checkIfTablesExist(client, appName));
|
|
40
|
+
if (tablesStillMissing) {
|
|
35
41
|
await this.createTables(client, appName);
|
|
36
42
|
}
|
|
37
43
|
// Commit transaction
|
|
@@ -90,11 +96,18 @@ const KVTables = (context) => ({
|
|
|
90
96
|
client = transactionClient;
|
|
91
97
|
}
|
|
92
98
|
try {
|
|
99
|
+
// Check if tables exist directly (most efficient check)
|
|
100
|
+
const tablesExist = await this.checkIfTablesExist(client, appName);
|
|
101
|
+
if (tablesExist) {
|
|
102
|
+
// Tables now exist, deployment is complete
|
|
103
|
+
return;
|
|
104
|
+
}
|
|
105
|
+
// Fallback: check if the lock has been released (indicates completion)
|
|
93
106
|
const lockCheck = await client.query("SELECT NOT EXISTS (SELECT 1 FROM pg_locks WHERE locktype = 'advisory' AND objid = $1::bigint) AS unlocked", [lockId]);
|
|
94
107
|
if (lockCheck.rows[0].unlocked) {
|
|
95
108
|
// Lock has been released, tables should exist now
|
|
96
|
-
const
|
|
97
|
-
if (
|
|
109
|
+
const tablesExistAfterLock = await this.checkIfTablesExist(client, appName);
|
|
110
|
+
if (tablesExistAfterLock) {
|
|
98
111
|
return;
|
|
99
112
|
}
|
|
100
113
|
}
|
|
@@ -1073,9 +1073,20 @@ class PostgresStoreService extends __1.StoreService {
|
|
|
1073
1073
|
try {
|
|
1074
1074
|
// Set up LISTEN for time notifications
|
|
1075
1075
|
await this.pgClient.query(`LISTEN "${channelName}"`);
|
|
1076
|
-
// Set up notification handler
|
|
1076
|
+
// Set up notification handler with channel filtering
|
|
1077
1077
|
this.pgClient.on('notification', (notification) => {
|
|
1078
|
-
|
|
1078
|
+
// Only handle time notifications (channels starting with "time_hooks_")
|
|
1079
|
+
// Ignore sub and stream notifications from other providers
|
|
1080
|
+
if (notification.channel.startsWith('time_hooks_')) {
|
|
1081
|
+
this.handleTimeNotification(notification, timeEventCallback);
|
|
1082
|
+
}
|
|
1083
|
+
else {
|
|
1084
|
+
// This is likely a notification from sub or stream provider, ignore it
|
|
1085
|
+
this.logger.debug('postgres-store-ignoring-non-time-notification', {
|
|
1086
|
+
channel: notification.channel,
|
|
1087
|
+
payloadPreview: notification.payload.substring(0, 100)
|
|
1088
|
+
});
|
|
1089
|
+
}
|
|
1079
1090
|
});
|
|
1080
1091
|
this.logger.debug('postgres-time-scout-notifications-started', {
|
|
1081
1092
|
appId: this.appId,
|
|
@@ -9,15 +9,18 @@ declare class PostgresStreamService extends StreamService<PostgresClientType & P
|
|
|
9
9
|
namespace: string;
|
|
10
10
|
appId: string;
|
|
11
11
|
logger: ILogger;
|
|
12
|
-
private
|
|
12
|
+
private static clientNotificationConsumers;
|
|
13
|
+
private static clientNotificationHandlers;
|
|
14
|
+
private static clientFallbackPollers;
|
|
15
|
+
private instanceNotificationConsumers;
|
|
13
16
|
private notificationHandlerBound;
|
|
14
|
-
private fallbackIntervalId;
|
|
15
17
|
constructor(streamClient: PostgresClientType & ProviderClient, storeClient: ProviderClient, config?: StreamConfig);
|
|
16
18
|
init(namespace: string, appId: string, logger: ILogger): Promise<void>;
|
|
19
|
+
private setupClientNotificationHandler;
|
|
20
|
+
private startClientFallbackPoller;
|
|
17
21
|
private isNotificationsEnabled;
|
|
18
22
|
private getFallbackInterval;
|
|
19
23
|
private getNotificationTimeout;
|
|
20
|
-
private startFallbackPoller;
|
|
21
24
|
private checkForMissedMessages;
|
|
22
25
|
private handleNotification;
|
|
23
26
|
private fetchAndDeliverMessages;
|