@hotmeshio/hotmesh 0.5.8 → 0.6.1

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 (49) hide show
  1. package/build/index.d.ts +3 -1
  2. package/build/index.js +5 -1
  3. package/build/modules/enums.d.ts +17 -0
  4. package/build/modules/enums.js +18 -1
  5. package/build/modules/utils.js +27 -0
  6. package/build/package.json +15 -3
  7. package/build/services/connector/factory.d.ts +1 -1
  8. package/build/services/connector/factory.js +15 -1
  9. package/build/services/connector/providers/ioredis.d.ts +9 -0
  10. package/build/services/connector/providers/ioredis.js +26 -0
  11. package/build/services/connector/providers/redis.d.ts +9 -0
  12. package/build/services/connector/providers/redis.js +38 -0
  13. package/build/services/engine/index.js +12 -2
  14. package/build/services/quorum/index.js +18 -1
  15. package/build/services/search/factory.js +8 -0
  16. package/build/services/search/providers/redis/ioredis.d.ts +23 -0
  17. package/build/services/search/providers/redis/ioredis.js +189 -0
  18. package/build/services/search/providers/redis/redis.d.ts +23 -0
  19. package/build/services/search/providers/redis/redis.js +202 -0
  20. package/build/services/store/factory.js +9 -1
  21. package/build/services/store/providers/postgres/postgres.js +3 -5
  22. package/build/services/store/providers/postgres/time-notify.d.ts +7 -0
  23. package/build/services/store/providers/postgres/time-notify.js +163 -0
  24. package/build/services/store/providers/redis/_base.d.ts +137 -0
  25. package/build/services/store/providers/redis/_base.js +980 -0
  26. package/build/services/store/providers/redis/ioredis.d.ts +20 -0
  27. package/build/services/store/providers/redis/ioredis.js +180 -0
  28. package/build/services/store/providers/redis/redis.d.ts +18 -0
  29. package/build/services/store/providers/redis/redis.js +199 -0
  30. package/build/services/stream/factory.js +17 -1
  31. package/build/services/stream/providers/postgres/kvtables.js +81 -14
  32. package/build/services/stream/providers/redis/ioredis.d.ts +61 -0
  33. package/build/services/stream/providers/redis/ioredis.js +272 -0
  34. package/build/services/stream/providers/redis/redis.d.ts +61 -0
  35. package/build/services/stream/providers/redis/redis.js +305 -0
  36. package/build/services/sub/factory.js +8 -0
  37. package/build/services/sub/providers/postgres/postgres.js +28 -1
  38. package/build/services/sub/providers/redis/ioredis.d.ts +20 -0
  39. package/build/services/sub/providers/redis/ioredis.js +150 -0
  40. package/build/services/sub/providers/redis/redis.d.ts +18 -0
  41. package/build/services/sub/providers/redis/redis.js +137 -0
  42. package/build/types/index.d.ts +1 -0
  43. package/build/types/index.js +4 -1
  44. package/build/types/provider.d.ts +1 -1
  45. package/build/types/quorum.d.ts +2 -0
  46. package/build/types/redis.d.ts +258 -0
  47. package/build/types/redis.js +11 -0
  48. package/index.ts +4 -0
  49. package/package.json +15 -3
@@ -5,6 +5,7 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
5
5
  Object.defineProperty(exports, "__esModule", { value: true });
6
6
  exports.PostgresSubService = void 0;
7
7
  const crypto_1 = __importDefault(require("crypto"));
8
+ const enums_1 = require("../../../../modules/enums");
8
9
  const key_1 = require("../../../../modules/key");
9
10
  const index_1 = require("../../index");
10
11
  class PostgresSubService extends index_1.SubService {
@@ -180,8 +181,34 @@ class PostgresSubService extends index_1.SubService {
180
181
  appId,
181
182
  engineId: topic,
182
183
  });
