@cap-js-community/event-queue 1.9.0 → 1.9.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.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@cap-js-community/event-queue",
3
- "version": "1.9.0",
3
+ "version": "1.9.1",
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",
@@ -929,6 +929,7 @@ class EventQueueProcessorBase {
929
929
  }
930
930
  });
931
931
  }
932
+ this.logger.info("keep alive finished!", { numberOfEvents: ids.length });
932
933
  });
933
934
  }).catch((err) => {
934
935
  this.logger.error("keep alive handling failed!", err);
@@ -971,7 +972,7 @@ class EventQueueProcessorBase {
971
972
  { expiryTime: this.#eventConfig.keepAliveMaxInProgressTime }
972
973
  );
973
974
  if (!lockAcquired) {
974
- this.logger.error("renewing redis lock failed!", {
975
+ this.logger.error("renewing distributed lock failed!", {
975
976
  type: this.#eventType,
976
977
  subType: this.#eventSubType,
977
978
  });
package/src/config.js CHANGED
@@ -529,6 +529,10 @@ class Config {
529
529
  this.#configEvents = JSON.parse(JSON.stringify(value));
530
530
  }
531
531
 
532
+ get hasConfigEvents() {
533
+ return !!(Object.keys(this.#configEvents ?? {}).length || Object.keys(this.#configPeriodicEvents ?? {}).length);
534
+ }
535
+
532
536
  set configPeriodicEvents(value) {
533
537
  this.#configPeriodicEvents = JSON.parse(JSON.stringify(value));
534
538
  }
package/src/initialize.js CHANGED
@@ -134,7 +134,7 @@ const readConfigFromFile = async (configFilepath) => {
134
134
  "configFilepath with unsupported extension, allowed extensions are .yaml and .json"
135
135
  );
136
136
  } catch (err) {
137
- if (config.useAsCAPOutbox) {
137
+ if (!configFilepath && (config.useAsCAPOutbox || config.hasConfigEvents)) {
138
138
  return {};
139
139
  }
140
140
  throw err;
@@ -150,8 +150,14 @@ const _insertPeriodEvents = async (tx, events, now) => {
150
150
  processChunkedSync(eventsToBeInserted, CHUNK_SIZE_INSERT_PERIODIC_EVENTS, (chunk) => {
151
151
  logger.info(`${counter}/${chunks} | inserting chunk of changed or new periodic events`, {
152
152
  events: chunk.map(({ type, subType, startAfter }) => {
153
- const { interval } = eventConfig.getEventConfig(type, subType);
154
- return { type, subType, interval, ...(startAfter && { startAfter }) };
153
+ const { interval, cron } = eventConfig.getEventConfig(type, subType);
154
+ return {
155
+ type,
156
+ subType,
157
+ ...(startAfter && { startAfter }),
158
+ ...(interval && { interval }),
159
+ ...(cron && { cron }),
160
+ };
155
161
  }),
156
162
  });
157
163
  counter++;
@@ -20,7 +20,7 @@ const processEventQueue = async (context, eventType, eventSubType, startTime = n
20
20
  try {
21
21
  let eventTypeInstance;
22
22
  const eventConfig = config.getEventConfig(eventType, eventSubType);
23
- const [err, EventTypeClass] = resilientRequire(eventConfig);
23
+ const [err, EventTypeClass] = await resilientRequire(eventConfig);
24
24
  if (!eventConfig || err || !(typeof EventTypeClass.constructor === "function")) {
25
25
  cds.log(COMPONENT_NAME).error("No Implementation found in the provided configuration file.", {
26
26
  eventType,
@@ -331,12 +331,24 @@ const _processEvent = async (eventTypeInstance, processContext, key, queueEntrie
331
331
  }
332
332
  };
333
333
 
334
- const resilientRequire = (eventConfig) => {
334
+ const resilientRequire = async (eventConfig) => {
335
335
  try {
336
336
  const path = eventConfig?.impl;
337
337
  const internal = eventConfig?.internalEvent;
338
- const module = require(pathLib.join(internal ? __dirname : process.cwd(), path));
339
- return [null, module];
338
+ const filePath = pathLib.join(internal ? __dirname : process.cwd(), path);
339
+ const fileExtension = pathLib.extname(filePath);
340
+ switch (fileExtension) {
341
+ case ".js":
342
+ return [null, require(filePath)];
343
+ case ".mjs":
344
+ return [null, (await import(`file://${filePath}`)).default];
345
+ case "":
346
+ try {
347
+ return [null, require(filePath)];
348
+ } catch {
349
+ return [null, (await import(`file://${filePath}`)).default];
350
+ }
351
+ }
340
352
  } catch (err) {
341
353
  return [err, null];
342
354
  }
@@ -51,7 +51,10 @@ const _scheduleFunction = async (singleRunFn, periodicFn) => {
51
51
  }
52
52
  if (!singleRunDone) {
53
53
  singleRunDone = true;
54
- singleRunFn().catch(() => (singleRunDone = false));
54
+ singleRunFn()
55
+ .then(periodicFn)
56
+ .catch(() => (singleRunDone = false));
57
+ return;
55
58
  }
56
59
  return periodicFn();
57
60
  };
@@ -123,7 +123,6 @@ const getTokenInfo = async (tenantId) => {
123
123
  }
124
124
 
125
125
  if (!cds.requires?.auth.kind.match(/jwt|xsuaa/i)) {
126
- cds.log(COMPONENT_NAME).warn("Only 'jwt' or 'xsuaa' are supported as values for auth.kind.");
127
126
  return null;
128
127
  }
129
128
 
@@ -90,10 +90,20 @@ const _acquireLockRedis = async (
90
90
 
91
91
  const _renewLockRedis = async (context, fullKey, expiryTime, { value = "true" } = {}) => {
92
92
  const client = await redis.createMainClientAndConnect(config.redisOptions);
93
- const result = await client.set(fullKey, value, {
93
+ let result = await client.set(fullKey, value, {
94
94
  PX: Math.round(expiryTime),
95
95
  XX: true,
96
96
  });
97
+
98
+ if (result !== REDIS_COMMAND_OK) {
99
+ const readResult = await client.get(fullKey);
100
+ if (!readResult) {
101
+ result = await client.set(fullKey, value, {
102
+ PX: Math.round(expiryTime),
103
+ });
104
+ }
105
+ }
106
+
97
107
  return result === REDIS_COMMAND_OK;
98
108
  };
99
109