Skip to content

Commit cfbe8c5

Browse files
authored
CDS namespace support (#407)
1 parent eee242e commit cfbe8c5

File tree

6 files changed

+80
-22
lines changed

6 files changed

+80
-22
lines changed

src/config.js

Lines changed: 19 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -143,7 +143,7 @@ class Config {
143143
}
144144

145145
isCapOutboxEvent(type) {
146-
return type === CAP_EVENT_TYPE;
146+
return [CAP_EVENT_TYPE, [CAP_EVENT_TYPE, SUFFIX_PERIODIC].join("")].includes(type);
147147
}
148148

149149
hasEventAfterCommitFlag(type, subType, namespace = this.namespace) {
@@ -168,15 +168,27 @@ class Config {
168168
return { type: "string", value: str };
169169
}
170170

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+
};
175188
}
176189

177190
shouldBeProcessedInThisApplication(type, rawSubType, namespace = this.namespace) {
178-
const subType = this.#normalizeSubType(rawSubType);
179-
191+
const { subType } = this.normalizeSubType(type, rawSubType);
180192
const config = this.#eventMap[this.generateKey(namespace, type, subType)];
181193
const appNameConfig = config._appNameMap;
182194
const appInstanceConfig = config._appInstancesMap;

src/outbox/EventQueueGenericOutboxHandler.js

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -22,8 +22,8 @@ class EventQueueGenericOutboxHandler extends EventQueueBaseClass {
2222
}
2323

2424
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);
2727
this.__srvUnboxed = cds.unboxed(this.__srv);
2828
const { handlers, clusterRelevant, specificClusterRelevant } = this.__srvUnboxed.handlers.on.reduce(
2929
(result, handler) => {
@@ -309,8 +309,8 @@ class EventQueueGenericOutboxHandler extends EventQueueBaseClass {
309309
}
310310

311311
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] } });
314314
await this.#setContextUser(processContext, config.userId, reg);
315315
await this.__srvUnboxed.tx(processContext).emit(reg);
316316
}

src/redis/redisSub.js

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -43,16 +43,16 @@ const _messageHandlerProcessEvents = async (messageData) => {
4343
return;
4444
}
4545

