@cap-js-community/event-queue 1.9.2 → 1.9.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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@cap-js-community/event-queue",
3
- "version": "1.9.2",
3
+ "version": "1.9.4",
4
4
  "description": "An event queue that enables secure transactional processing of asynchronous and periodic events, featuring instant event processing with Redis Pub/Sub and load distribution across all application instances.",
5
5
  "main": "src/index.js",
6
6
  "types": "src/index.d.ts",
package/src/config.js CHANGED
@@ -10,9 +10,12 @@ const { Priorities } = require("./constants");
10
10
 
11
11
  const FOR_UPDATE_TIMEOUT = 10;
12
12
  const GLOBAL_TX_TIMEOUT = 30 * 60 * 1000;
13
- const REDIS_CONFIG_CHANNEL = "EVENT_QUEUE_CONFIG_CHANNEL";
13
+ const REDIS_PREFIX = "EVENT_QUEUE";
14
+ const REDIS_CONFIG_CHANNEL = "CONFIG_CHANNEL";
14
15
  const REDIS_OFFBOARD_TENANT_CHANNEL = "REDIS_OFFBOARD_TENANT_CHANNEL";
15
- const REDIS_CONFIG_BLOCKLIST_CHANNEL = "EVENT_QUEUE_REDIS_CONFIG_BLOCKLIST_CHANNEL";
16
+ const REDIS_CONFIG_BLOCKLIST_CHANNEL = "REDIS_CONFIG_BLOCKLIST_CHANNEL";
17
+ const COMMAND_BLOCK = "EVENT_BLOCK";
18
+ const COMMAND_UNBLOCK = "EVENT_UNBLOCK";
16
19
  const COMPONENT_NAME = "/eventQueue/config";
17
20
  const MIN_INTERVAL_SEC = 10;
18
21
  const DEFAULT_LOAD = 1;
@@ -22,8 +25,6 @@ const DEFAULT_KEEP_ALIVE_INTERVAL = 60;
22
25
  const DEFAULT_MAX_FACTOR_STUCK_2_KEEP_ALIVE_INTERVAL = 3.5;
23
26
  const DEFAULT_INHERIT_TRACE_CONTEXT = true;
24
27
  const SUFFIX_PERIODIC = "_PERIODIC";
25
- const COMMAND_BLOCK = "EVENT_QUEUE_EVENT_BLOCK";
26
- const COMMAND_UNBLOCK = "EVENT_QUEUE_EVENT_UNBLOCK";
27
28
  const CAP_EVENT_TYPE = "CAP_OUTBOX";
28
29
  const CAP_PARALLEL_DEFAULT = 5;
29
30
  const DELETE_TENANT_BLOCK_AFTER_MS = 5 * 60 * 1000;