184
+ let messageToPublish = message;
185
+ let payload = JSON.stringify(message);
186
+ // PostgreSQL NOTIFY has a payload limit. If job message exceeds limit,
187
+ // send a reference message instead - subscriber will fetch via getState.
188
+ if (payload.length > enums_1.HMSH_NOTIFY_PAYLOAD_LIMIT &&
189
+ message.type === 'job' &&
190
+ message.job?.metadata) {
191
+ const { jid, tpc, app, js } = message.job.metadata;
192
+ messageToPublish = {
193
+ type: 'job',
194
+ topic: message.topic,
195
+ job: {
196
+ metadata: { jid, tpc, app, js },
197
+ data: null,
198
+ },
199
+ _ref: true,
200
+ };
201
+ payload = JSON.stringify(messageToPublish);
202
+ this.logger.debug('postgres-publish-ref', {
203
+ originalKey,
204
+ safeKey,
205
+ originalSize: JSON.stringify(message).length,
206
+ refSize: payload.length,
207
+ jid,
208
+ });
209
+ }
183
210
  // Publish the message using the safe topic
184
- const payload = JSON.stringify(message).replace(/'/g, "''");
211
+ payload = payload.replace(/'/g, "''");
185
212
  await this.storeClient.query(`NOTIFY "${safeKey}", '${payload}'`);
186
213
  this.logger.debug(`postgres-publish`, { originalKey, safeKey });
187
214
  return true;
@@ -0,0 +1,20 @@
1
+ import { KeyStoreParams, KeyType } from '../../../../modules/key';
2
+ import { ILogger } from '../../../logger';
3
+ import { SubService } from '../../index';
4
+ import { IORedisClientType as RedisClientType, IORedisMultiType as RedisMultiType } from '../../../../types/redis';
5
+ import { SubscriptionCallback } from '../../../../types/quorum';
6
+ declare class IORedisSubService extends SubService<RedisClientType> {
7
+ private subscriptions;
8
+ private messageHandlerSet;
9
+ private pmessageHandlerSet;
10
+ constructor(eventClient: RedisClientType, storeClient: RedisClientType);
11
+ init(namespace: string, appId: string, engineId: string, logger: ILogger): Promise<void>;
12
+ transact(): RedisMultiType;
13
+ mintKey(type: KeyType, params: KeyStoreParams): string;
14
+ subscribe(keyType: KeyType.QUORUM, callback: SubscriptionCallback, appId: string, engineId?: string): Promise<void>;
15
+ unsubscribe(keyType: KeyType.QUORUM, appId: string, engineId?: string): Promise<void>;
16
+ psubscribe(keyType: KeyType.QUORUM, callback: SubscriptionCallback, appId: string, engineId?: string): Promise<void>;
17
+ punsubscribe(keyType: KeyType.QUORUM, appId: string, engineId?: string): Promise<void>;
18
+ publish(keyType: KeyType.QUORUM, message: Record<string, any>, appId: string, engineId?: string): Promise<boolean>;
19
+ }
20
+ export { IORedisSubService };
@@ -0,0 +1,150 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.IORedisSubService = void 0;
4
+ const key_1 = require("../../../../modules/key");
5
+ const index_1 = require("../../index");
6
+ class IORedisSubService extends index_1.SubService {
7
+ constructor(eventClient, storeClient) {
8
+ super(eventClient, storeClient);
9
+ this.subscriptions = new Map();
10
+ this.messageHandlerSet = false;
11
+ this.pmessageHandlerSet = false;
12
+ }
13
+ async init(namespace = key_1.HMNS, appId, engineId, logger) {
14
+ this.namespace = namespace;
15
+ this.logger = logger;
16
+ this.appId = appId;
17
+ this.engineId = engineId;
18
+ }
19
+ transact() {
20
+ return this.eventClient.multi();
21
+ }
22
+ mintKey(type, params) {
23
+ if (!this.namespace)
24
+ throw new Error('namespace not set');
25
+ return key_1.KeyService.mintKey(this.namespace, type, params);
26
+ }
27
+ async subscribe(keyType, callback, appId, engineId) {
28
+ const topic = this.mintKey(keyType, { appId, engineId });
29
+ // Add callback to set (supports multiple subscribers per topic)
30
+ let callbacks = this.subscriptions.get(topic);
31
+ const isFirstSubscription = !callbacks;
32
+ if (!callbacks) {
33
+ callbacks = new Set();
34
+ this.subscriptions.set(topic, callbacks);
35
+ }
36
+ callbacks.add(callback);
37
+ this.logger.debug('ioredis-subscribe', {
38
+ topic,
39
+ isFirstSubscription,
40
+ totalCallbacks: callbacks.size,
41
+ messageHandlerSet: this.messageHandlerSet,
42
+ });
43
+ // Set up message handler only once
44
+ if (!this.messageHandlerSet) {
45
+ this.eventClient.on('message', (channel, message) => {
46
+ try {
47
+ const payload = JSON.parse(message);
48
+ const cbs = this.subscriptions.get(channel);
49
+ this.logger.debug('ioredis-message-received', {
50
+ channel,
51
+ callbackCount: cbs?.size || 0,
52
+ payload,
53
+ });
54
+ if (cbs) {
55
+ // Call all callbacks for this channel
56
+ cbs.forEach(cb => {
57
+ try {
58
+ cb(channel, payload);
59
+ }
60
+ catch (err) {
61
+ this.logger.error(`Error in callback for ${channel}`, err);
62
+ }
63
+ });
64
+ }
65
+ }
66
+ catch (e) {
67
+ this.logger.error(`Error parsing message: ${message}`, e);
68
+ }
69
+ });
70
+ this.messageHandlerSet = true;
71
+ }
72
+ await this.eventClient.subscribe(topic, (err) => {
73
+ if (err) {
74
+ this.logger.error(`Error subscribing to: ${topic}`, err);
75
+ }
76
+ });
77
+ }
78
+ async unsubscribe(keyType, appId, engineId) {
79
+ const topic = this.mintKey(keyType, { appId, engineId });
80
+ const callbacks = this.subscriptions.get(topic);
81
+ this.logger.debug('ioredis-unsubscribe', {
82
+ topic,
83
+ hadCallbacks: !!callbacks,
84
+ callbackCount: callbacks?.size || 0,
85
+ });
86
+ // Only unsubscribe from Redis if no more callbacks exist
87
+ if (callbacks && callbacks.size > 0) {
88
+ this.subscriptions.delete(topic);
89
+ await this.eventClient.unsubscribe(topic);
90
+ }
91
+ }
92
+ async psubscribe(keyType, callback, appId, engineId) {
93
+ const topic = this.mintKey(keyType, { appId, engineId });
94
+ // Add callback to set (supports multiple subscribers per topic)
95
+ let callbacks = this.subscriptions.get(topic);
96
+ if (!callbacks) {
97
+ callbacks = new Set();
98
+ this.subscriptions.set(topic, callbacks);
99
+ }
100
+ callbacks.add(callback);
101
+ // Set up pmessage handler only once
102
+ if (!this.pmessageHandlerSet) {
103
+ this.eventClient.on('pmessage', (pattern, channel, message) => {
104
+ try {
105
+ const payload = JSON.parse(message);
106
+ const cbs = this.subscriptions.get(pattern);
107
+ if (cbs) {
108
+ // Call all callbacks for this pattern
109
+ cbs.forEach(cb => {
110
+ try {
111
+ cb(channel, payload);
112
+ }
113
+ catch (err) {
114
+ this.logger.error(`Error in callback for ${pattern}`, err);
115
+ }
116
+ });
117
+ }
118
+ }
119
+ catch (e) {
120
+ this.logger.error(`Error parsing message: ${message}`, e);
121
+ }
122
+ });
123
+ this.pmessageHandlerSet = true;
124
+ }
125
+ await this.eventClient.psubscribe(topic, (err) => {
126
+ if (err) {
127
+ this.logger.error(`Error subscribing to: ${topic}`, err);
128
+ }
129
+ });
130
+ }
131
+ async punsubscribe(keyType, appId, engineId) {
132
+ const topic = this.mintKey(keyType, { appId, engineId });
133
+ const callbacks = this.subscriptions.get(topic);
134
+ // Only unsubscribe from Redis if no more callbacks exist
135
+ if (callbacks && callbacks.size > 0) {
136
+ this.subscriptions.delete(topic);
137
+ await this.eventClient.punsubscribe(topic);
138
+ }
139
+ }
140
+ async publish(keyType, message, appId, engineId) {
141
+ const topic = this.mintKey(keyType, { appId, engineId });
142
+ //NOTE: `storeClient.publish` is used,
143
+ // because a Redis connection with subscriptions
144
+ // may not publish (is read only).
145
+ this.logger.debug('ioredis-publish', { topic, message });
146
+ const status = await this.storeClient.publish(topic, JSON.stringify(message));
147
+ return status === 1;
148
+ }
149
+ }
150
+ exports.IORedisSubService = IORedisSubService;
@@ -0,0 +1,18 @@
1
+ import { KeyStoreParams, KeyType } from '../../../../modules/key';
2
+ import { ILogger } from '../../../logger';
3
+ import { SubService } from '../../index';
4
+ import { RedisRedisClientType as ClientProvider, RedisRedisMultiType as TransactionProvider } from '../../../../types/redis';
5
+ import { SubscriptionCallback } from '../../../../types/quorum';
6
+ declare class RedisSubService extends SubService<ClientProvider> {
7
+ private subscriptions;
8
+ constructor(eventClient: ClientProvider, storeClient: ClientProvider);
9
+ init(namespace: string, appId: string, engineId: string, logger: ILogger): Promise<void>;
10
+ transact(): TransactionProvider;
11
+ mintKey(type: KeyType, params: KeyStoreParams): string;
12
+ subscribe(keyType: KeyType.QUORUM, callback: SubscriptionCallback, appId: string, engineId?: string): Promise<void>;
13
+ unsubscribe(keyType: KeyType.QUORUM, appId: string, engineId?: string): Promise<void>;
14
+ psubscribe(keyType: KeyType.QUORUM, callback: SubscriptionCallback, appId: string, engineId?: string): Promise<void>;
15
+ punsubscribe(keyType: KeyType.QUORUM, appId: string, engineId?: string): Promise<void>;
16
+ publish(keyType: KeyType.QUORUM, message: Record<string, any>, appId: string, engineId?: string): Promise<boolean>;
17
+ }
18
+ export { RedisSubService };
@@ -0,0 +1,137 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.RedisSubService = void 0;
4
+ const key_1 = require("../../../../modules/key");
5
+ const index_1 = require("../../index");
6
+ class RedisSubService extends index_1.SubService {
7
+ constructor(eventClient, storeClient) {
8
+ super(eventClient, storeClient);
9
+ this.subscriptions = new Map();
10
+ }
11
+ async init(namespace = key_1.HMNS, appId, engineId, logger) {
12
+ this.namespace = namespace;
13
+ this.logger = logger;
14
+ this.appId = appId;
15
+ this.engineId = engineId;
16
+ }
17
+ transact() {
18
+ const multi = this.eventClient.multi();
19
+ return multi;
20
+ }
21
+ mintKey(type, params) {
22
+ if (!this.namespace)
23
+ throw new Error('namespace not set');
24
+ return key_1.KeyService.mintKey(this.namespace, type, params);
25
+ }
26
+ async subscribe(keyType, callback, appId, engineId) {
27
+ if (this.eventClient) {
28
+ const topic = this.mintKey(keyType, { appId, engineId });
29
+ // Add callback to set (supports multiple subscribers per topic)
30
+ let callbacks = this.subscriptions.get(topic);
31
+ const isFirstSubscription = !callbacks;
32
+ if (!callbacks) {
33
+ callbacks = new Set();
34
+ this.subscriptions.set(topic, callbacks);
35
+ }
36
+ callbacks.add(callback);
37
+ this.logger.debug('redis-subscribe', {
38
+ topic,
39
+ isFirstSubscription,
40
+ totalCallbacks: callbacks.size,
41
+ });
42
+ // Only subscribe to Redis once per topic
43
+ if (isFirstSubscription) {
44
+ await this.eventClient.subscribe(topic, (message) => {
45
+ try {
46
+ const payload = JSON.parse(message);
47
+ const cbs = this.subscriptions.get(topic);
48
+ this.logger.debug('redis-message-received', {
49
+ topic,
50
+ callbackCount: cbs?.size || 0,
51
+ payload,
52
+ });
53
+ if (cbs) {
54
+ // Call all callbacks for this topic
55
+ cbs.forEach(cb => {
56
+ try {
57
+ cb(topic, payload);
58
+ }
59
+ catch (err) {
60
+ this.logger.error(`Error in callback for ${topic}`, err);
61
+ }
62
+ });
63
+ }
64
+ }
65
+ catch (e) {
66
+ this.logger.error(`Error parsing message: ${message}`, e);
67
+ }
68
+ });
69
+ }
70
+ }
71
+ }
72
+ async unsubscribe(keyType, appId, engineId) {
73
+ const topic = this.mintKey(keyType, { appId, engineId });
74
+ const callbacks = this.subscriptions.get(topic);
75
+ this.logger.debug('redis-unsubscribe', {
76
+ topic,
77
+ hadCallbacks: !!callbacks,
78
+ callbackCount: callbacks?.size || 0,
79
+ });
80
+ // Only unsubscribe from Redis if no more callbacks exist
81
+ if (callbacks && callbacks.size > 0) {
82
+ this.subscriptions.delete(topic);
83
+ await this.eventClient.unsubscribe(topic);
84
+ }
85
+ }
86
+ async psubscribe(keyType, callback, appId, engineId) {
87
+ if (this.eventClient) {
88
+ const topic = this.mintKey(keyType, { appId, engineId });
89
+ // Add callback to set (supports multiple subscribers per topic)
90
+ let callbacks = this.subscriptions.get(topic);
91
+ if (!callbacks) {
92
+ callbacks = new Set();
93
+ this.subscriptions.set(topic, callbacks);
94
+ }
95
+ callbacks.add(callback);
96
+ await this.eventClient.pSubscribe(topic, (message, channel) => {
97
+ try {
98
+ const payload = JSON.parse(message);
99
+ const cbs = this.subscriptions.get(topic);
100
+ if (cbs) {
101
+ // Call all callbacks for this topic
102
+ cbs.forEach(cb => {
103
+ try {
104
+ cb(channel, payload);
105
+ }
106
+ catch (err) {
107
+ this.logger.error(`Error in callback for ${topic}`, err);
108
+ }
109
+ });
110
+ }
111
+ }
112
+ catch (e) {
113
+ this.logger.error(`Error parsing message: ${message}`, e);
114
+ }
115
+ });
116
+ }
117
+ }
118
+ async punsubscribe(keyType, appId, engineId) {
119
+ const topic = this.mintKey(keyType, { appId, engineId });
120
+ const callbacks = this.subscriptions.get(topic);
121
+ // Only unsubscribe from Redis if no more callbacks exist
122
+ if (callbacks && callbacks.size > 0) {
123
+ this.subscriptions.delete(topic);
124
+ await this.eventClient.pUnsubscribe(topic);
125
+ }
126
+ }
127
+ async publish(keyType, message, appId, engineId) {
128
+ const topic = this.mintKey(keyType, { appId, engineId });
129
+ //NOTE: `storeClient.publish` is used,
130
+ // because a Redis connection with subscriptions
131
+ // may not publish (is read only).
132
+ this.logger.debug('redis-publish', { topic, message });
133
+ const status = await this.storeClient.publish(topic, JSON.stringify(message));
134
+ return status > 0;
135
+ }
136
+ }
137
+ exports.RedisSubService = RedisSubService;
@@ -17,6 +17,7 @@ export { MeshCallConnectParams, MeshCallExecParams, MeshCallCronParams, MeshCall
17
17
  export { PostgresClassType, PostgresClientOptions, PostgresClientType, PostgresConsumerGroup, PostgresPendingMessage, PostgresPoolClientType, PostgresQueryConfigType, PostgresQueryResultType, PostgresStreamMessage, PostgresStreamOptions, PostgresTransaction, } from './postgres';
18
18
  export { ActivateMessage, CronMessage, JobMessage, JobMessageCallback, PingMessage, PongMessage, QuorumMessage, QuorumMessageCallback, QuorumProfile, RollCallMessage, RollCallOptions, SubscriptionCallback, SubscriptionOptions, SystemHealth, ThrottleMessage, ThrottleOptions, WorkMessage, } from './quorum';
19
19
  export { NatsAckPolicy, NatsAckPolicyExplicitType, NatsClassType, NatsClientType, NatsClientOptions, NatsConsumerConfigType, NatsJetStreamManager, NatsConnection, NatsJetStreamType, NatsConnectionOptions, NatsConsumerConfig, NatsConsumerInfo, NatsConsumerManager, NatsDeliveryInfo, NatsJetStreamOptions, NatsError, NatsErrorType, NatsJetStreamClient, NatsJsMsg, NatsMessageType, NatsMsgExpect, NatsPubAck, NatsPubAckType, NatsPublishOptions, NatsRetentionPolicy, NatsRetentionPolicyWorkqueueType, NatsSequenceInfo, NatsStorageMemoryType, NatsStorageType, NatsStreamConfig, NatsStreamInfo, NatsStreamManager, NatsStreamConfigType, NatsStreamInfoType, NatsStreamOptions, NatsStreamState, NatsTransaction, } from './nats';
20
+ export { RedisClass, RedisRedisClientType, RedisRedisClientOptions, RedisRedisClassType, IORedisClientType, RedisClient, RedisMulti, RedisRedisMultiType, IORedisClientOptions, IORedisClassType, IORedisMultiType, RedisOptions, isRedisClient, isIORedisClient, } from './redis';
20
21
  export { JSONSchema, StringAnyType, StringScalarType, StringStringType, SymbolMap, SymbolMaps, SymbolRanges, Symbols, SymbolSets, } from './serializer';
21
22
  export { AggregatedData, CountByFacet, GetStatsOptions, IdsData, Measure, MeasureIds, MetricTypes, StatType, StatsType, IdsResponse, JobStats, JobStatsInput, JobStatsRange, StatsResponse, Segment, TimeSegment, } from './stats';
22
23
  export { ReclaimedMessageType, RouterConfig, StreamCode, StreamConfig, StreamData, StreamDataType, StreamError, StreamDataResponse, StreamMessage, StreamMessageMetadata, StreamProviderType, StreamRetryPolicy, StreamRole, StreamStats, StreamStatus, } from './stream';
@@ -1,12 +1,15 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.ValueType = exports.trace = exports.SpanKind = exports.SpanStatusCode = exports.propagation = exports.metrics = exports.context = exports.StreamStatus = exports.StreamRole = exports.StreamDataType = exports.KeyType = exports.HookGate = exports.CollationFaultType = void 0;
3
+ exports.ValueType = exports.trace = exports.SpanKind = exports.SpanStatusCode = exports.propagation = exports.metrics = exports.context = exports.StreamStatus = exports.StreamRole = exports.StreamDataType = exports.isIORedisClient = exports.isRedisClient = exports.KeyType = exports.HookGate = exports.CollationFaultType = void 0;
4
4
  var collator_1 = require("./collator");
5
5
  Object.defineProperty(exports, "CollationFaultType", { enumerable: true, get: function () { return collator_1.CollationFaultType; } });
6
6
  var hook_1 = require("./hook");
7
7
  Object.defineProperty(exports, "HookGate", { enumerable: true, get: function () { return hook_1.HookGate; } });
8
8
  var hotmesh_1 = require("./hotmesh");
9
9
  Object.defineProperty(exports, "KeyType", { enumerable: true, get: function () { return hotmesh_1.KeyType; } });
10
+ var redis_1 = require("./redis");
11
+ Object.defineProperty(exports, "isRedisClient", { enumerable: true, get: function () { return redis_1.isRedisClient; } });
12
+ Object.defineProperty(exports, "isIORedisClient", { enumerable: true, get: function () { return redis_1.isIORedisClient; } });
10
13
  var stream_1 = require("./stream");
11
14
  Object.defineProperty(exports, "StreamDataType", { enumerable: true, get: function () { return stream_1.StreamDataType; } });
12
15
  Object.defineProperty(exports, "StreamRole", { enumerable: true, get: function () { return stream_1.StreamRole; } });
@@ -12,7 +12,7 @@ export interface ProviderClass {
12
12
  export interface ProviderOptions {
13
13
  [key: string]: any;
14
14
  }
15
- export type Providers = 'nats' | 'postgres';
15
+ export type Providers = 'nats' | 'postgres' | 'redis' | 'ioredis';
16
16
  /**
17
17
  * A provider transaction is a set of operations that are executed
18
18
  * atomically by the provider. The transaction is created by calling
@@ -94,6 +94,8 @@ export interface JobMessage extends QuorumMessageBase {
94
94
  entity?: string;
95
95
  topic: string;
96
96
  job: JobOutput;
97
+ /** if true, job.data is null due to payload size - subscriber should fetch via getState */
98
+ _ref?: boolean;
97
99
  }
98
100
  export interface ThrottleMessage extends QuorumMessageBase {
99
101
  type: 'throttle';