46-
const [serviceNameOrSubType, actionName] = subType.split(".");
46+
const { srvName, actionName } = config.normalizeSubType(type, subType);
4747
if (!config.getEventConfig(type, subType, namespace)) {
4848
if (config.isCapOutboxEvent(type)) {
4949
try {
50-
const service = await cds.connect.to(serviceNameOrSubType);
50+
const service = await cds.connect.to(srvName);
5151
cds.outboxed(service);
5252
if (actionName) {
53-
const specificSettings = config.getCdsOutboxEventSpecificConfig(serviceNameOrSubType, actionName);
53+
const specificSettings = config.getCdsOutboxEventSpecificConfig(srvName, actionName);
5454
if (specificSettings) {
55-
config.addCAPOutboxEventSpecificAction(serviceNameOrSubType, actionName);
55+
config.addCAPOutboxEventSpecificAction(srvName, actionName);
5656
}
5757
}
5858
} catch (err) {

src/runner/openEvents.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,7 @@ const getOpenQueueEntries = async (tx, filterAppSpecificEvents = true) => {
3939
const result = [];
4040
for (const { type, subType, namespace } of entries) {
4141
if (eventConfig.isCapOutboxEvent(type)) {
42-
const [srvName, actionName] = subType.split(".");
42+
const { srvName, actionName } = config.normalizeSubType(type, subType);
4343
try {
4444
const service = await cds.connect.to(srvName);
4545
if (filterAppSpecificEvents) {

test/__snapshots__/eventQueueOutbox.test.js.snap

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -385,6 +385,11 @@ exports[`event-queue outbox monkeyPatchCAPOutbox=true return open event types 1`
385385
"subType": "QueueService.main",
386386
"type": "CAP_OUTBOX_PERIODIC",
387387
},
388+
{
389+
"namespace": "default",
390+
"subType": "sapafcsdk.scheduling.ProviderService.timeBucketAction",
391+
"type": "CAP_OUTBOX_PERIODIC",
392+
},
388393
]
389394
`;
390395

test/eventQueueOutbox.test.js

Lines changed: 47 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -141,7 +141,6 @@ cds.env.requires["sapafcsdk.scheduling.ProviderService"] = {
141141
impl: path.join(basePath, "srv/service/standard-service.js"),
142142
outbox: {
143143
kind: "persistent-outbox",
144-
namespace: "namespaceA",
145144
events: {
146145
main: {
147146
priority: "high",
@@ -1732,8 +1731,19 @@ describe("event-queue outbox", () => {
17321731
});
17331732

17341733
describe("redisPubSub", () => {
1735-
beforeAll(() => {
1734+
beforeAll(async () => {
17361735
config.isEventQueueActive = true;
1736+
for (const serviceName in cds.env.requires) {
1737+
const config = cds.env.requires[serviceName];
1738+
if (!config.outbox) {
1739+
continue;
1740+
}
1741+
1742+
delete cds.services[serviceName];
1743+
}
1744+
Object.keys(config._rawEventMap)
1745+
.filter((name) => !name.includes("PERIODIC"))
1746+
.forEach((key) => delete config._rawEventMap[key]);
17371747
});
17381748

17391749
afterAll(() => {
@@ -1750,11 +1760,12 @@ describe("event-queue outbox", () => {
17501760
JSON.stringify({
17511761
type: "CAP_OUTBOX",
17521762
subType: "OutboxCustomHooks",
1763+
namespace: config.namespace,
17531764
})
17541765
);
17551766
expect(runnerSpy).toHaveBeenCalledTimes(1);
1756-
expect(connectSpy).toHaveBeenCalledTimes(0);
1757-
expect(configSpy).toHaveBeenCalledTimes(1);
1767+
expect(connectSpy).toHaveBeenCalledTimes(1);
1768+
expect(configSpy).toHaveBeenCalledTimes(2);
17581769
expect(configAddSpy).toHaveBeenCalledTimes(0);
17591770
expect(loggerMock.callsLengths()).toMatchObject({ error: 0, warn: 0 });
17601771
});
@@ -1769,12 +1780,13 @@ describe("event-queue outbox", () => {
17691780
JSON.stringify({
17701781
type: "CAP_OUTBOX",
17711782
subType: "OutboxCustomHooks.connectSpecific",
1783+
namespace: config.namespace,
17721784
})
17731785
);
17741786
expect(runnerSpy).toHaveBeenCalledTimes(1);
17751787
expect(connectSpy).toHaveBeenCalledTimes(1);
17761788
expect(connectSpy).toHaveBeenCalledWith("OutboxCustomHooks");
1777-
expect(configSpy).toHaveBeenCalledTimes(3);
1789+
expect(configSpy).toHaveBeenCalledTimes(4);
17781790
expect(configAddSpy).toHaveBeenCalledTimes(1);
17791791
expect(loggerMock.callsLengths()).toMatchObject({ error: 0, warn: 0 });
17801792
});
@@ -1789,11 +1801,12 @@ describe("event-queue outbox", () => {
17891801
JSON.stringify({
17901802
type: "CAP_OUTBOX_PERIODIC",
17911803
subType: "NotificationServicePeriodic.main",
1804+
namespace: config.namespace,
17921805
})
17931806
);
17941807
expect(runnerSpy).toHaveBeenCalledTimes(1);
17951808
expect(connectSpy).toHaveBeenCalledTimes(0);
1796-
expect(configSpy).toHaveBeenCalledTimes(1);
1809+
expect(configSpy).toHaveBeenCalledTimes(2);
17971810
expect(configAddSpy).toHaveBeenCalledTimes(0);
17981811
expect(loggerMock.callsLengths()).toMatchObject({ error: 0, warn: 0 });
17991812
});
@@ -2387,6 +2400,34 @@ describe("event-queue outbox", () => {
23872400
});
23882401
});
23892402
});
2403+
2404+
describe("CDS namespace support", () => {
2405+
it("action without any specific config", async () => {
2406+
const service = await cds.connect.to("sapafcsdk.scheduling.ProviderService");
2407+
await service.send("plainStatus", {
2408+
status: EventProcessingStatus.Done,
2409+
});
2410+
await commitAndOpenNew();
2411+
await testHelper.selectEventQueueAndExpectOpen(tx, { expectedLength: 1 });
2412+
await processEventQueue(tx.context, "CAP_OUTBOX", service.name);
2413+
await commitAndOpenNew();
2414+
await testHelper.selectEventQueueAndExpectDone(tx, { expectedLength: 1 });
2415+
expect(loggerMock.callsLengths().error).toEqual(0);
2416+
});
2417+
2418+
it("action with any specific config", async () => {
2419+
const service = await cds.connect.to("sapafcsdk.scheduling.ProviderService");
2420+
await service.send("main", {
2421+
status: EventProcessingStatus.Done,
2422+
});
2423+
await commitAndOpenNew();
2424+
await testHelper.selectEventQueueAndExpectOpen(tx, { expectedLength: 1 });
2425+
await processEventQueue(tx.context, "CAP_OUTBOX", `${service.name}.main`);
2426+
await commitAndOpenNew();
2427+
await testHelper.selectEventQueueAndExpectDone(tx, { expectedLength: 1 });
2428+
expect(loggerMock.callsLengths().error).toEqual(0);
2429+
});
2430+
});
23902431
});
23912432

23922433
const commitAndOpenNew = async () => {

0 commit comments

Comments
 (0)