@cap-js-community/event-queue 1.9.2 → 1.10.0-beta.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/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@cap-js-community/event-queue",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.10.0-beta.0",
|
|
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",
|
|
@@ -23,6 +23,7 @@
|
|
|
23
23
|
"scripts": {
|
|
24
24
|
"test:unit": "jest --testPathIgnorePatterns=\"/test-integration/\"",
|
|
25
25
|
"test:integration": "jest --testPathIgnorePatterns=\"/test/\" --runInBand --forceExit",
|
|
26
|
+
"voter:test:integration": "jest --testPathIgnorePatterns=\"/test/\" --forceExit",
|
|
26
27
|
"test": "npm run test:unit && npm run test:integration",
|
|
27
28
|
"test:all:coverage": "jest --runInBand --forceExit --collect-coverage",
|
|
28
29
|
"test:prepare": "npm run build:ci --prefix=./test-integration/_env",
|
|
@@ -64,7 +65,8 @@
|
|
|
64
65
|
"jest": "^29.7.0",
|
|
65
66
|
"prettier": "^2.8.8",
|
|
66
67
|
"sqlite3": "^5.1.7",
|
|
67
|
-
"@opentelemetry/api": "^1.9.0"
|
|
68
|
+
"@opentelemetry/api": "^1.9.0",
|
|
69
|
+
"@actions/core": "^1.11.1"
|
|
68
70
|
},
|
|
69
71
|
"homepage": "https://cap-js-community.github.io/event-queue/",
|
|
70
72
|
"repository": {
|
package/src/config.js
CHANGED
|
@@ -36,6 +36,44 @@ const BASE_TABLES = {
|
|
|
36
36
|
LOCK: "sap.eventqueue.Lock",
|
|
37
37
|
};
|
|
38
38
|
|
|
39
|
+
const ALLOWED_EVENT_OPTIONS_BASE = [
|
|
40
|
+
"type",
|
|
41
|
+
"subType",
|
|
42
|
+
"load",
|
|
43
|
+
"impl",
|
|
44
|
+
"transactionMode",
|
|
45
|
+
"deleteFinishedEventsAfterDays",
|
|
46
|
+
"useEventQueueUser",
|
|
47
|
+
"priority",
|
|
48
|
+
"keepAliveInterval",
|
|
49
|
+
"increasePriorityOverTime",
|
|
50
|
+
"keepAliveMaxInProgressTime",
|
|
51
|
+
"appNames",
|
|
52
|
+
"appInstances",
|
|
53
|
+
"internalEvent",
|
|
54
|
+
];
|
|
55
|
+
|
|
56
|
+
const ALLOWED_EVENT_OPTIONS_AD_HOC = [
|
|
57
|
+
...ALLOWED_EVENT_OPTIONS_BASE,
|
|
58
|
+
"inheritTraceContext",
|
|
59
|
+
"selectMaxChunkSize",
|
|
60
|
+
"parallelEventProcessing",
|
|
61
|
+
"retryAttempts",
|
|
62
|
+
"processAfterCommit",
|
|
63
|
+
"checkForNextChunk",
|
|
64
|
+
"retryFailedAfter",
|
|
65
|
+
"multiInstanceProcessing",
|
|
66
|
+
"kind",
|
|
67
|
+
];
|
|
68
|
+
|
|
69
|
+
const ALLOWED_EVENT_OPTIONS_PERIODIC_EVENT = [
|
|
70
|
+
...ALLOWED_EVENT_OPTIONS_BASE,
|
|
71
|
+
"interval",
|
|
72
|
+
"cron",
|
|
73
|
+
"utc",
|
|
74
|
+
"useCronTimezone",
|
|
75
|
+
];
|
|
76
|
+
|
|
39
77
|
class Config {
|
|
40
78
|
#logger;
|
|
41
79
|
#config;
|
|
@@ -286,7 +324,7 @@ class Config {
|
|
|
286
324
|
});
|
|
287
325
|
}
|
|
288
326
|
|
|
289
|
-
|
|
327
|
+
addCAPOutboxEventBase(serviceName, config) {
|
|
290
328
|
if (this.#eventMap[this.generateKey(CAP_EVENT_TYPE, serviceName)]) {
|
|
291
329
|
const index = this.#config.events.findIndex(
|
|
292
330
|
(event) => event.type === CAP_EVENT_TYPE && event.subType === serviceName
|
|
@@ -294,36 +332,49 @@ class Config {
|
|
|
294
332
|
this.#config.events.splice(index, 1);
|
|
295
333
|
}
|
|
296
334
|
|
|
297
|
-
const eventConfig = {
|
|
335
|
+
const eventConfig = this.#sanitizeParamsAdHocEvent({
|
|
298
336
|
type: CAP_EVENT_TYPE,
|
|
299
337
|
subType: serviceName,
|
|
300
|
-
load: config.load,
|
|
301
338
|
impl: "./outbox/EventQueueGenericOutboxHandler",
|
|
302
|
-
|
|
339
|
+
kind: config.kind ?? "persistent-outbox",
|
|
340
|
+
selectMaxChunkSize: config.selectMaxChunkSize ?? config.chunkSize,
|
|
303
341
|
parallelEventProcessing: config.parallelEventProcessing ?? (config.parallel && CAP_PARALLEL_DEFAULT),
|
|
304
|
-
retryAttempts: config.maxAttempts,
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
deleteFinishedEventsAfterDays: config.deleteFinishedEventsAfterDays,
|
|
309
|
-
appNames: config.appNames,
|
|
310
|
-
appInstances: config.appInstances,
|
|
311
|
-
useEventQueueUser: config.useEventQueueUser,
|
|
312
|
-
retryFailedAfter: config.retryFailedAfter,
|
|
313
|
-
priority: config.priority,
|
|
314
|
-
multiInstanceProcessing: config.multiInstanceProcessing,
|
|
315
|
-
increasePriorityOverTime: config.increasePriorityOverTime,
|
|
316
|
-
keepAliveInterval: config.keepAliveInterval,
|
|
317
|
-
inheritTraceContext: true,
|
|
318
|
-
internalEvent: true,
|
|
319
|
-
};
|
|
342
|
+
retryAttempts: config.retryAttempts ?? config.maxAttempts,
|
|
343
|
+
...config,
|
|
344
|
+
});
|
|
345
|
+
eventConfig.internalEvent = true;
|
|
320
346
|
|
|
321
347
|
this.#basicEventTransformation(eventConfig);
|
|
348
|
+
this.#validateAdHocEvents(this.#eventMap, eventConfig, false);
|
|
322
349
|
this.#basicEventTransformationAfterValidate(eventConfig);
|
|
323
350
|
this.#config.events.push(eventConfig);
|
|
324
351
|
this.#eventMap[this.generateKey(CAP_EVENT_TYPE, serviceName)] = eventConfig;
|
|
325
352
|
}
|
|
326
353
|
|
|
354
|
+
addCAPOutboxEventSpecificAction(serviceName, actionName) {
|
|
355
|
+
const subType = [serviceName, actionName].join(".");
|
|
356
|
+
if (this.#eventMap[this.generateKey(CAP_EVENT_TYPE, subType)]) {
|
|
357
|
+
const index = this.#config.events.findIndex(
|
|
358
|
+
(event) => event.type === CAP_EVENT_TYPE && event.subType === serviceName
|
|
359
|
+
);
|
|
360
|
+
this.#config.events.splice(index, 1);
|
|
361
|
+
}
|
|
362
|
+
|
|
363
|
+
const eventConfig = this.#sanitizeParamsAdHocEvent({
|
|
364
|
+
...this.getEventConfig(CAP_EVENT_TYPE, serviceName),
|
|
365
|
+
...this.getCdsOutboxEventSpecificConfig(serviceName, actionName),
|
|
366
|
+
subType,
|
|
367
|
+
});
|
|
368
|
+
eventConfig.internalEvent = true;
|
|
369
|
+
|
|
370
|
+
this.#basicEventTransformation(eventConfig);
|
|
371
|
+
this.#validateAdHocEvents(this.#eventMap, eventConfig, false);
|
|
372
|
+
this.#basicEventTransformationAfterValidate(eventConfig);
|
|
373
|
+
this.#config.events.push(eventConfig);
|
|
374
|
+
this.#eventMap[this.generateKey(CAP_EVENT_TYPE, subType)] = eventConfig;
|
|
375
|
+
return eventConfig;
|
|
376
|
+
}
|
|
377
|
+
|
|
327
378
|
#unblockEventLocalState(key, tenant) {
|
|
328
379
|
const map = this.#blockedEvents[key];
|
|
329
380
|
if (!map) {
|
|
@@ -356,11 +407,59 @@ class Config {
|
|
|
356
407
|
fileContent.periodicEvents ??= [];
|
|
357
408
|
const events = this.#configEvents ?? {};
|
|
358
409
|
const periodicEvents = this.#configPeriodicEvents ?? {};
|
|
410
|
+
const periodicCapServiceEvents = this.#cdsPeriodicOutboxServicesFromEnv();
|
|
359
411
|
fileContent.events = fileContent.events.concat(this.#mapEnvEvents(events));
|
|
360
|
-
fileContent.periodicEvents = fileContent.periodicEvents
|
|
412
|
+
fileContent.periodicEvents = fileContent.periodicEvents
|
|
413
|
+
.concat(this.#mapEnvEvents(periodicEvents))
|
|
414
|
+
.concat(this.#mapCapOutboxPeriodicEvent(periodicCapServiceEvents));
|
|
361
415
|
this.fileContent = fileContent;
|
|
362
416
|
}
|
|
363
417
|
|
|
418
|
+
#mapCapOutboxPeriodicEvent(periodicEventMap) {
|
|
419
|
+
return Object.values(periodicEventMap);
|
|
420
|
+
}
|
|
421
|
+
|
|
422
|
+
#cdsPeriodicOutboxServicesFromEnv() {
|
|
423
|
+
return Object.entries(cds.env.requires).reduce((result, [name, value]) => {
|
|
424
|
+
if (value.outbox?.events) {
|
|
425
|
+
for (const fnName in value.outbox.events) {
|
|
426
|
+
const base = { ...value.outbox };
|
|
427
|
+
const fnConfig = value.outbox.events[fnName];
|
|
428
|
+
if (fnConfig.interval || fnConfig.cron) {
|
|
429
|
+
if ("interval" in base || "cron" in base) {
|
|
430
|
+
this.#logger.error(
|
|
431
|
+
"The properties interval|cron must be defined in the event section and will be ignored in the outbox section.",
|
|
432
|
+
{ serviceName: name }
|
|
433
|
+
);
|
|
434
|
+
delete base.cron;
|
|
435
|
+
delete base.interval;
|
|
436
|
+
}
|
|
437
|
+
|
|
438
|
+
result[fnName] = Object.assign(
|
|
439
|
+
{
|
|
440
|
+
type: CAP_EVENT_TYPE,
|
|
441
|
+
subType: `${name}.${fnName}`,
|
|
442
|
+
impl: "./outbox/EventQueueGenericOutboxHandler",
|
|
443
|
+
internalEvent: true,
|
|
444
|
+
},
|
|
445
|
+
base,
|
|
446
|
+
fnConfig
|
|
447
|
+
);
|
|
448
|
+
}
|
|
449
|
+
}
|
|
450
|
+
}
|
|
451
|
+
return result;
|
|
452
|
+
}, {});
|
|
453
|
+
}
|
|
454
|
+
|
|
455
|
+
getCdsOutboxEventSpecificConfig(serviceName, action) {
|
|
456
|
+
if (cds.env.requires[serviceName]?.outbox?.events?.[action]) {
|
|
457
|
+
return cds.env.requires[serviceName].outbox.events[action];
|
|
458
|
+
} else {
|
|
459
|
+
return null;
|
|
460
|
+
}
|
|
461
|
+
}
|
|
462
|
+
|
|
364
463
|
#mapEnvEvents(events) {
|
|
365
464
|
return Object.entries(events)
|
|
366
465
|
.map(([key, event]) => {
|
|
@@ -379,19 +478,21 @@ class Config {
|
|
|
379
478
|
config.events = config.events ?? [];
|
|
380
479
|
config.periodicEvents = config.periodicEvents ?? [];
|
|
381
480
|
this.#eventMap = config.events.reduce((result, event) => {
|
|
382
|
-
this.#
|
|
383
|
-
this.#
|
|
384
|
-
this.#
|
|
385
|
-
|
|
481
|
+
const eventSanitized = this.#sanitizeParamsAdHocEvent(event);
|
|
482
|
+
this.#basicEventTransformation(eventSanitized);
|
|
483
|
+
this.#validateAdHocEvents(result, eventSanitized);
|
|
484
|
+
this.#basicEventTransformationAfterValidate(eventSanitized);
|
|
485
|
+
result[this.generateKey(eventSanitized.type, eventSanitized.subType)] = eventSanitized;
|
|
386
486
|
return result;
|
|
387
487
|
}, {});
|
|
388
488
|
this.#eventMap = config.periodicEvents.reduce((result, event) => {
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
this.#
|
|
393
|
-
this.#
|
|
394
|
-
|
|
489
|
+
const eventSanitized = this.#sanitizeParamsPeriodicEventEvent(event);
|
|
490
|
+
eventSanitized.type = `${eventSanitized.type}${SUFFIX_PERIODIC}`;
|
|
491
|
+
eventSanitized.isPeriodic = true;
|
|
492
|
+
this.#basicEventTransformation(eventSanitized);
|
|
493
|
+
this.#validatePeriodicConfig(result, eventSanitized);
|
|
494
|
+
this.#basicEventTransformationAfterValidate(eventSanitized);
|
|
495
|
+
result[this.generateKey(eventSanitized.type, eventSanitized.subType)] = eventSanitized;
|
|
395
496
|
return result;
|
|
396
497
|
}, this.#eventMap);
|
|
397
498
|
this.#config = config;
|
|
@@ -405,6 +506,23 @@ class Config {
|
|
|
405
506
|
event.keepAliveMaxInProgressTime = event.keepAliveInterval * DEFAULT_MAX_FACTOR_STUCK_2_KEEP_ALIVE_INTERVAL;
|
|
406
507
|
}
|
|
407
508
|
|
|
509
|
+
#sanitizeParamsBase(config, allowList) {
|
|
510
|
+
return Object.entries(config).reduce((result, [name, value]) => {
|
|
511
|
+
if (allowList.includes(name)) {
|
|
512
|
+
result[name] = value;
|
|
513
|
+
}
|
|
514
|
+
return result;
|
|
515
|
+
}, {});
|
|
516
|
+
}
|
|
517
|
+
|
|
518
|
+
#sanitizeParamsAdHocEvent(config) {
|
|
519
|
+
return this.#sanitizeParamsBase(config, ALLOWED_EVENT_OPTIONS_AD_HOC);
|
|
520
|
+
}
|
|
521
|
+
|
|
522
|
+
#sanitizeParamsPeriodicEventEvent(config) {
|
|
523
|
+
return this.#sanitizeParamsBase(config, ALLOWED_EVENT_OPTIONS_PERIODIC_EVENT);
|
|
524
|
+
}
|
|
525
|
+
|
|
408
526
|
#basicEventTransformationAfterValidate(event) {
|
|
409
527
|
event._appNameMap = event.appNames ? Object.fromEntries(new Map(event.appNames.map((a) => [a, true]))) : null;
|
|
410
528
|
event._appInstancesMap = event.appInstances
|
|
@@ -498,16 +616,12 @@ class Config {
|
|
|
498
616
|
throw EventQueueError.invalidInterval(event.type, event.subType, event.interval);
|
|
499
617
|
}
|
|
500
618
|
|
|
501
|
-
if (event.multiInstanceProcessing) {
|
|
502
|
-
throw EventQueueError.multiInstanceProcessingNotAllowed(event.type, event.subType);
|
|
503
|
-
}
|
|
504
|
-
|
|
505
619
|
this.#basicEventValidation(event);
|
|
506
620
|
}
|
|
507
621
|
|
|
508
|
-
#validateAdHocEvents(eventMap, event) {
|
|
622
|
+
#validateAdHocEvents(eventMap, event, checkForDuplication = true) {
|
|
509
623
|
const key = this.generateKey(event.type, event.subType);
|
|
510
|
-
if (eventMap[key] && !eventMap[key].isPeriodic) {
|
|
624
|
+
if (eventMap[key] && !eventMap[key].isPeriodic && checkForDuplication) {
|
|
511
625
|
throw EventQueueError.duplicateEventRegistration(event.type, event.subType);
|
|
512
626
|
}
|
|
513
627
|
|
|
@@ -540,7 +654,7 @@ class Config {
|
|
|
540
654
|
}
|
|
541
655
|
|
|
542
656
|
get events() {
|
|
543
|
-
return this.#
|
|
657
|
+
return Object.values(this.#eventMap).filter((e) => !e.isPeriodic);
|
|
544
658
|
}
|
|
545
659
|
|
|
546
660
|
set configEvents(value) {
|
|
@@ -556,7 +670,7 @@ class Config {
|
|
|
556
670
|
}
|
|
557
671
|
|
|
558
672
|
get periodicEvents() {
|
|
559
|
-
return this.#
|
|
673
|
+
return Object.values(this.#eventMap).filter((e) => e.isPeriodic);
|
|
560
674
|
}
|
|
561
675
|
|
|
562
676
|
isPeriodicEvent(type, subType) {
|
|
@@ -564,7 +678,7 @@ class Config {
|
|
|
564
678
|
}
|
|
565
679
|
|
|
566
680
|
get allEvents() {
|
|
567
|
-
return
|
|
681
|
+
return Object.values(this.#eventMap);
|
|
568
682
|
}
|
|
569
683
|
|
|
570
684
|
get forUpdateTimeout() {
|
package/src/index.d.ts
CHANGED
|
@@ -194,7 +194,7 @@ declare class Config {
|
|
|
194
194
|
blockEvent(type: any, subType: any, isPeriodic: any, tenant?: string): void;
|
|
195
195
|
clearPeriodicEventBlockList(): void;
|
|
196
196
|
unblockEvent(type: any, subType: any, isPeriodic: any, tenant?: string): void;
|
|
197
|
-
|
|
197
|
+
addCAPOutboxEventBase(serviceName: any, config: any): void;
|
|
198
198
|
isEventBlocked(type: any, subType: any, isPeriodicEvent: any, tenant: any): any;
|
|
199
199
|
set isEventQueueActive(value: boolean);
|
|
200
200
|
get isEventQueueActive(): boolean;
|
|
@@ -15,9 +15,22 @@ class EventQueueGenericOutboxHandler extends EventQueueBaseClass {
|
|
|
15
15
|
this.logger = cds.log(`${COMPONENT_NAME}/${eventSubType}`);
|
|
16
16
|
}
|
|
17
17
|
|
|
18
|
+
async processPeriodicEvent(processContext, key, queueEntry) {
|
|
19
|
+
const [serviceName, action] = this.eventSubType.split(".");
|
|
20
|
+
const service = await cds.connect.to(serviceName);
|
|
21
|
+
const msg = new cds.Event({ event: action });
|
|
22
|
+
processContext.user = new cds.User.Privileged({
|
|
23
|
+
id: config.userId,
|
|
24
|
+
authInfo: await common.getTokenInfo(processContext.tenant),
|
|
25
|
+
});
|
|
26
|
+
processContext._eventQueue = { processor: this, key, queueEntries: [queueEntry] };
|
|
27
|
+
await cds.unboxed(service).tx(processContext)["emit"](msg);
|
|
28
|
+
}
|
|
29
|
+
|
|
18
30
|
async processEvent(processContext, key, queueEntries, payload) {
|
|
19
31
|
try {
|
|
20
|
-
const
|
|
32
|
+
const [srvName] = this.eventSubType.split(".");
|
|
33
|
+
const service = await cds.connect.to(srvName);
|
|
21
34
|
const { useEventQueueUser } = this.eventConfig;
|
|
22
35
|
const userId = useEventQueueUser ? config.userId : payload.contextUser;
|
|
23
36
|
const msg = payload._fromSend ? new cds.Request(payload) : new cds.Event(payload);
|
|
@@ -20,16 +20,14 @@ function outboxed(srv, customOpts) {
|
|
|
20
20
|
}
|
|
21
21
|
|
|
22
22
|
const logger = cds.log(COMPONENT_NAME);
|
|
23
|
-
|
|
23
|
+
let outboxOpts = Object.assign(
|
|
24
24
|
{},
|
|
25
25
|
(typeof cds.requires.outbox === "object" && cds.requires.outbox) || {},
|
|
26
26
|
(typeof srv.options?.outbox === "object" && srv.options.outbox) || {},
|
|
27
27
|
customOpts || {}
|
|
28
28
|
);
|
|
29
29
|
|
|
30
|
-
|
|
31
|
-
config.addCAPOutboxEvent(srv.name, outboxOpts);
|
|
32
|
-
}
|
|
30
|
+
config.addCAPOutboxEventBase(srv.name, outboxOpts);
|
|
33
31
|
|
|
34
32
|
const originalSrv = srv[UNBOXED] || srv;
|
|
35
33
|
const outboxedSrv = Object.create(originalSrv);
|
|
@@ -42,9 +40,20 @@ function outboxed(srv, customOpts) {
|
|
|
42
40
|
}
|
|
43
41
|
outboxedSrv.handle = async function (req) {
|
|
44
42
|
const context = req.context || cds.context;
|
|
43
|
+
outboxOpts = Object.assign(
|
|
44
|
+
{},
|
|
45
|
+
(typeof cds.requires.outbox === "object" && cds.requires.outbox) || {},
|
|
46
|
+
(typeof srv.options?.outbox === "object" && srv.options.outbox) || {},
|
|
47
|
+
customOpts || {}
|
|
48
|
+
);
|
|
49
|
+
config.addCAPOutboxEventBase(srv.name, outboxOpts);
|
|
50
|
+
const specificSettings = config.getCdsOutboxEventSpecificConfig(srv.name, req.method);
|
|
51
|
+
if (specificSettings) {
|
|
52
|
+
outboxOpts = config.addCAPOutboxEventSpecificAction(srv.name, req.event);
|
|
53
|
+
}
|
|
54
|
+
|
|
45
55
|
if (outboxOpts.kind === "persistent-outbox") {
|
|
46
|
-
|
|
47
|
-
await _mapToEventAndPublish(context, srv.name, req);
|
|
56
|
+
await _mapToEventAndPublish(context, srv.name, req, !!specificSettings);
|
|
48
57
|
return;
|
|
49
58
|
}
|
|
50
59
|
context.on("succeeded", async () => {
|
|
@@ -70,7 +79,7 @@ function unboxed(srv) {
|
|
|
70
79
|
return srv[UNBOXED] || srv;
|
|
71
80
|
}
|
|
72
81
|
|
|
73
|
-
const _mapToEventAndPublish = async (context, name, req) => {
|
|
82
|
+
const _mapToEventAndPublish = async (context, name, req, actionSpecific) => {
|
|
74
83
|
const eventQueueSpecificValues = {};
|
|
75
84
|
for (const header in req.headers ?? {}) {
|
|
76
85
|
for (const field of EVENT_QUEUE_SPECIFIC_FIELDS) {
|
|
@@ -93,7 +102,7 @@ const _mapToEventAndPublish = async (context, name, req) => {
|
|
|
93
102
|
|
|
94
103
|
await publishEvent(cds.tx(context), {
|
|
95
104
|
type: CDS_EVENT_TYPE,
|
|
96
|
-
subType: name,
|
|
105
|
+
subType: actionSpecific ? [name, req.event].join(".") : name,
|
|
97
106
|
payload: JSON.stringify(event),
|
|
98
107
|
...eventQueueSpecificValues,
|
|
99
108
|
});
|
package/src/runner/openEvents.js
CHANGED
|
@@ -4,6 +4,7 @@ const cds = require("@sap/cds");
|
|
|
4
4
|
|
|
5
5
|
const eventConfig = require("../config");
|
|
6
6
|
const { EventProcessingStatus } = require("../constants");
|
|
7
|
+
const config = require("../config");
|
|
7
8
|
|
|
8
9
|
const MS_IN_DAYS = 24 * 60 * 60 * 1000;
|
|
9
10
|
|
|
@@ -36,8 +37,9 @@ const getOpenQueueEntries = async (tx, filterAppSpecificEvents = true) => {
|
|
|
36
37
|
const result = [];
|
|
37
38
|
for (const { type, subType } of entries) {
|
|
38
39
|
if (eventConfig.isCapOutboxEvent(type)) {
|
|
40
|
+
const [srvName, actionName] = subType.split(".");
|
|
39
41
|
cds.connect
|
|
40
|
-
.to(
|
|
42
|
+
.to(srvName)
|
|
41
43
|
.then((service) => {
|
|
42
44
|
if (!filterAppSpecificEvents) {
|
|
43
45
|
return; // will be done in finally
|
|
@@ -47,6 +49,9 @@ const getOpenQueueEntries = async (tx, filterAppSpecificEvents = true) => {
|
|
|
47
49
|
return;
|
|
48
50
|
}
|
|
49
51
|
cds.outboxed(service);
|
|
52
|
+
if (actionName) {
|
|
53
|
+
config.addCAPOutboxEventSpecificAction(srvName, actionName);
|
|
54
|
+
}
|
|
50
55
|
if (filterAppSpecificEvents) {
|
|
51
56
|
if (eventConfig.shouldBeProcessedInThisApplication(type, subType)) {
|
|
52
57
|
result.push({ type, subType });
|
|
@@ -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;
|