@cap-js-community/event-queue 1.6.0 → 1.6.2
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 +8 -8
- package/src/EventQueueProcessorBase.js +3 -2
- package/src/index.d.ts +36 -0
- package/src/index.js +1 -0
- package/src/processEventQueue.js +1 -1
- package/src/shared/WorkerQueue.js +6 -2
- package/src/shared/common.js +15 -8
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@cap-js-community/event-queue",
|
|
3
|
-
"version": "1.6.
|
|
3
|
+
"version": "1.6.2",
|
|
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",
|
|
@@ -43,16 +43,16 @@
|
|
|
43
43
|
"node": ">=18"
|
|
44
44
|
},
|
|
45
45
|
"dependencies": {
|
|
46
|
-
"@sap/xssec": "^
|
|
47
|
-
"redis": "^4.
|
|
46
|
+
"@sap/xssec": "^4.2.1",
|
|
47
|
+
"redis": "^4.7.0",
|
|
48
48
|
"verror": "^1.10.1",
|
|
49
|
-
"yaml": "^2.
|
|
49
|
+
"yaml": "^2.5.0"
|
|
50
50
|
},
|
|
51
51
|
"devDependencies": {
|
|
52
|
-
"@cap-js/hana": "^1.1.
|
|
53
|
-
"@cap-js/sqlite": "^1.7.
|
|
54
|
-
"@sap/cds": "^
|
|
55
|
-
"@sap/cds-dk": "^
|
|
52
|
+
"@cap-js/hana": "^1.1.1",
|
|
53
|
+
"@cap-js/sqlite": "^1.7.3",
|
|
54
|
+
"@sap/cds": "^8.1.0",
|
|
55
|
+
"@sap/cds-dk": "^8.1.0",
|
|
56
56
|
"eslint": "^8.57.0",
|
|
57
57
|
"eslint-config-prettier": "^9.1.0",
|
|
58
58
|
"eslint-plugin-jest": "^28.6.0",
|
|
@@ -163,12 +163,13 @@ class EventQueueProcessorBase {
|
|
|
163
163
|
);
|
|
164
164
|
}
|
|
165
165
|
|
|
166
|
-
|
|
167
|
-
this.logger.info("Exiting event queue processing as max time exceeded", {
|
|
166
|
+
logTimeExceededAndPublishContinue(iterationCounter) {
|
|
167
|
+
this.logger.info("Exiting event queue processing as max time exceeded - but broadcast to trigger processing", {
|
|
168
168
|
eventType: this.#eventType,
|
|
169
169
|
eventSubType: this.#eventSubType,
|
|
170
170
|
iterationCounter,
|
|
171
171
|
});
|
|
172
|
+
this.#eventSchedulerInstance.scheduleEvent(this.__context.tenant, this.#eventType, this.#eventSubType, new Date());
|
|
172
173
|
}
|
|
173
174
|
|
|
174
175
|
logStartMessage() {
|
package/src/index.d.ts
CHANGED
|
@@ -117,6 +117,7 @@ export declare class EventQueueProcessorBase {
|
|
|
117
117
|
setShouldRollbackTransaction(key: string): void;
|
|
118
118
|
shouldRollbackTransaction(key: string): boolean;
|
|
119
119
|
beforeProcessingEvents(): Promise<void>;
|
|
120
|
+
addEntryToProcessingMap(key: string, queueEntry: EventEntity, payload: Object): void;
|
|
120
121
|
|
|
121
122
|
set logger(value: CdsLogger);
|
|
122
123
|
get logger(): CdsLogger;
|
|
@@ -214,3 +215,38 @@ declare class Config {
|
|
|
214
215
|
}
|
|
215
216
|
|
|
216
217
|
export const config: Config;
|
|
218
|
+
|
|
219
|
+
export const workerQueue: WorkerQueue;
|
|
220
|
+
|
|
221
|
+
declare class WorkerQueue {
|
|
222
|
+
constructor(concurrency: number);
|
|
223
|
+
|
|
224
|
+
addToQueue(load: number, label: string, priority?: Priorities, cb?: () => any): Promise<any>;
|
|
225
|
+
|
|
226
|
+
_executeFunction(
|
|
227
|
+
load: number,
|
|
228
|
+
label: string,
|
|
229
|
+
cb: () => any,
|
|
230
|
+
resolve: (value?: unknown) => void,
|
|
231
|
+
reject: (reason?: any) => void,
|
|
232
|
+
startTime: bigint,
|
|
233
|
+
priority: string
|
|
234
|
+
): void;
|
|
235
|
+
|
|
236
|
+
get runningPromises(): Array<Promise<any>>;
|
|
237
|
+
get runningLoad(): number;
|
|
238
|
+
|
|
239
|
+
static get instance(): WorkerQueue;
|
|
240
|
+
|
|
241
|
+
get queue(): Record<
|
|
242
|
+
string,
|
|
243
|
+
Array<[number, string, () => any, (value?: unknown) => void, (reason?: any) => void, bigint]>
|
|
244
|
+
>;
|
|
245
|
+
}
|
|
246
|
+
|
|
247
|
+
interface Priorities {
|
|
248
|
+
Low: string;
|
|
249
|
+
Medium: string;
|
|
250
|
+
High: string;
|
|
251
|
+
VeryHigh: string;
|
|
252
|
+
}
|
package/src/index.js
CHANGED
package/src/processEventQueue.js
CHANGED
|
@@ -120,7 +120,7 @@ const reevaluateShouldContinue = (eventTypeInstance, iterationCounter, startTime
|
|
|
120
120
|
return true;
|
|
121
121
|
}
|
|
122
122
|
|
|
123
|
-
eventTypeInstance.
|
|
123
|
+
eventTypeInstance.logTimeExceededAndPublishContinue(iterationCounter);
|
|
124
124
|
return false;
|
|
125
125
|
};
|
|
126
126
|
|
|
@@ -8,7 +8,7 @@ const { Priorities } = require("../constants");
|
|
|
8
8
|
const SetIntervalDriftSafe = require("./SetIntervalDriftSafe");
|
|
9
9
|
|
|
10
10
|
const PRIORITIES = Object.values(Priorities).reverse();
|
|
11
|
-
const
|
|
11
|
+
const PRIORITY_MULTIPLICATION = PRIORITIES.reduce((result, element, index) => {
|
|
12
12
|
result[element] = index + 1;
|
|
13
13
|
return result;
|
|
14
14
|
}, {});
|
|
@@ -152,6 +152,10 @@ class WorkerQueue {
|
|
|
152
152
|
return this.#queue;
|
|
153
153
|
}
|
|
154
154
|
|
|
155
|
+
get runningLoad() {
|
|
156
|
+
return this.#runningLoad;
|
|
157
|
+
}
|
|
158
|
+
|
|
155
159
|
#checkAndLogWaitingTime(startTime, label, priority) {
|
|
156
160
|
const ts = Date.now();
|
|
157
161
|
if (ts - lastLogTs <= 1000) {
|
|
@@ -159,7 +163,7 @@ class WorkerQueue {
|
|
|
159
163
|
}
|
|
160
164
|
lastLogTs = ts;
|
|
161
165
|
const diffMs = Math.round(Number(process.hrtime.bigint() - startTime) / NANO_TO_MS);
|
|
162
|
-
const priorityMultiplication =
|
|
166
|
+
const priorityMultiplication = PRIORITY_MULTIPLICATION[priority];
|
|
163
167
|
let logLevel;
|
|
164
168
|
if (diffMs >= THRESHOLD.ERROR * priorityMultiplication) {
|
|
165
169
|
logLevel = "error";
|
package/src/shared/common.js
CHANGED
|
@@ -1,15 +1,10 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
|
|
3
3
|
const crypto = require("crypto");
|
|
4
|
-
const { promisify } = require("util");
|
|
5
4
|
|
|
6
5
|
const cds = require("@sap/cds");
|
|
7
6
|
const xssec = require("@sap/xssec");
|
|
8
7
|
|
|
9
|
-
const getAuthTokenAsync = promisify(xssec.requests.requestClientCredentialsToken);
|
|
10
|
-
const getCreateSecurityContextAsync = promisify(xssec.createSecurityContext);
|
|
11
|
-
|
|
12
|
-
let authInfoCache = {};
|
|
13
8
|
const MARGIN_AUTH_INFO_EXPIRY = 60 * 1000;
|
|
14
9
|
const COMPONENT_NAME = "/eventQueue/common";
|
|
15
10
|
|
|
@@ -74,9 +69,15 @@ const processChunkedSync = (inputs, chunkSize, chunkHandler) => {
|
|
|
74
69
|
const hashStringTo32Bit = (value) => crypto.createHash("sha256").update(String(value)).digest("base64").slice(0, 32);
|
|
75
70
|
|
|
76
71
|
const _getNewAuthInfo = async (tenantId) => {
|
|
72
|
+
const authInfoCache = getAuthInfo._authInfoCache;
|
|
73
|
+
authInfoCache[tenantId] = authInfoCache[tenantId] ?? {};
|
|
77
74
|
try {
|
|
78
|
-
|
|
79
|
-
|
|
75
|
+
if (!_getNewAuthInfo._xsuaaService) {
|
|
76
|
+
_getNewAuthInfo._xsuaaService = new xssec.XsuaaService(cds.requires.auth.credentials);
|
|
77
|
+
}
|
|
78
|
+
const authService = _getNewAuthInfo._xsuaaService;
|
|
79
|
+
const token = await authService.fetchClientCredentialsToken({ zid: tenantId });
|
|
80
|
+
const authInfo = await authService.createSecurityContext(token.access_token);
|
|
80
81
|
authInfoCache[tenantId].expireTs = authInfo.getExpirationDate().getTime() - MARGIN_AUTH_INFO_EXPIRY;
|
|
81
82
|
return authInfo;
|
|
82
83
|
} catch (err) {
|
|
@@ -89,7 +90,13 @@ const getAuthInfo = async (tenantId) => {
|
|
|
89
90
|
if (!cds.requires?.auth?.credentials) {
|
|
90
91
|
return null; // no credentials not authInfo
|
|
91
92
|
}
|
|
93
|
+
if (!cds.requires?.auth.kind.match(/jwt|xsuaa/i)) {
|
|
94
|
+
cds.log(COMPONENT_NAME).warn("Only 'jwt' or 'xsuaa' are supported as values for auth.kind.");
|
|
95
|
+
return null;
|
|
96
|
+
}
|
|
92
97
|
|
|
98
|
+
getAuthInfo._authInfoCache = getAuthInfo._authInfoCache ?? {};
|
|
99
|
+
const authInfoCache = getAuthInfo._authInfoCache;
|
|
93
100
|
// not existing or existing but expired
|
|
94
101
|
if (
|
|
95
102
|
!authInfoCache[tenantId] ||
|
|
@@ -110,6 +117,6 @@ module.exports = {
|
|
|
110
117
|
hashStringTo32Bit,
|
|
111
118
|
getAuthInfo,
|
|
112
119
|
__: {
|
|
113
|
-
clearAuthInfoCache: () => (
|
|
120
|
+
clearAuthInfoCache: () => (getAuthInfo._authInfoCache = {}),
|
|
114
121
|
},
|
|
115
122
|
};
|