@hotmeshio/hotmesh 0.7.0 → 0.8.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.
- package/.claude/settings.local.json +7 -0
- package/README.md +1 -1
- package/build/index.d.ts +1 -3
- package/build/index.js +1 -5
- package/build/modules/utils.js +3 -31
- package/build/package.json +16 -27
- package/build/services/activities/activity.d.ts +43 -6
- package/build/services/activities/activity.js +262 -54
- package/build/services/activities/await.js +2 -2
- package/build/services/activities/cycle.js +1 -1
- package/build/services/activities/hook.d.ts +5 -0
- package/build/services/activities/hook.js +22 -19
- package/build/services/activities/interrupt.js +17 -25
- package/build/services/activities/signal.d.ts +4 -2
- package/build/services/activities/signal.js +27 -24
- package/build/services/activities/worker.js +2 -2
- package/build/services/collator/index.d.ts +123 -25
- package/build/services/collator/index.js +224 -101
- package/build/services/connector/factory.d.ts +1 -1
- package/build/services/connector/factory.js +1 -11
- package/build/services/engine/index.d.ts +5 -5
- package/build/services/engine/index.js +36 -15
- package/build/services/router/consumption/index.js +1 -1
- package/build/services/search/factory.js +1 -9
- package/build/services/store/factory.js +1 -9
- package/build/services/store/index.d.ts +5 -0
- package/build/services/store/providers/postgres/kvsql.d.ts +4 -0
- package/build/services/store/providers/postgres/kvsql.js +4 -0
- package/build/services/store/providers/postgres/kvtransaction.d.ts +2 -0
- package/build/services/store/providers/postgres/kvtransaction.js +23 -0
- package/build/services/store/providers/postgres/kvtypes/hash/basic.d.ts +51 -0
- package/build/services/store/providers/postgres/kvtypes/hash/basic.js +193 -1
- package/build/services/store/providers/postgres/kvtypes/hash/index.d.ts +4 -0
- package/build/services/store/providers/postgres/kvtypes/hash/index.js +6 -0
- package/build/services/store/providers/postgres/postgres.d.ts +20 -0
- package/build/services/store/providers/postgres/postgres.js +38 -1
- package/build/services/stream/factory.js +1 -17
- package/build/services/stream/providers/postgres/scout.js +2 -2
- package/build/services/sub/factory.js +1 -9
- package/build/services/sub/index.d.ts +1 -1
- package/build/services/sub/providers/postgres/postgres.d.ts +1 -1
- package/build/services/sub/providers/postgres/postgres.js +25 -10
- package/build/services/task/index.d.ts +1 -1
- package/build/services/task/index.js +2 -6
- package/build/types/index.d.ts +0 -1
- package/build/types/index.js +1 -4
- package/build/types/provider.d.ts +1 -1
- package/index.ts +0 -4
- package/package.json +16 -27
- package/build/services/connector/providers/ioredis.d.ts +0 -9
- package/build/services/connector/providers/ioredis.js +0 -26
- package/build/services/connector/providers/redis.d.ts +0 -9
- package/build/services/connector/providers/redis.js +0 -38
- package/build/services/search/providers/redis/ioredis.d.ts +0 -23
- package/build/services/search/providers/redis/ioredis.js +0 -189
- package/build/services/search/providers/redis/redis.d.ts +0 -23
- package/build/services/search/providers/redis/redis.js +0 -202
- package/build/services/store/providers/redis/_base.d.ts +0 -137
- package/build/services/store/providers/redis/_base.js +0 -980
- package/build/services/store/providers/redis/ioredis.d.ts +0 -20
- package/build/services/store/providers/redis/ioredis.js +0 -190
- package/build/services/store/providers/redis/redis.d.ts +0 -18
- package/build/services/store/providers/redis/redis.js +0 -199
- package/build/services/stream/providers/redis/ioredis.d.ts +0 -61
- package/build/services/stream/providers/redis/ioredis.js +0 -272
- package/build/services/stream/providers/redis/redis.d.ts +0 -61
- package/build/services/stream/providers/redis/redis.js +0 -305
- package/build/services/sub/providers/redis/ioredis.d.ts +0 -20
- package/build/services/sub/providers/redis/ioredis.js +0 -161
- package/build/services/sub/providers/redis/redis.d.ts +0 -18
- package/build/services/sub/providers/redis/redis.js +0 -148
- package/build/types/redis.d.ts +0 -258
- package/build/types/redis.js +0 -11
|
@@ -3,20 +3,12 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
3
3
|
exports.SearchServiceFactory = void 0;
|
|
4
4
|
const utils_1 = require("../../modules/utils");
|
|
5
5
|
const postgres_1 = require("./providers/postgres/postgres");
|
|
6
|
-
const ioredis_1 = require("./providers/redis/ioredis");
|
|
7
|
-
const redis_1 = require("./providers/redis/redis");
|
|
8
6
|
class SearchServiceFactory {
|
|
9
7
|
static async init(providerClient, storeProviderClient, namespace, appId, logger) {
|
|
10
8
|
let service;
|
|
11
9
|
if ((0, utils_1.identifyProvider)(providerClient) === 'postgres') {
|
|
12
10
|
service = new postgres_1.PostgresSearchService(providerClient, storeProviderClient);
|
|
13
|
-
}
|
|
14
|
-
else if ((0, utils_1.identifyProvider)(providerClient) === 'redis') {
|
|
15
|
-
service = new redis_1.RedisSearchService(providerClient, storeProviderClient);
|
|
16
|
-
}
|
|
17
|
-
else {
|
|
18
|
-
service = new ioredis_1.IORedisSearchService(providerClient, storeProviderClient);
|
|
19
|
-
}
|
|
11
|
+
} //etc
|
|
20
12
|
await service.init(namespace, appId, logger);
|
|
21
13
|
return service;
|
|
22
14
|
}
|
|
@@ -2,19 +2,11 @@
|
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.StoreServiceFactory = void 0;
|
|
4
4
|
const utils_1 = require("../../modules/utils");
|
|
5
|
-
const ioredis_1 = require("./providers/redis/ioredis");
|
|
6
|
-
const redis_1 = require("./providers/redis/redis");
|
|
7
5
|
const postgres_1 = require("./providers/postgres/postgres");
|
|
8
6
|
class StoreServiceFactory {
|
|
9
7
|
static async init(providerClient, namespace, appId, logger) {
|
|
10
8
|
let service;
|
|
11
|
-
if ((0, utils_1.identifyProvider)(providerClient) === '
|
|
12
|
-
service = new redis_1.RedisStoreService(providerClient);
|
|
13
|
-
}
|
|
14
|
-
else if ((0, utils_1.identifyProvider)(providerClient) === 'ioredis') {
|
|
15
|
-
service = new ioredis_1.IORedisStoreService(providerClient);
|
|
16
|
-
}
|
|
17
|
-
else if ((0, utils_1.identifyProvider)(providerClient) === 'postgres') {
|
|
9
|
+
if ((0, utils_1.identifyProvider)(providerClient) === 'postgres') {
|
|
18
10
|
service = new postgres_1.PostgresStoreService(providerClient);
|
|
19
11
|
} //etc
|
|
20
12
|
await service.init(namespace, appId, logger);
|
|
@@ -40,6 +40,10 @@ declare abstract class StoreService<Provider extends ProviderClient, Transaction
|
|
|
40
40
|
abstract getJobStats(jobKeys: string[]): Promise<JobStatsRange>;
|
|
41
41
|
abstract getJobIds(indexKeys: string[], idRange: [number, number]): Promise<IdsData>;
|
|
42
42
|
abstract setStatus(collationKeyStatus: number, jobId: string, appId: string, transaction?: TransactionProvider): Promise<any>;
|
|
43
|
+
abstract setStatusAndCollateGuid(statusDelta: number, // typically (N - 1)
|
|
44
|
+
threshold: number, // typically 0 (but supports 0,1,12,...)
|
|
45
|
+
jobId: string, appId: string, guidField: string, //
|
|
46
|
+
guidWeight: number, transaction?: ProviderTransaction): Promise<any>;
|
|
43
47
|
abstract getStatus(jobId: string, appId: string): Promise<number>;
|
|
44
48
|
abstract setStateNX(jobId: string, appId: string, status?: number, entity?: string): Promise<boolean>;
|
|
45
49
|
abstract setState(state: StringAnyType, status: number | null, jobId: string, symbolNames: string[], dIds: StringStringType, transaction?: TransactionProvider): Promise<string>;
|
|
@@ -47,6 +51,7 @@ declare abstract class StoreService<Provider extends ProviderClient, Transaction
|
|
|
47
51
|
abstract getState(jobId: string, consumes: Consumes, dIds: StringStringType): Promise<[StringAnyType, number] | undefined>;
|
|
48
52
|
abstract getRaw(jobId: string): Promise<StringStringType>;
|
|
49
53
|
abstract collate(jobId: string, activityId: string, amount: number, dIds: StringStringType, transaction?: TransactionProvider): Promise<number>;
|
|
54
|
+
abstract collateLeg2Entry(jobId: string, activityId: string, guid: string, dIds: StringStringType, transaction?: TransactionProvider): Promise<[number, number]>;
|
|
50
55
|
abstract collateSynthetic(jobId: string, guid: string, amount: number, transaction?: TransactionProvider): Promise<number>;
|
|
51
56
|
abstract getSchema(activityId: string, appVersion: AppVID): Promise<any>;
|
|
52
57
|
abstract getSchemas(appVersion: AppVID): Promise<Record<string, any>>;
|
|
@@ -58,6 +58,10 @@ export declare class KVSQL {
|
|
|
58
58
|
_hmget: (key: string, fields: string[]) => import("./kvtypes/hash/types").SqlResult;
|
|
59
59
|
hgetall: (key: string, multi?: ProviderTransaction) => Promise<Record<string, string>>;
|
|
60
60
|
hincrbyfloat: (key: string, field: string, increment: number, multi?: ProviderTransaction) => Promise<number>;
|
|
61
|
+
collateLeg2Entry: (key: string, activityField: string, increment: number, guidField: string, multi?: ProviderTransaction) => Promise<[number, number]>;
|
|
62
|
+
_collateLeg2Entry: (key: string, activityField: string, increment: number, guidField: string) => import("./kvtypes/hash/types").SqlResult;
|
|
63
|
+
setStatusAndCollateGuid: (key: string, statusDelta: number, threshold: number, guidField: string, guidWeight: number, multi?: ProviderTransaction) => Promise<number>;
|
|
64
|
+
_setStatusAndCollateGuid: (key: string, statusDelta: number, threshold: number, guidField: string, guidWeight: number) => import("./kvtypes/hash/types").SqlResult;
|
|
61
65
|
_hincrbyfloat: (key: string, field: string, increment: number) => import("./kvtypes/hash/types").SqlResult;
|
|
62
66
|
hscan: (key: string, cursor: string, count?: number, pattern?: string, multi?: ProviderTransaction) => Promise<import("./kvtypes/hash/index").HScanResult>;
|
|
63
67
|
_hscan: (key: string, cursor: string, count: number, pattern?: string) => import("./kvtypes/hash/types").SqlResult;
|
|
@@ -34,6 +34,10 @@ class KVSQL {
|
|
|
34
34
|
this._hmget = (...args) => this.hash._hmget(...args);
|
|
35
35
|
this.hgetall = (...args) => this.hash.hgetall(...args);
|
|
36
36
|
this.hincrbyfloat = (...args) => this.hash.hincrbyfloat(...args);
|
|
37
|
+
this.collateLeg2Entry = (...args) => this.hash.collateLeg2Entry(...args);
|
|
38
|
+
this._collateLeg2Entry = (...args) => this.hash._collateLeg2Entry(...args);
|
|
39
|
+
this.setStatusAndCollateGuid = (...args) => this.hash.setStatusAndCollateGuid(...args);
|
|
40
|
+
this._setStatusAndCollateGuid = (...args) => this.hash._setStatusAndCollateGuid(...args);
|
|
37
41
|
this._hincrbyfloat = (...args) => this.hash._hincrbyfloat(...args);
|
|
38
42
|
this.hscan = (...args) => this.hash.hscan(...args);
|
|
39
43
|
this._hscan = (...args) => this.hash._hscan(...args);
|
|
@@ -31,6 +31,8 @@ export declare class KVTransaction implements KVSQLProviderTransaction {
|
|
|
31
31
|
zrem(key: string, member: string): this;
|
|
32
32
|
zrank(key: string, member: string): this;
|
|
33
33
|
scan(cursor: number, count?: number): this;
|
|
34
|
+
collateLeg2Entry(key: string, activityField: string, increment: number, guidField: string): this;
|
|
35
|
+
setStatusAndCollateGuid(key: string, statusDelta: number, threshold: number, guidField: string, guidWeight: number): this;
|
|
34
36
|
rename(oldKey: string, newKey: string): this;
|
|
35
37
|
exec(): Promise<any[]>;
|
|
36
38
|
}
|
|
@@ -8,8 +8,13 @@ const pg_format_1 = __importDefault(require("pg-format"));
|
|
|
8
8
|
/**
|
|
9
9
|
* Utility function to format SQL commands with parameters.
|
|
10
10
|
* Replaces $1, $2, etc., with %L or %s based on parameter types.
|
|
11
|
+
* Commands with no parameters (e.g., NOTIFY with inline values)
|
|
12
|
+
* are returned as-is to avoid pg-format corrupting the SQL.
|
|
11
13
|
*/
|
|
12
14
|
function formatSqlCommand(sql, params) {
|
|
15
|
+
if (!params || params.length === 0) {
|
|
16
|
+
return sql;
|
|
17
|
+
}
|
|
13
18
|
const formatParams = [];
|
|
14
19
|
// Replace $1, $2, etc., with %L or %s and collect parameters
|
|
15
20
|
const formattedSql = sql.replace(/\$(\d+)/g, (match, p1) => {
|
|
@@ -182,6 +187,18 @@ class KVTransaction {
|
|
|
182
187
|
};
|
|
183
188
|
return this.addCommand(sql, params, 'object', transform);
|
|
184
189
|
}
|
|
190
|
+
collateLeg2Entry(key, activityField, increment, guidField) {
|
|
191
|
+
const { sql, params } = this.kvsql._collateLeg2Entry(key, activityField, increment, guidField);
|
|
192
|
+
return this.addCommand(sql, params, 'array', (rows) => {
|
|
193
|
+
return [parseFloat(rows[0].activity_value), parseFloat(rows[0].guid_value)];
|
|
194
|
+
});
|
|
195
|
+
}
|
|
196
|
+
setStatusAndCollateGuid(key, statusDelta, threshold, guidField, guidWeight) {
|
|
197
|
+
const { sql, params } = this.kvsql._setStatusAndCollateGuid(key, statusDelta, threshold, guidField, guidWeight);
|
|
198
|
+
return this.addCommand(sql, params, 'number', (rows) => {
|
|
199
|
+
return parseFloat(rows[0].value);
|
|
200
|
+
});
|
|
201
|
+
}
|
|
185
202
|
rename(oldKey, newKey) {
|
|
186
203
|
const { sql, params } = this.kvsql._rename(oldKey, newKey);
|
|
187
204
|
return this.addCommand(sql, params, 'void');
|
|
@@ -240,6 +257,12 @@ class KVTransaction {
|
|
|
240
257
|
return results;
|
|
241
258
|
}
|
|
242
259
|
catch (err) {
|
|
260
|
+
console.error('kvtransaction-exec-error', {
|
|
261
|
+
error: err.message,
|
|
262
|
+
commandCount: this.commands.length,
|
|
263
|
+
commandTypes: this.commands.map(c => c.returnType),
|
|
264
|
+
commandSqlPreviews: this.commands.map(c => c.sql.substring(0, 80)),
|
|
265
|
+
});
|
|
243
266
|
await client.query('ROLLBACK');
|
|
244
267
|
throw err;
|
|
245
268
|
}
|
|
@@ -7,6 +7,25 @@ export declare function createBasicOperations(context: HashContext['context']):
|
|
|
7
7
|
hmget(key: string, fields: string[], multi?: ProviderTransaction): Promise<(string | null)[]>;
|
|
8
8
|
hgetall(key: string, multi?: ProviderTransaction): Promise<Record<string, string>>;
|
|
9
9
|
hincrbyfloat(key: string, field: string, increment: number, multi?: ProviderTransaction): Promise<number>;
|
|
10
|
+
/**
|
|
11
|
+
* 2b) KVSQL METHOD: Leg2 Entry Compound
|
|
12
|
+
* --------------------------------------
|
|
13
|
+
* Atomically increments the activity Leg2 entry counter and seeds
|
|
14
|
+
* the GUID ledger with the ordinal IF NOT EXISTS.
|
|
15
|
+
*
|
|
16
|
+
* Returns: [activityValue, guidValue] as [number, number]
|
|
17
|
+
*/
|
|
18
|
+
collateLeg2Entry(key: string, activityField: string, increment: number, guidField: string, multi?: ProviderTransaction): Promise<[number, number]>;
|
|
19
|
+
/**
|
|
20
|
+
* 2) KVSQL METHOD (non-transactional + transactional)
|
|
21
|
+
* ---------------------------------------------------
|
|
22
|
+
* Matches hincrbyfloat() pattern:
|
|
23
|
+
* - when multi is present: enqueue command and return 0 immediately
|
|
24
|
+
* - when multi absent: execute immediately and return parsed numeric value
|
|
25
|
+
*
|
|
26
|
+
* Returns: thresholdHit (0/1) as number
|
|
27
|
+
*/
|
|
28
|
+
setStatusAndCollateGuid(key: string, statusDelta: number, threshold: number, guidField: string, guidWeight: number, multi?: ProviderTransaction): Promise<number>;
|
|
10
29
|
};
|
|
11
30
|
export declare function _hset(context: HashContext['context'], key: string, fields: Record<string, string>, options?: HSetOptions): SqlResult;
|
|
12
31
|
export declare function _hget(context: HashContext['context'], key: string, field: string): SqlResult;
|
|
@@ -14,3 +33,35 @@ export declare function _hdel(context: HashContext['context'], key: string, fiel
|
|
|
14
33
|
export declare function _hmget(context: HashContext['context'], key: string, fields: string[]): SqlResult;
|
|
15
34
|
export declare function _hgetall(context: HashContext['context'], key: string): SqlResult;
|
|
16
35
|
export declare function _hincrbyfloat(context: HashContext['context'], key: string, field: string, increment: number): SqlResult;
|
|
36
|
+
/**
|
|
37
|
+
* 3b) LOW-LEVEL SQL GENERATOR: Leg2 Entry Compound
|
|
38
|
+
* -------------------------------------------------
|
|
39
|
+
* Atomically:
|
|
40
|
+
* - increments the activity collation field by +1 (Leg2 entry counter)
|
|
41
|
+
* - seeds the GUID ledger with the ordinal (last 8 digits of activity value)
|
|
42
|
+
* IF the GUID row does not yet exist; returns the existing value if it does
|
|
43
|
+
* - returns both (activity_value, guid_value) for the caller
|
|
44
|
+
*
|
|
45
|
+
* The GUID seed uses ON CONFLICT DO UPDATE SET value = existing.value
|
|
46
|
+
* (a no-op update) so that RETURNING fires in both insert and conflict cases.
|
|
47
|
+
*/
|
|
48
|
+
export declare function _collateLeg2Entry(context: HashContext['context'], key: string, // jobKey
|
|
49
|
+
activityField: string, // serialized activity collation field name
|
|
50
|
+
increment: number, // always 1 for Leg2 entry
|
|
51
|
+
guidField: string): SqlResult;
|
|
52
|
+
/**
|
|
53
|
+
* 3) LOW-LEVEL SQL GENERATOR
|
|
54
|
+
* --------------------------
|
|
55
|
+
* This is the core compound statement. It must:
|
|
56
|
+
* - update jobs.status by statusDelta
|
|
57
|
+
* - compute thresholdHit (0/1) when status_after == threshold
|
|
58
|
+
* - increment the guidField by thresholdHit * guidWeight (typically 100B digit)
|
|
59
|
+
* - return thresholdHit as "value" so it fits the existing return parsing
|
|
60
|
+
*
|
|
61
|
+
* Notes:
|
|
62
|
+
* - Uses tableForKey(key, 'hash') which will resolve to the jobs table for job keys.
|
|
63
|
+
* - Assumes jobs_attributes table is `${jobsTableName}_attributes` (same as _hincrbyfloat)
|
|
64
|
+
* - Uses deriveType(guidField) to be consistent with your attribute typing system.
|
|
65
|
+
*/
|
|
66
|
+
export declare function _setStatusAndCollateGuid(context: HashContext['context'], key: string, // jobKey
|
|
67
|
+
statusDelta: number, threshold: number, guidField: string, guidWeight: number): SqlResult;
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports._hincrbyfloat = exports._hgetall = exports._hmget = exports._hdel = exports._hget = exports._hset = exports.createBasicOperations = void 0;
|
|
3
|
+
exports._setStatusAndCollateGuid = exports._collateLeg2Entry = exports._hincrbyfloat = exports._hgetall = exports._hmget = exports._hdel = exports._hget = exports._hset = exports.createBasicOperations = void 0;
|
|
4
4
|
const utils_1 = require("./utils");
|
|
5
5
|
function createBasicOperations(context) {
|
|
6
6
|
return {
|
|
@@ -184,6 +184,77 @@ function createBasicOperations(context) {
|
|
|
184
184
|
}
|
|
185
185
|
}
|
|
186
186
|
},
|
|
187
|
+
/**
|
|
188
|
+
* 2b) KVSQL METHOD: Leg2 Entry Compound
|
|
189
|
+
* --------------------------------------
|
|
190
|
+
* Atomically increments the activity Leg2 entry counter and seeds
|
|
191
|
+
* the GUID ledger with the ordinal IF NOT EXISTS.
|
|
192
|
+
*
|
|
193
|
+
* Returns: [activityValue, guidValue] as [number, number]
|
|
194
|
+
*/
|
|
195
|
+
async collateLeg2Entry(key, // jobKey
|
|
196
|
+
activityField, // serialized activity collation field
|
|
197
|
+
increment, // always 1
|
|
198
|
+
guidField, // GUID string
|
|
199
|
+
multi) {
|
|
200
|
+
const { sql, params } = _collateLeg2Entry(context, key, activityField, increment, guidField);
|
|
201
|
+
if (multi) {
|
|
202
|
+
multi.addCommand(sql, params, 'array', (rows) => {
|
|
203
|
+
return [parseFloat(rows[0].activity_value), parseFloat(rows[0].guid_value)];
|
|
204
|
+
});
|
|
205
|
+
return Promise.resolve([0, 0]);
|
|
206
|
+
}
|
|
207
|
+
else {
|
|
208
|
+
try {
|
|
209
|
+
const res = await context.pgClient.query(sql, params);
|
|
210
|
+
return [parseFloat(res.rows[0].activity_value), parseFloat(res.rows[0].guid_value)];
|
|
211
|
+
}
|
|
212
|
+
catch (error) {
|
|
213
|
+
if (error?.message?.includes('closed') ||
|
|
214
|
+
error?.message?.includes('queryable')) {
|
|
215
|
+
return [0, 0];
|
|
216
|
+
}
|
|
217
|
+
throw error;
|
|
218
|
+
}
|
|
219
|
+
}
|
|
220
|
+
},
|
|
221
|
+
/**
|
|
222
|
+
* 2) KVSQL METHOD (non-transactional + transactional)
|
|
223
|
+
* ---------------------------------------------------
|
|
224
|
+
* Matches hincrbyfloat() pattern:
|
|
225
|
+
* - when multi is present: enqueue command and return 0 immediately
|
|
226
|
+
* - when multi absent: execute immediately and return parsed numeric value
|
|
227
|
+
*
|
|
228
|
+
* Returns: thresholdHit (0/1) as number
|
|
229
|
+
*/
|
|
230
|
+
async setStatusAndCollateGuid(key, // jobKey
|
|
231
|
+
statusDelta, // semaphore delta
|
|
232
|
+
threshold, // desired threshold (usually 0)
|
|
233
|
+
guidField, // jobs_attributes.field for the guid ledger
|
|
234
|
+
guidWeight, // e.g. 100B digit increment
|
|
235
|
+
multi) {
|
|
236
|
+
const { sql, params } = _setStatusAndCollateGuid(context, key, statusDelta, threshold, guidField, guidWeight);
|
|
237
|
+
if (multi) {
|
|
238
|
+
multi.addCommand(sql, params, 'number', (rows) => {
|
|
239
|
+
return parseFloat(rows[0].value);
|
|
240
|
+
});
|
|
241
|
+
return Promise.resolve(0);
|
|
242
|
+
}
|
|
243
|
+
else {
|
|
244
|
+
try {
|
|
245
|
+
const res = await context.pgClient.query(sql, params);
|
|
246
|
+
return parseFloat(res.rows[0].value);
|
|
247
|
+
}
|
|
248
|
+
catch (error) {
|
|
249
|
+
// Connection closed during test cleanup - return 0
|
|
250
|
+
if (error?.message?.includes('closed') ||
|
|
251
|
+
error?.message?.includes('queryable')) {
|
|
252
|
+
return 0;
|
|
253
|
+
}
|
|
254
|
+
throw error;
|
|
255
|
+
}
|
|
256
|
+
}
|
|
257
|
+
},
|
|
187
258
|
};
|
|
188
259
|
}
|
|
189
260
|
exports.createBasicOperations = createBasicOperations;
|
|
@@ -508,3 +579,124 @@ function _hincrbyfloat(context, key, field, increment) {
|
|
|
508
579
|
}
|
|
509
580
|
}
|
|
510
581
|
exports._hincrbyfloat = _hincrbyfloat;
|
|
582
|
+
/**
|
|
583
|
+
* 3b) LOW-LEVEL SQL GENERATOR: Leg2 Entry Compound
|
|
584
|
+
* -------------------------------------------------
|
|
585
|
+
* Atomically:
|
|
586
|
+
* - increments the activity collation field by +1 (Leg2 entry counter)
|
|
587
|
+
* - seeds the GUID ledger with the ordinal (last 8 digits of activity value)
|
|
588
|
+
* IF the GUID row does not yet exist; returns the existing value if it does
|
|
589
|
+
* - returns both (activity_value, guid_value) for the caller
|
|
590
|
+
*
|
|
591
|
+
* The GUID seed uses ON CONFLICT DO UPDATE SET value = existing.value
|
|
592
|
+
* (a no-op update) so that RETURNING fires in both insert and conflict cases.
|
|
593
|
+
*/
|
|
594
|
+
function _collateLeg2Entry(context, key, // jobKey
|
|
595
|
+
activityField, // serialized activity collation field name
|
|
596
|
+
increment, // always 1 for Leg2 entry
|
|
597
|
+
guidField) {
|
|
598
|
+
const jobsTableName = context.tableForKey(key, 'hash');
|
|
599
|
+
if (!(0, utils_1.isJobsTable)(jobsTableName)) {
|
|
600
|
+
throw new Error(`_collateLeg2Entry requires a jobs table key; got table ${jobsTableName}`);
|
|
601
|
+
}
|
|
602
|
+
const attrsTable = `${jobsTableName}_attributes`;
|
|
603
|
+
const sql = `
|
|
604
|
+
WITH activity_update AS (
|
|
605
|
+
INSERT INTO ${attrsTable} (job_id, field, value, type)
|
|
606
|
+
SELECT id, $2, ($3::double precision)::text, $4
|
|
607
|
+
FROM ${jobsTableName}
|
|
608
|
+
WHERE key = $1 AND is_live
|
|
609
|
+
ON CONFLICT (job_id, field) DO UPDATE
|
|
610
|
+
SET value = ((COALESCE(${attrsTable}.value, '0')::double precision) + $3::double precision)::text,
|
|
611
|
+
type = EXCLUDED.type
|
|
612
|
+
RETURNING job_id, value::double precision AS activity_value
|
|
613
|
+
),
|
|
614
|
+
guid_upsert AS (
|
|
615
|
+
INSERT INTO ${attrsTable} (job_id, field, value, type)
|
|
616
|
+
SELECT
|
|
617
|
+
job_id,
|
|
618
|
+
$5,
|
|
619
|
+
((activity_value::bigint) % 100000000)::text,
|
|
620
|
+
$6
|
|
621
|
+
FROM activity_update
|
|
622
|
+
ON CONFLICT (job_id, field) DO UPDATE
|
|
623
|
+
SET value = ${attrsTable}.value
|
|
624
|
+
RETURNING value::double precision AS guid_value
|
|
625
|
+
)
|
|
626
|
+
SELECT
|
|
627
|
+
(SELECT activity_value FROM activity_update) AS activity_value,
|
|
628
|
+
(SELECT guid_value FROM guid_upsert) AS guid_value
|
|
629
|
+
`;
|
|
630
|
+
return {
|
|
631
|
+
sql,
|
|
632
|
+
params: [
|
|
633
|
+
key,
|
|
634
|
+
activityField,
|
|
635
|
+
increment,
|
|
636
|
+
(0, utils_1.deriveType)(activityField),
|
|
637
|
+
guidField,
|
|
638
|
+
(0, utils_1.deriveType)(guidField), // $6
|
|
639
|
+
],
|
|
640
|
+
};
|
|
641
|
+
}
|
|
642
|
+
exports._collateLeg2Entry = _collateLeg2Entry;
|
|
643
|
+
/**
|
|
644
|
+
* 3) LOW-LEVEL SQL GENERATOR
|
|
645
|
+
* --------------------------
|
|
646
|
+
* This is the core compound statement. It must:
|
|
647
|
+
* - update jobs.status by statusDelta
|
|
648
|
+
* - compute thresholdHit (0/1) when status_after == threshold
|
|
649
|
+
* - increment the guidField by thresholdHit * guidWeight (typically 100B digit)
|
|
650
|
+
* - return thresholdHit as "value" so it fits the existing return parsing
|
|
651
|
+
*
|
|
652
|
+
* Notes:
|
|
653
|
+
* - Uses tableForKey(key, 'hash') which will resolve to the jobs table for job keys.
|
|
654
|
+
* - Assumes jobs_attributes table is `${jobsTableName}_attributes` (same as _hincrbyfloat)
|
|
655
|
+
* - Uses deriveType(guidField) to be consistent with your attribute typing system.
|
|
656
|
+
*/
|
|
657
|
+
function _setStatusAndCollateGuid(context, key, // jobKey
|
|
658
|
+
statusDelta, threshold, guidField, guidWeight) {
|
|
659
|
+
const jobsTableName = context.tableForKey(key, 'hash');
|
|
660
|
+
if (!(0, utils_1.isJobsTable)(jobsTableName)) {
|
|
661
|
+
throw new Error(`_setStatusAndCollateGuid requires a jobs table key; got table ${jobsTableName}`);
|
|
662
|
+
}
|
|
663
|
+
const sql = `
|
|
664
|
+
WITH status_update AS (
|
|
665
|
+
UPDATE ${jobsTableName}
|
|
666
|
+
SET status = status + $2
|
|
667
|
+
WHERE key = $1 AND is_live
|
|
668
|
+
RETURNING id AS job_id, status AS status_after
|
|
669
|
+
),
|
|
670
|
+
hit AS (
|
|
671
|
+
SELECT
|
|
672
|
+
job_id,
|
|
673
|
+
CASE WHEN status_after = $3 THEN 1 ELSE 0 END AS threshold_hit,
|
|
674
|
+
CASE WHEN status_after = $3 THEN ($4::double precision) ELSE 0::double precision END AS guid_increment
|
|
675
|
+
FROM status_update
|
|
676
|
+
)
|
|
677
|
+
INSERT INTO ${jobsTableName}_attributes (job_id, field, value, type)
|
|
678
|
+
SELECT
|
|
679
|
+
job_id,
|
|
680
|
+
$5 AS field,
|
|
681
|
+
(guid_increment)::text AS value,
|
|
682
|
+
$6
|
|
683
|
+
FROM hit
|
|
684
|
+
ON CONFLICT (job_id, field) DO UPDATE
|
|
685
|
+
SET
|
|
686
|
+
value = ((COALESCE(${jobsTableName}_attributes.value, '0')::double precision) + EXCLUDED.value::double precision)::text,
|
|
687
|
+
type = EXCLUDED.type
|
|
688
|
+
RETURNING (SELECT threshold_hit::text FROM hit) AS value
|
|
689
|
+
`;
|
|
690
|
+
return {
|
|
691
|
+
sql,
|
|
692
|
+
params: [
|
|
693
|
+
key,
|
|
694
|
+
statusDelta,
|
|
695
|
+
threshold,
|
|
696
|
+
guidWeight,
|
|
697
|
+
guidField,
|
|
698
|
+
(0, utils_1.deriveType)(guidField), // $6
|
|
699
|
+
],
|
|
700
|
+
};
|
|
701
|
+
}
|
|
702
|
+
exports._setStatusAndCollateGuid = _setStatusAndCollateGuid;
|
|
@@ -8,6 +8,8 @@ export declare const hashModule: (context: KVSQL) => {
|
|
|
8
8
|
_hdel: (key: string, fields: string[]) => import("./types").SqlResult;
|
|
9
9
|
_hmget: (key: string, fields: string[]) => import("./types").SqlResult;
|
|
10
10
|
_hincrbyfloat: (key: string, field: string, increment: number) => import("./types").SqlResult;
|
|
11
|
+
_collateLeg2Entry: (key: string, activityField: string, increment: number, guidField: string) => import("./types").SqlResult;
|
|
12
|
+
_setStatusAndCollateGuid: (key: string, statusDelta: number, threshold: number, guidField: string, guidWeight: number) => import("./types").SqlResult;
|
|
11
13
|
_hscan: (key: string, cursor: string, count: number, pattern?: string) => import("./types").SqlResult;
|
|
12
14
|
_expire: (key: string, seconds: number) => import("./types").SqlResult;
|
|
13
15
|
_scan: (cursor: number, count: number, pattern?: string) => import("./types").SqlResult;
|
|
@@ -24,6 +26,8 @@ export declare const hashModule: (context: KVSQL) => {
|
|
|
24
26
|
hmget(key: string, fields: string[], multi?: import("./types").ProviderTransaction): Promise<string[]>;
|
|
25
27
|
hgetall(key: string, multi?: import("./types").ProviderTransaction): Promise<Record<string, string>>;
|
|
26
28
|
hincrbyfloat(key: string, field: string, increment: number, multi?: import("./types").ProviderTransaction): Promise<number>;
|
|
29
|
+
collateLeg2Entry(key: string, activityField: string, increment: number, guidField: string, multi?: import("./types").ProviderTransaction): Promise<[number, number]>;
|
|
30
|
+
setStatusAndCollateGuid(key: string, statusDelta: number, threshold: number, guidField: string, guidWeight: number, multi?: import("./types").ProviderTransaction): Promise<number>;
|
|
27
31
|
};
|
|
28
32
|
export { isJobsTable, deriveType } from './utils';
|
|
29
33
|
export * from './types';
|
|
@@ -199,6 +199,12 @@ const hashModule = (context) => {
|
|
|
199
199
|
_hincrbyfloat: (key, field, increment) => {
|
|
200
200
|
return (0, basic_1._hincrbyfloat)(context, key, field, increment);
|
|
201
201
|
},
|
|
202
|
+
_collateLeg2Entry: (key, activityField, increment, guidField) => {
|
|
203
|
+
return (0, basic_1._collateLeg2Entry)(context, key, activityField, increment, guidField);
|
|
204
|
+
},
|
|
205
|
+
_setStatusAndCollateGuid: (key, statusDelta, threshold, guidField, guidWeight) => {
|
|
206
|
+
return (0, basic_1._setStatusAndCollateGuid)(context, key, statusDelta, threshold, guidField, guidWeight);
|
|
207
|
+
},
|
|
202
208
|
_hscan: (key, cursor, count, pattern) => {
|
|
203
209
|
return (0, scan_1._hscan)(context, key, cursor, count, pattern);
|
|
204
210
|
},
|
|
@@ -61,6 +61,20 @@ declare class PostgresStoreService extends StoreService<ProviderClient, Provider
|
|
|
61
61
|
getJobStats(jobKeys: string[]): Promise<JobStatsRange>;
|
|
62
62
|
getJobIds(indexKeys: string[], idRange: [number, number]): Promise<IdsData>;
|
|
63
63
|
setStatus(collationKeyStatus: number, jobId: string, appId: string, transaction?: ProviderTransaction): Promise<any>;
|
|
64
|
+
/**
|
|
65
|
+
* 1) HIGH-LEVEL STORE METHOD (engine/activity-facing)
|
|
66
|
+
* ---------------------------------------------------
|
|
67
|
+
* Mirrors setStatus(), but performs the compound Step-2 requirement:
|
|
68
|
+
* - apply delta to job semaphore (jobs.status)
|
|
69
|
+
* - compute thresholdHit (0/1) for desired threshold
|
|
70
|
+
* - persist thresholdHit onto the Leg2 GUID ledger by incrementing the 100B digit (or other weight)
|
|
71
|
+
* - return thresholdHit (0/1)
|
|
72
|
+
*/
|
|
73
|
+
setStatusAndCollateGuid(statusDelta: number, // typically (N - 1)
|
|
74
|
+
threshold: number, // typically 0 (but supports 0,1,12,...)
|
|
75
|
+
jobId: string, appId: string, guidField: string, // the jobs_attributes.field for the Leg2 GUID ledger row
|
|
76
|
+
guidWeight: number, // e.g. 100_000_000_000 for GUID 100B digit
|
|
77
|
+
transaction?: ProviderTransaction): Promise<number>;
|
|
64
78
|
getStatus(jobId: string, appId: string): Promise<number>;
|
|
65
79
|
setState({ ...state }: StringAnyType, status: number | null, jobId: string, symbolNames: string[], dIds: StringStringType, transaction?: ProviderTransaction): Promise<string>;
|
|
66
80
|
/**
|
|
@@ -76,6 +90,12 @@ declare class PostgresStoreService extends StoreService<ProviderClient, Provider
|
|
|
76
90
|
* in order to track their progress during processing.
|
|
77
91
|
*/
|
|
78
92
|
collate(jobId: string, activityId: string, amount: number, dIds: StringStringType, transaction?: ProviderTransaction): Promise<number>;
|
|
93
|
+
/**
|
|
94
|
+
* Compound Leg2 entry: atomically increments the activity Leg2 entry
|
|
95
|
+
* counter and seeds the GUID ledger with the ordinal IF NOT EXISTS.
|
|
96
|
+
* Returns [activityValue, guidValue].
|
|
97
|
+
*/
|
|
98
|
+
collateLeg2Entry(jobId: string, activityId: string, guid: string, dIds: StringStringType, transaction?: ProviderTransaction): Promise<[number, number]>;
|
|
79
99
|
/**
|
|
80
100
|
* Synthentic collation affects those activities in the graph
|
|
81
101
|
* that represent the synthetic DAG that was materialized during compilation;
|
|
@@ -439,6 +439,23 @@ class PostgresStoreService extends __1.StoreService {
|
|
|
439
439
|
const jobKey = this.mintKey(key_1.KeyType.JOB_STATE, { appId, jobId });
|
|
440
440
|
return await this.kvsql(transaction).hincrbyfloat(jobKey, ':', collationKeyStatus);
|
|
441
441
|
}
|
|
442
|
+
/**
|
|
443
|
+
* 1) HIGH-LEVEL STORE METHOD (engine/activity-facing)
|
|
444
|
+
* ---------------------------------------------------
|
|
445
|
+
* Mirrors setStatus(), but performs the compound Step-2 requirement:
|
|
446
|
+
* - apply delta to job semaphore (jobs.status)
|
|
447
|
+
* - compute thresholdHit (0/1) for desired threshold
|
|
448
|
+
* - persist thresholdHit onto the Leg2 GUID ledger by incrementing the 100B digit (or other weight)
|
|
449
|
+
* - return thresholdHit (0/1)
|
|
450
|
+
*/
|
|
451
|
+
async setStatusAndCollateGuid(statusDelta, // typically (N - 1)
|
|
452
|
+
threshold, // typically 0 (but supports 0,1,12,...)
|
|
453
|
+
jobId, appId, guidField, // the jobs_attributes.field for the Leg2 GUID ledger row
|
|
454
|
+
guidWeight, // e.g. 100_000_000_000 for GUID 100B digit
|
|
455
|
+
transaction) {
|
|
456
|
+
const jobKey = this.mintKey(key_1.KeyType.JOB_STATE, { appId, jobId });
|
|
457
|
+
return await this.kvsql(transaction).setStatusAndCollateGuid(jobKey, statusDelta, threshold, guidField, guidWeight);
|
|
458
|
+
}
|
|
442
459
|
async getStatus(jobId, appId) {
|
|
443
460
|
const jobKey = this.mintKey(key_1.KeyType.JOB_STATE, { appId, jobId });
|
|
444
461
|
const status = await this.kvsql().hget(jobKey, ':');
|
|
@@ -551,6 +568,26 @@ class PostgresStoreService extends __1.StoreService {
|
|
|
551
568
|
const targetId = Object.keys(hashData)[0];
|
|
552
569
|
return await this.kvsql(transaction).hincrbyfloat(jobKey, targetId, amount);
|
|
553
570
|
}
|
|
571
|
+
/**
|
|
572
|
+
* Compound Leg2 entry: atomically increments the activity Leg2 entry
|
|
573
|
+
* counter and seeds the GUID ledger with the ordinal IF NOT EXISTS.
|
|
574
|
+
* Returns [activityValue, guidValue].
|
|
575
|
+
*/
|
|
576
|
+
async collateLeg2Entry(jobId, activityId, guid, dIds, transaction) {
|
|
577
|
+
const jobKey = this.mintKey(key_1.KeyType.JOB_STATE, {
|
|
578
|
+
appId: this.appId,
|
|
579
|
+
jobId,
|
|
580
|
+
});
|
|
581
|
+
const collationKey = `${activityId}/output/metadata/as`;
|
|
582
|
+
const symbolNames = [activityId];
|
|
583
|
+
const symKeys = await this.getSymbolKeys(symbolNames);
|
|
584
|
+
const symVals = await this.getSymbolValues();
|
|
585
|
+
this.serializer.resetSymbols(symKeys, symVals, dIds);
|
|
586
|
+
const payload = { [collationKey]: '1' };
|
|
587
|
+
const hashData = this.serializer.package(payload, symbolNames);
|
|
588
|
+
const targetId = Object.keys(hashData)[0];
|
|
589
|
+
return await this.kvsql(transaction).collateLeg2Entry(jobKey, targetId, 1, guid);
|
|
590
|
+
}
|
|
554
591
|
/**
|
|
555
592
|
* Synthentic collation affects those activities in the graph
|
|
556
593
|
* that represent the synthetic DAG that was materialized during compilation;
|
|
@@ -1044,7 +1081,7 @@ class PostgresStoreService extends __1.StoreService {
|
|
|
1044
1081
|
const sql = (0, time_notify_1.getTimeNotifySql)(schemaName);
|
|
1045
1082
|
// Execute the entire SQL as one statement (functions contain $$ blocks with semicolons)
|
|
1046
1083
|
await client.query(sql);
|
|
1047
|
-
this.logger.
|
|
1084
|
+
this.logger.debug('postgres-time-notifications-deployed', {
|
|
1048
1085
|
appId,
|
|
1049
1086
|
schemaName,
|
|
1050
1087
|
message: 'Time-aware notifications ENABLED - using LISTEN/NOTIFY instead of polling',
|
|
@@ -2,8 +2,6 @@
|
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.StreamServiceFactory = void 0;
|
|
4
4
|
const utils_1 = require("../../modules/utils");
|
|
5
|
-
const ioredis_1 = require("./providers/redis/ioredis");
|
|
6
|
-
const redis_1 = require("./providers/redis/redis");
|
|
7
5
|
const nats_1 = require("./providers/nats/nats");
|
|
8
6
|
const postgres_1 = require("./providers/postgres/postgres");
|
|
9
7
|
class StreamServiceFactory {
|
|
@@ -11,24 +9,10 @@ class StreamServiceFactory {
|
|
|
11
9
|
let service;
|
|
12
10
|
const providerType = (0, utils_1.identifyProvider)(provider);
|
|
13
11
|
if (providerType === 'nats') {
|
|
14
|
-
|
|
15
|
-
if ((0, utils_1.identifyProvider)(storeProvider) === 'redis') {
|
|
16
|
-
redisStoreProvider = storeProvider;
|
|
17
|
-
}
|
|
18
|
-
else {
|
|
19
|
-
//ioredis
|
|
20
|
-
redisStoreProvider = storeProvider;
|
|
21
|
-
}
|
|
22
|
-
service = new nats_1.NatsStreamService(provider, redisStoreProvider);
|
|
12
|
+
service = new nats_1.NatsStreamService(provider, storeProvider);
|
|
23
13
|
}
|
|
24
14
|
else if (providerType === 'postgres') {
|
|
25
15
|
service = new postgres_1.PostgresStreamService(provider, storeProvider);
|
|
26
|
-
}
|
|
27
|
-
else if (providerType === 'redis') {
|
|
28
|
-
service = new redis_1.RedisStreamService(provider, storeProvider);
|
|
29
|
-
}
|
|
30
|
-
else if (providerType === 'ioredis') {
|
|
31
|
-
service = new ioredis_1.IORedisStreamService(provider, storeProvider);
|
|
32
16
|
} //etc register other providers here
|
|
33
17
|
await service.init(namespace, appId, logger);
|
|
34
18
|
return service;
|
|
@@ -31,7 +31,7 @@ class ScoutManager {
|
|
|
31
31
|
this.pollForVisibleMessagesLoop().catch((error) => {
|
|
32
32
|
this.logger.error('postgres-stream-router-scout-start-error', { error });
|
|
33
33
|
});
|
|
34
|
-
this.logger.
|
|
34
|
+
this.logger.debug('postgres-stream-router-scout-started', {
|
|
35
35
|
appId: this.appId,
|
|
36
36
|
pollInterval: this.getRouterScoutInterval(),
|
|
37
37
|
scoutInterval: enums_1.HMSH_ROUTER_SCOUT_INTERVAL_SECONDS,
|
|
@@ -204,7 +204,7 @@ class ScoutManager {
|
|
|
204
204
|
*/
|
|
205
205
|
logPollingMetrics() {
|
|
206
206
|
if (this.pollCount === 0) {
|
|
207
|
-
this.logger.
|
|
207
|
+
this.logger.debug('postgres-stream-router-scout-metrics', {
|
|
208
208
|
message: 'No polling occurred during this session',
|
|
209
209
|
appId: this.appId,
|
|
210
210
|
});
|
|
@@ -2,10 +2,8 @@
|
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.SubServiceFactory = void 0;
|
|
4
4
|
const utils_1 = require("../../modules/utils");
|
|
5
|
-
const redis_1 = require("./providers/redis/redis");
|
|
6
5
|
const postgres_1 = require("./providers/postgres/postgres");
|
|
7
6
|
const nats_1 = require("./providers/nats/nats");
|
|
8
|
-
const ioredis_1 = require("./providers/redis/ioredis");
|
|
9
7
|
class SubServiceFactory {
|
|
10
8
|
static async init(providerSubClient, providerPubClient, namespace, appId, engineId, logger) {
|
|
11
9
|
let service;
|
|
@@ -13,15 +11,9 @@ class SubServiceFactory {
|
|
|
13
11
|
if (providerType === 'nats') {
|
|
14
12
|
service = new nats_1.NatsSubService(providerSubClient, providerPubClient);
|
|
15
13
|
}
|
|
16
|
-
else if (providerType === 'redis') {
|
|
17
|
-
service = new redis_1.RedisSubService(providerSubClient, providerPubClient);
|
|
18
|
-
}
|
|
19
14
|
else if (providerType === 'postgres') {
|
|
20
15
|
service = new postgres_1.PostgresSubService(providerSubClient, providerPubClient);
|
|
21
|
-
}
|
|
22
|
-
else {
|
|
23
|
-
service = new ioredis_1.IORedisSubService(providerSubClient, providerPubClient);
|
|
24
|
-
}
|
|
16
|
+
} //etc
|
|
25
17
|
await service.init(namespace, appId, engineId, logger);
|
|
26
18
|
return service;
|
|
27
19
|
}
|
|
@@ -17,6 +17,6 @@ declare abstract class SubService<ClientProvider extends ProviderClient> {
|
|
|
17
17
|
abstract unsubscribe(keyType: KeyType.QUORUM, appId: string, topic?: string): Promise<void>;
|
|
18
18
|
abstract psubscribe(keyType: KeyType.QUORUM, callback: SubscriptionCallback, appId: string, topic?: string): Promise<void>;
|
|
19
19
|
abstract punsubscribe(keyType: KeyType.QUORUM, appId: string, topic?: string): Promise<void>;
|
|
20
|
-
abstract publish(keyType: KeyType, message: Record<string, any>, appId: string, topic?: string): Promise<boolean>;
|
|
20
|
+
abstract publish(keyType: KeyType, message: Record<string, any>, appId: string, topic?: string, transaction?: ProviderTransaction): Promise<boolean>;
|
|
21
21
|
}
|
|
22
22
|
export { SubService };
|
|
@@ -22,7 +22,7 @@ declare class PostgresSubService extends SubService<PostgresClientType & Provide
|
|
|
22
22
|
* Should be called when the SubService instance is being destroyed.
|
|
23
23
|
*/
|
|
24
24
|
cleanup(): Promise<void>;
|
|
25
|
-
publish(keyType: KeyType.QUORUM, message: Record<string, any>, appId: string, topic?: string): Promise<boolean>;
|
|
25
|
+
publish(keyType: KeyType.QUORUM, message: Record<string, any>, appId: string, topic?: string, transaction?: ProviderTransaction): Promise<boolean>;
|
|
26
26
|
psubscribe(): Promise<void>;
|
|
27
27
|
punsubscribe(): Promise<void>;
|
|
28
28
|
}
|