@cap-js-community/event-queue 1.2.3 → 1.2.5
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/README.md +0 -1
- package/package.json +11 -11
- package/src/EventQueueProcessorBase.js +10 -7
- package/src/config.js +12 -0
- package/src/initialize.js +49 -18
package/README.md
CHANGED
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@cap-js-community/event-queue",
|
|
3
|
-
"version": "1.2.
|
|
4
|
-
"description": "An event queue that enables secure transactional processing of asynchronous events, featuring instant event processing with Redis Pub/Sub and load distribution across all application instances.",
|
|
3
|
+
"version": "1.2.5",
|
|
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
|
"files": [
|
|
7
7
|
"src",
|
|
@@ -49,15 +49,15 @@
|
|
|
49
49
|
"devDependencies": {
|
|
50
50
|
"@sap/cds": "^7.5.3",
|
|
51
51
|
"@sap/cds-dk": "^7.5.1",
|
|
52
|
-
"eslint": "8.56.0",
|
|
53
|
-
"eslint-config-prettier": "9.1.0",
|
|
54
|
-
"eslint-plugin-jest": "27.6.3",
|
|
55
|
-
"eslint-plugin-node": "11.1.0",
|
|
56
|
-
"express": "4.18.2",
|
|
57
|
-
"hdb": "0.19.7",
|
|
58
|
-
"jest": "29.7.0",
|
|
59
|
-
"prettier": "2.8.8",
|
|
60
|
-
"sqlite3": "5.1.7"
|
|
52
|
+
"eslint": "^8.56.0",
|
|
53
|
+
"eslint-config-prettier": "^9.1.0",
|
|
54
|
+
"eslint-plugin-jest": "^27.6.3",
|
|
55
|
+
"eslint-plugin-node": "^11.1.0",
|
|
56
|
+
"express": "^4.18.2",
|
|
57
|
+
"hdb": "^0.19.7",
|
|
58
|
+
"jest": "^29.7.0",
|
|
59
|
+
"prettier": "^2.8.8",
|
|
60
|
+
"sqlite3": "^5.1.7"
|
|
61
61
|
},
|
|
62
62
|
"homepage": "https://cap-js-community.github.io/event-queue/",
|
|
63
63
|
"repository": {
|
|
@@ -21,7 +21,7 @@ const SELECT_LIMIT_EVENTS_PER_TICK = 100;
|
|
|
21
21
|
const TRIES_FOR_EXCEEDED_EVENTS = 3;
|
|
22
22
|
const EVENT_START_AFTER_HEADROOM = 3 * 1000;
|
|
23
23
|
|
|
24
|
-
let serviceBindingCache =
|
|
24
|
+
let serviceBindingCache = null;
|
|
25
25
|
|
|
26
26
|
class EventQueueProcessorBase {
|
|
27
27
|
#eventsWithExceededTries = [];
|
|
@@ -700,13 +700,16 @@ class EventQueueProcessorBase {
|
|
|
700
700
|
}
|
|
701
701
|
|
|
702
702
|
async #getServiceBindings() {
|
|
703
|
-
if (serviceBindingCache && serviceBindingCache.
|
|
704
|
-
|
|
703
|
+
if (!(serviceBindingCache && serviceBindingCache.expireTs >= Date.now())) {
|
|
704
|
+
const mtxServiceManager = require("@sap/cds-mtxs/srv/plugins/hana/srv-mgr");
|
|
705
|
+
serviceBindingCache = {
|
|
706
|
+
expireTs: Date.now() + 10 * 60 * 1000,
|
|
707
|
+
value: mtxServiceManager.getAll().catch(() => {
|
|
708
|
+
serviceBindingCache = null;
|
|
709
|
+
}),
|
|
710
|
+
};
|
|
705
711
|
}
|
|
706
|
-
|
|
707
|
-
serviceBindingCache.value = await mtxServiceManager.getAll();
|
|
708
|
-
serviceBindingCache.exipreTs = Date.now() + 10 * 60 * 1000;
|
|
709
|
-
return serviceBindingCache.value;
|
|
712
|
+
return await serviceBindingCache.value;
|
|
710
713
|
}
|
|
711
714
|
|
|
712
715
|
async #selectLastSuccessfulPeriodicTimestamp() {
|
package/src/config.js
CHANGED
|
@@ -57,6 +57,7 @@ class Config {
|
|
|
57
57
|
#useAsCAPOutbox;
|
|
58
58
|
#userId;
|
|
59
59
|
#enableTxConsistencyCheck;
|
|
60
|
+
#cleanupLocksAndEventsForDev;
|
|
60
61
|
static #instance;
|
|
61
62
|
constructor() {
|
|
62
63
|
this.#logger = cds.log(COMPONENT_NAME);
|
|
@@ -340,6 +341,9 @@ class Config {
|
|
|
340
341
|
}
|
|
341
342
|
|
|
342
343
|
set runInterval(value) {
|
|
344
|
+
if (!Number.isInteger(value) || value <= 10 * 1000) {
|
|
345
|
+
throw EventQueueError.invalidInterval();
|
|
346
|
+
}
|
|
343
347
|
this.#runInterval = value;
|
|
344
348
|
}
|
|
345
349
|
|
|
@@ -471,6 +475,14 @@ class Config {
|
|
|
471
475
|
return this.#enableTxConsistencyCheck;
|
|
472
476
|
}
|
|
473
477
|
|
|
478
|
+
set cleanupLocksAndEventsForDev(value) {
|
|
479
|
+
this.#cleanupLocksAndEventsForDev = value;
|
|
480
|
+
}
|
|
481
|
+
|
|
482
|
+
get cleanupLocksAndEventsForDev() {
|
|
483
|
+
return this.#cleanupLocksAndEventsForDev;
|
|
484
|
+
}
|
|
485
|
+
|
|
474
486
|
get isMultiTenancy() {
|
|
475
487
|
return !!cds.requires.multitenancy;
|
|
476
488
|
}
|
package/src/initialize.js
CHANGED
|
@@ -14,6 +14,8 @@ const config = require("./config");
|
|
|
14
14
|
const { initEventQueueRedisSubscribe, closeSubscribeClient } = require("./redisPubSub");
|
|
15
15
|
const { closeMainClient } = require("./shared/redis");
|
|
16
16
|
const eventQueueAsOutbox = require("./outbox/eventQueueAsOutbox");
|
|
17
|
+
const { getAllTenantIds } = require("./shared/cdsHelper");
|
|
18
|
+
const { EventProcessingStatus } = require("./constants");
|
|
17
19
|
|
|
18
20
|
const readFileAsync = promisify(fs.readFile);
|
|
19
21
|
|
|
@@ -38,6 +40,7 @@ const CONFIG_VARS = [
|
|
|
38
40
|
["useAsCAPOutbox", false],
|
|
39
41
|
["userId", null],
|
|
40
42
|
["enableTxConsistencyCheck", false],
|
|
43
|
+
["registerCleanupForDev", true],
|
|
41
44
|
];
|
|
42
45
|
|
|
43
46
|
const initialize = async ({
|
|
@@ -55,11 +58,8 @@ const initialize = async ({
|
|
|
55
58
|
useAsCAPOutbox,
|
|
56
59
|
userId,
|
|
57
60
|
enableTxConsistencyCheck,
|
|
61
|
+
cleanupLocksAndEventsForDev,
|
|
58
62
|
} = {}) => {
|
|
59
|
-
// TODO: initialize check:
|
|
60
|
-
// - content of yaml check
|
|
61
|
-
// - betweenRuns
|
|
62
|
-
|
|
63
63
|
if (config.initialized) {
|
|
64
64
|
return;
|
|
65
65
|
}
|
|
@@ -79,7 +79,8 @@ const initialize = async ({
|
|
|
79
79
|
thresholdLoggingEventProcessing,
|
|
80
80
|
useAsCAPOutbox,
|
|
81
81
|
userId,
|
|
82
|
-
enableTxConsistencyCheck
|
|
82
|
+
enableTxConsistencyCheck,
|
|
83
|
+
cleanupLocksAndEventsForDev
|
|
83
84
|
);
|
|
84
85
|
|
|
85
86
|
const logger = cds.log(COMPONENT);
|
|
@@ -90,6 +91,7 @@ const initialize = async ({
|
|
|
90
91
|
cds.on("connect", (service) => {
|
|
91
92
|
if (service.name === "db") {
|
|
92
93
|
dbHandler.registerEventQueueDbHandler(service);
|
|
94
|
+
config.cleanupLocksAndEventsForDev && registerCleanupForDevDb().catch(() => {});
|
|
93
95
|
}
|
|
94
96
|
});
|
|
95
97
|
}
|
|
@@ -108,20 +110,28 @@ const initialize = async ({
|
|
|
108
110
|
};
|
|
109
111
|
|
|
110
112
|
const readConfigFromFile = async (configFilepath) => {
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
113
|
+
try {
|
|
114
|
+
const fileData = await readFileAsync(configFilepath);
|
|
115
|
+
if (/\.ya?ml$/i.test(configFilepath)) {
|
|
116
|
+
return yaml.parse(fileData.toString());
|
|
117
|
+
}
|
|
118
|
+
if (/\.json$/i.test(configFilepath)) {
|
|
119
|
+
return JSON.parse(fileData.toString());
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
throw new VError(
|
|
123
|
+
{
|
|
124
|
+
name: VERROR_CLUSTER_NAME,
|
|
125
|
+
info: { configFilepath },
|
|
126
|
+
},
|
|
127
|
+
"configFilepath with unsupported extension, allowed extensions are .yaml and .json"
|
|
128
|
+
);
|
|
129
|
+
} catch (err) {
|
|
130
|
+
if (config.useAsCAPOutbox) {
|
|
131
|
+
return {};
|
|
132
|
+
}
|
|
133
|
+
throw err;
|
|
117
134
|
}
|
|
118
|
-
throw new VError(
|
|
119
|
-
{
|
|
120
|
-
name: VERROR_CLUSTER_NAME,
|
|
121
|
-
info: { configFilepath },
|
|
122
|
-
},
|
|
123
|
-
"configFilepath with unsupported extension, allowed extensions are .yaml and .json"
|
|
124
|
-
);
|
|
125
135
|
};
|
|
126
136
|
|
|
127
137
|
const registerEventProcessors = () => {
|
|
@@ -149,9 +159,11 @@ const monkeyPatchCAPOutbox = () => {
|
|
|
149
159
|
if (config.useAsCAPOutbox) {
|
|
150
160
|
Object.defineProperty(cds, "outboxed", {
|
|
151
161
|
get: () => eventQueueAsOutbox.outboxed,
|
|
162
|
+
configurable: true,
|
|
152
163
|
});
|
|
153
164
|
Object.defineProperty(cds, "unboxed", {
|
|
154
165
|
get: () => eventQueueAsOutbox.unboxed,
|
|
166
|
+
configurable: true,
|
|
155
167
|
});
|
|
156
168
|
}
|
|
157
169
|
};
|
|
@@ -213,6 +225,25 @@ const registerCdsShutdown = () => {
|
|
|
213
225
|
});
|
|
214
226
|
};
|
|
215
227
|
|
|
228
|
+
const registerCleanupForDevDb = async () => {
|
|
229
|
+
const profile = cds.env.profiles.find((profile) => profile === "development");
|
|
230
|
+
if (!profile) {
|
|
231
|
+
return;
|
|
232
|
+
}
|
|
233
|
+
|
|
234
|
+
const tenantIds = await getAllTenantIds();
|
|
235
|
+
for (const tenantId of tenantIds) {
|
|
236
|
+
await cds.tx({ tenant: tenantId }, async (tx) => {
|
|
237
|
+
await tx.run(DELETE.from(config.tableNameEventLock));
|
|
238
|
+
await tx.run(
|
|
239
|
+
UPDATE.entity(config.tableNameEventQueue).where({ status: EventProcessingStatus.InProgress }).set({
|
|
240
|
+
status: EventProcessingStatus.Error,
|
|
241
|
+
})
|
|
242
|
+
);
|
|
243
|
+
});
|
|
244
|
+
}
|
|
245
|
+
};
|
|
246
|
+
|
|
216
247
|
module.exports = {
|
|
217
248
|
initialize,
|
|
218
249
|
};
|