@cap-js-community/event-queue 2.0.0-beta.6 → 2.0.0-beta.8

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": "2.0.0-beta.6",
3
+ "version": "2.0.0-beta.8",
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",
@@ -353,12 +353,14 @@ class EventQueueProcessorBase {
353
353
  statusMap[id] = statusOrUpdateData;
354
354
  return;
355
355
  }
356
+
356
357
  if ([EventProcessingStatus.Error, EventProcessingStatus.Exceeded].includes(statusMap[id].status)) {
357
358
  // NOTE: worst aggregation --> if already error|exceeded keep this state
358
359
  return;
359
360
  }
360
- if (statusMap[id].status >= 0) {
361
- statusMap[id] = { status: statusOrUpdateData };
361
+
362
+ if (statusMap[id].status >= statusOrUpdateData.status) {
363
+ statusMap[id] = statusOrUpdateData;
362
364
  }
363
365
  }
364
366
 
@@ -407,7 +409,7 @@ class EventQueueProcessorBase {
407
409
  if (typeof entry === "number") {
408
410
  result.status = entry;
409
411
  } else if (typeof entry === "object") {
410
- for (const fieldName of ALLOWED_FIELDS_FOR_UPDATE) {
412
+ for (const fieldName of this.allowedFieldsEventHandler) {
411
413
  if (fieldName in entry) {
412
414
  result[fieldName] = entry[fieldName];
413
415
  }
@@ -442,7 +444,8 @@ class EventQueueProcessorBase {
442
444
  });
443
445
  const ts = new Date().toISOString();
444
446
  const updateData = Object.entries(statusMap).reduce((result, [id, data]) => {
445
- const key = ALLOWED_FIELDS_FOR_UPDATE.map((name) => [name, data[name]])
447
+ const key = this.allowedFieldsEventHandler
448
+ .map((name) => [name, data[name]])
446
449
  .flat()
447
450
  .join("##");
448
451
 
@@ -1358,6 +1361,10 @@ class EventQueueProcessorBase {
1358
1361
  get namespace() {
1359
1362
  return this.#namespace;
1360
1363
  }
1364
+
1365
+ get allowedFieldsEventHandler() {
1366
+ return ALLOWED_FIELDS_FOR_UPDATE;
1367
+ }
1361
1368
  }
1362
1369
 
1363
1370
  module.exports = EventQueueProcessorBase;
package/src/config.js CHANGED
@@ -143,7 +143,7 @@ class Config {
143
143
  }
144
144
 
145
145
  isCapOutboxEvent(type) {
146
- return type === CAP_EVENT_TYPE;
146
+ return [CAP_EVENT_TYPE, [CAP_EVENT_TYPE, SUFFIX_PERIODIC].join("")].includes(type);
147
147
  }
148
148
 
149
149
  hasEventAfterCommitFlag(type, subType, namespace = this.namespace) {
@@ -168,15 +168,27 @@ class Config {
168
168
  return { type: "string", value: str };
169
169
  }
170
170
 
171
- #normalizeSubType(rawSubType) {
172
- const [serviceName, actionName] = rawSubType.split(".");
173
- const actionSpecificCall = this.getCdsOutboxEventSpecificConfig(serviceName, actionName);
174
- return actionSpecificCall ? rawSubType : serviceName;
171
+ normalizeSubType(type, rawSubType) {
172
+ if (![CAP_EVENT_TYPE, [CAP_EVENT_TYPE, SUFFIX_PERIODIC].join("")].includes(type)) {
173
+ return { subType: rawSubType };
174
+ }
175
+
176
+ const serviceParts = rawSubType.split(".");
177
+ let srvName = serviceParts.shift();
178
+ while (!cds.env.requires[srvName] && serviceParts.length) {
179
+ srvName = [srvName, serviceParts.shift()].join(".");
180
+ }
181
+ const actionName = serviceParts.shift();
182
+ const actionSpecificCall = this.getCdsOutboxEventSpecificConfig(srvName, actionName);
183
+ return {
184
+ subType: actionSpecificCall ? rawSubType : srvName,
185
+ actionName,
186
+ srvName,
187
+ };
175
188
  }
176
189
 
177
190
  shouldBeProcessedInThisApplication(type, rawSubType, namespace = this.namespace) {
178
- const subType = this.#normalizeSubType(rawSubType);
179
-
191
+ const { subType } = this.normalizeSubType(type, rawSubType);
180
192
  const config = this.#eventMap[this.generateKey(namespace, type, subType)];
181
193
  const appNameConfig = config._appNameMap;
182
194
  const appInstanceConfig = config._appInstancesMap;
@@ -22,8 +22,8 @@ class EventQueueGenericOutboxHandler extends EventQueueBaseClass {
22
22
  }
23
23
 
24
24
  async getQueueEntriesAndSetToInProgress() {
25
- const [serviceName] = this.eventSubType.split(".");
26
- this.__srv = await cds.connect.to(serviceName);
25
+ const { srvName } = config.normalizeSubType(this.eventType, this.eventSubType);
26
+ this.__srv = await cds.connect.to(srvName);
27
27
  this.__srvUnboxed = cds.unboxed(this.__srv);
28
28
  const { handlers, clusterRelevant, specificClusterRelevant } = this.__srvUnboxed.handlers.on.reduce(
29
29
  (result, handler) => {
@@ -309,8 +309,8 @@ class EventQueueGenericOutboxHandler extends EventQueueBaseClass {
309
309
  }
310
310
 
311
311
  async processPeriodicEvent(processContext, key, queueEntry) {
312
- const [, action] = this.eventSubType.split(".");
313
- const reg = new cds.Event({ event: action, eventQueue: { processor: this, key, queueEntries: [queueEntry] } });
312
+ const { actionName } = config.normalizeSubType(this.eventType, this.eventSubType);
313
+ const reg = new cds.Event({ event: actionName, eventQueue: { processor: this, key, queueEntries: [queueEntry] } });
314
314
  await this.#setContextUser(processContext, config.userId, reg);
315
315
  await this.__srvUnboxed.tx(processContext).emit(reg);
316
316
  }
@@ -366,7 +366,11 @@ class EventQueueGenericOutboxHandler extends EventQueueBaseClass {
366
366
  }
367
367
 
368
368
  if (result instanceof Object && !Array.isArray(result)) {
369
- return queueEntries.map((queueEntry) => [queueEntry.ID, result]);
369
+ const allAllowed = !Object.keys(result).some((name) => !this.allowedFieldsEventHandler.includes(name));
370
+ return queueEntries.map((queueEntry) => [
371
+ queueEntry.ID,
372
+ allAllowed ? result : { status: EventProcessingStatus.Done },
373
+ ]);
370
374
  }
371
375
 
372
376
  if (!Array.isArray(result)) {
@@ -377,7 +381,11 @@ class EventQueueGenericOutboxHandler extends EventQueueBaseClass {
377
381
  if (Array.isArray(firstEntry)) {
378
382
  const [, innerResult] = firstEntry;
379
383
  if (innerResult instanceof Object) {
380
- return result;
384
+ const allAllowed = !Object.keys(innerResult).some((name) => !this.allowedFieldsEventHandler.includes(name));
385
+ if (allAllowed) {
386
+ return result;
387
+ }
388
+ return queueEntries.map((queueEntry) => [queueEntry.ID, { status: EventProcessingStatus.Done }]);
381
389
  } else {
382
390
  return result.map(([id, status]) => {
383
391
  return [id, { status }];
@@ -398,6 +406,12 @@ class EventQueueGenericOutboxHandler extends EventQueueBaseClass {
398
406
  }
399
407
 
400
408
  delete entry.ID;
409
+ const allAllowed = !Object.keys(entry).some((name) => !this.allowedFieldsEventHandler.includes(name));
410
+
411
+ if (!allAllowed) {
412
+ result.push([ID, { status: EventProcessingStatus.Done }]);
413
+ }
414
+
401
415
  if (!("status" in entry)) {
402
416
  entry.status = EventProcessingStatus.Done;
403
417
  }
@@ -43,16 +43,16 @@ const _messageHandlerProcessEvents = async (messageData) => {
43
43
  return;
44
44
  }
45
45
 
46
- const [serviceNameOrSubType, actionName] = subType.split(".");
46
+ const { srvName, actionName } = config.normalizeSubType(type, subType);
47
47
  if (!config.getEventConfig(type, subType, namespace)) {
48
48
  if (config.isCapOutboxEvent(type)) {
49
49
  try {
50
- const service = await cds.connect.to(serviceNameOrSubType);
50
+ const service = await cds.connect.to(srvName);
51
51
  cds.outboxed(service);
52
52
  if (actionName) {
53
- const specificSettings = config.getCdsOutboxEventSpecificConfig(serviceNameOrSubType, actionName);
53
+ const specificSettings = config.getCdsOutboxEventSpecificConfig(srvName, actionName);
54
54
  if (specificSettings) {
55
- config.addCAPOutboxEventSpecificAction(serviceNameOrSubType, actionName);
55
+ config.addCAPOutboxEventSpecificAction(srvName, actionName);
56
56
  }
57
57
  }
58
58
  } catch (err) {
@@ -39,7 +39,7 @@ const getOpenQueueEntries = async (tx, filterAppSpecificEvents = true) => {
39
39
  const result = [];
40
40
  for (const { type, subType, namespace } of entries) {
41
41
  if (eventConfig.isCapOutboxEvent(type)) {
42
- const [srvName, actionName] = subType.split(".");
42
+ const { srvName, actionName } = config.normalizeSubType(type, subType);
43
43
  try {
44
44
  const service = await cds.connect.to(srvName);
45
45
  if (filterAppSpecificEvents) {