@@ -67,6 +68,7 @@ class Config {
67
68
  #unsubscribeHandlers = [];
68
69
  #unsubscribedTenants = {};
69
70
  #cronTimezone;
71
+ #redisNamespace;
70
72
  #publishEventBlockList;
71
73
  #crashOnRedisUnavailable;
72
74
  #tenantIdFilterTokenInfoCb;
@@ -143,7 +145,7 @@ class Config {
143
145
 
144
146
  attachConfigChangeHandler() {
145
147
  this.#attachBlockListChangeHandler();
146
- redis.subscribeRedisChannel(this.#redisOptions, REDIS_CONFIG_CHANNEL, (messageData) => {
148
+ redis.subscribeRedisChannel(this.redisOptions, REDIS_CONFIG_CHANNEL, (messageData) => {
147
149
  try {
148
150
  const { key, value } = JSON.parse(messageData);
149
151
  if (this[key] !== value) {
@@ -160,7 +162,7 @@ class Config {
160
162
 
161
163
  attachRedisUnsubscribeHandler() {
162
164
  this.#logger.info("attached redis handle for unsubscribe events");
163
- redis.subscribeRedisChannel(this.#redisOptions, REDIS_OFFBOARD_TENANT_CHANNEL, (messageData) => {
165
+ redis.subscribeRedisChannel(this.redisOptions, REDIS_OFFBOARD_TENANT_CHANNEL, (messageData) => {
164
166
  try {
165
167
  const { tenantId } = JSON.parse(messageData);
166
168
  this.#logger.info("received unsubscribe broadcast event", { tenantId });
@@ -190,7 +192,7 @@ class Config {
190
192
  handleUnsubscribe(tenantId) {
191
193
  if (this.redisEnabled) {
192
194
  redis
193
- .publishMessage(this.#redisOptions, REDIS_OFFBOARD_TENANT_CHANNEL, JSON.stringify({ tenantId }))
195
+ .publishMessage(this.redisOptions, REDIS_OFFBOARD_TENANT_CHANNEL, JSON.stringify({ tenantId }))
194
196
  .catch((error) => {
195
197
  this.#logger.error(`publishing tenant unsubscribe failed. tenantId: ${tenantId}`, error);
196
198
  });
@@ -208,13 +210,13 @@ class Config {
208
210
  this.#logger.info("redis not connected, config change won't be published", { key, value });
209
211
  return;
210
212
  }
211
- redis.publishMessage(this.#redisOptions, REDIS_CONFIG_CHANNEL, JSON.stringify({ key, value })).catch((error) => {
213
+ redis.publishMessage(this.redisOptions, REDIS_CONFIG_CHANNEL, JSON.stringify({ key, value })).catch((error) => {
212
214
  this.#logger.error(`publishing config change failed key: ${key}, value: ${value}`, error);
213
215
  });
214
216
  }
215
217
 
216
218
  #attachBlockListChangeHandler() {
217
- redis.subscribeRedisChannel(this.#redisOptions, REDIS_CONFIG_BLOCKLIST_CHANNEL, (messageData) => {
219
+ redis.subscribeRedisChannel(this.redisOptions, REDIS_CONFIG_BLOCKLIST_CHANNEL, (messageData) => {
218
220
  try {
219
221
  const { command, key, tenant } = JSON.parse(messageData);
220
222
  if (command === COMMAND_BLOCK) {
@@ -244,7 +246,7 @@ class Config {
244
246
 
245
247
  redis
246
248
  .publishMessage(
247
- this.#redisOptions,
249
+ this.redisOptions,
248
250
  REDIS_CONFIG_BLOCKLIST_CHANNEL,
249
251
  JSON.stringify({ command: COMMAND_BLOCK, key, tenant })
250
252
  )
@@ -277,7 +279,7 @@ class Config {
277
279
 
278
280
  redis
279
281
  .publishMessage(
280
- this.#redisOptions,
282
+ this.redisOptions,
281
283
  REDIS_CONFIG_BLOCKLIST_CHANNEL,
282
284
  JSON.stringify({ command: COMMAND_UNBLOCK, key, tenant })
283
285
  )
@@ -751,7 +753,18 @@ class Config {
751
753
  }
752
754
 
753
755
  get redisOptions() {
754
- return this.#redisOptions;
756
+ return {
757
+ ...this.#redisOptions,
758
+ redisNamespace: `${[REDIS_PREFIX, this.redisNamespace].filter((a) => a).join("_")}`,
759
+ };
760
+ }
761
+
762
+ set redisNamespace(value) {
763
+ this.#redisNamespace = value;
764
+ }
765
+
766
+ get redisNamespace() {
767
+ return this.#redisNamespace;
755
768
  }
756
769
 
757
770
  set insertEventsBeforeCommit(value) {
package/src/initialize.js CHANGED
@@ -42,6 +42,7 @@ const CONFIG_VARS = [
42
42
  ["insertEventsBeforeCommit", true],
43
43
  ["enableTelemetry", true],
44
44
  ["cronTimezone", null],
45
+ ["redisNamespace", null],
45
46
  ["publishEventBlockList", true],
46
47
  ["crashOnRedisUnavailable", false],
47
48
  ];
@@ -18,10 +18,10 @@ const { runEventCombinationForTenant } = require("./runnerHelper");
18
18
  const { trace } = require("../shared/openTelemetry");
19
19
 
20
20
  const COMPONENT_NAME = "/eventQueue/runner";
21
- const EVENT_QUEUE_RUN_ID = "EVENT_QUEUE_RUN_ID";
22
- const EVENT_QUEUE_RUN_TS = "EVENT_QUEUE_RUN_TS";
23
- const EVENT_QUEUE_RUN_REDIS_CHECK = "EVENT_QUEUE_RUN_REDIS_CHECK";
24
- const EVENT_QUEUE_UPDATE_PERIODIC_EVENTS = "EVENT_QUEUE_UPDATE_PERIODIC_EVENTS";
21
+ const EVENT_QUEUE_RUN_ID = "RUN_ID";
22
+ const EVENT_QUEUE_RUN_TS = "RUN_TS";
23
+ const EVENT_QUEUE_RUN_REDIS_CHECK = "RUN_REDIS_CHECK";
24
+ const EVENT_QUEUE_UPDATE_PERIODIC_EVENTS = "UPDATE_PERIODIC_EVENTS";
25
25
  let OFFSET_FIRST_RUN = 10 * 1000;
26
26
 
27
27
  let tenantIdHash;
@@ -4,7 +4,6 @@ const redis = require("./redis");
4
4
  const config = require("../config");
5
5
  const cdsHelper = require("./cdsHelper");
6
6
 
7
- const KEY_PREFIX = "EVENT_QUEUE";
8
7
  const existingLocks = {};
9
8
  const REDIS_COMMAND_OK = "OK";
10
9
  const COMPONENT_NAME = "/eventQueue/distributedLock";
@@ -176,10 +175,10 @@ const _acquireLockDB = async (context, fullKey, expiryTime, { value = "true", ov
176
175
  };
177
176
 
178
177
  const _generateKey = (context, tenantScoped, key) => {
179
- const keyParts = [];
178
+ const keyParts = [config.redisOptions.redisNamespace];
180
179
  tenantScoped && keyParts.push(context.tenant);
181
180
  keyParts.push(key);
182
- return `${KEY_PREFIX}_${keyParts.join("##")}`;
181
+ return `${keyParts.join("##")}`;
183
182
  };
184
183
 
185
184
  const shutdownHandler = async () => {
@@ -45,12 +45,6 @@ const trace = async (context, label, fn, { attributes = {}, newRootSpan = false,
45
45
 
46
46
  const _startOtelTrace = async (ctxWithSpan, traceContext, span, fn) => {
47
47
  return otel.context.with(ctxWithSpan, async () => {
48
- if (traceContext) {
49
- cds.log("/eventQueue/telemetry").info("Linked span:", span.spanContext());
50
- const carrier = {};
51
- otel.propagation.inject(ctxWithSpan, carrier);
52
- cds.log("/eventQueue/telemetry").info("Extracted trace context by inject", carrier);
53
- }
54
48
  const onSuccess = (res) => {
55
49
  span.setStatus({ code: otel.SpanStatusCode.OK });
56
50
  return res;
@@ -46,6 +46,7 @@ const _createClientBase = (redisOptions = {}) => {
46
46
  password: redisOptions.password ?? options.password ?? credentials.password,
47
47
  socket,
48
48
  });
49
+ delete socketOptions.redisNamespace;
49
50
  if (credentials.cluster_mode) {
50
51
  return redis.createCluster({
51
52
  rootNodes: [socketOptions],
@@ -106,9 +107,10 @@ const _subscribeChannels = (options, subscribedChannels, errorHandlerCreateClien
106
107
  if (client._subscribedChannels[channel]) {
107
108
  continue;
108
109
  }
109
- cds.log(COMPONENT_NAME).info("subscribe redis client connected channel", { channel });
110
+ const prefixedChannelName = [options.redisNamespace, channel].join("_");
111
+ cds.log(COMPONENT_NAME).info("subscribe redis client connected channel", { channel: prefixedChannelName });
110
112
  client
111
- .subscribe(channel, fn)
113
+ .subscribe(prefixedChannelName, fn)
112
114
  .then(() => {
113
115
  client._subscribedChannels ??= {};
114
116
  client._subscribedChannels[channel] = 1;
@@ -133,7 +135,7 @@ const _subscribeChannels = (options, subscribedChannels, errorHandlerCreateClien
133
135
 
134
136
  const publishMessage = async (options, channel, message) => {
135
137
  const client = await createMainClientAndConnect(options);
136
- return await client.publish(channel, message);
138
+ return await client.publish([options.redisNamespace, channel].join("_"), message);
137
139
  };
138
140
 
139
141
  const closeMainClient = async () => {