@cap-js-community/event-queue 1.10.0-beta.2 → 1.10.0-beta.4

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.10.0-beta.2",
3
+ "version": "1.10.0-beta.4",
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",
@@ -57,21 +57,29 @@ class EventQueueGenericOutboxHandler extends EventQueueBaseClass {
57
57
  return super.clusterQueueEntries(queueEntriesWithPayloadMap);
58
58
  }
59
59
  const { genericClusterEvents, specificClusterEvents } = this.#clusterByAction(queueEntriesWithPayloadMap);
60
+
60
61
  if (Object.keys(genericClusterEvents).length) {
61
62
  if (!this.__genericClusterRelevantAndAvailable) {
62
- await super.clusterQueueEntries(genericClusterEvents);
63
+ for (const actionName in genericClusterEvents) {
64
+ await super.clusterQueueEntries(genericClusterEvents[actionName]);
65
+ }
63
66
  } else {
64
- const msg = new cds.Request({
65
- event: "clusterQueueEntries",
66
- eventQueue: {
67
- processor: this,
68
- clusterByPayloadProperty: (propertyName, cb) =>
69
- this.clusterByPayloadProperty(genericClusterEvents, propertyName, cb),
70
- clusterByEventProperty: (propertyName) => this.clusterByEventProperty(genericClusterEvents, propertyName),
71
- },
72
- });
73
- const handlerCluster = await this.__srvUnboxed.tx(this.context).send(msg);
74
- this.#addToProcessingMap(handlerCluster);
67
+ for (const actionName in genericClusterEvents) {
68
+ const msg = new cds.Request({
69
+ event: `clusterQueueEntries`,
70
+ eventQueue: {
71
+ processor: this,
72
+ clusterByPayloadProperty: (propertyName, cb) =>
73
+ this.clusterByPayloadProperty(actionName, genericClusterEvents[actionName], propertyName, cb),
74
+ clusterByEventProperty: (propertyName, cb) =>
75
+ this.clusterByEventProperty(actionName, genericClusterEvents[actionName], propertyName, cb),
76
+ clusterByDataProperty: (propertyName, cb) =>
77
+ this.clusterByDataProperty(actionName, specificClusterEvents[actionName], propertyName, cb),
78
+ },
79
+ });
80
+ const handlerCluster = await this.__srvUnboxed.tx(this.context).send(msg);
81
+ this.#addToProcessingMap(handlerCluster);
82
+ }
75
83
  }
76
84
  }
77
85
 
@@ -81,9 +89,11 @@ class EventQueueGenericOutboxHandler extends EventQueueBaseClass {
81
89
  eventQueue: {
82
90
  processor: this,
83
91
  clusterByPayloadProperty: (propertyName, cb) =>
84
- this.clusterByPayloadProperty(specificClusterEvents[actionName], propertyName, cb),
92
+ this.clusterByPayloadProperty(actionName, specificClusterEvents[actionName], propertyName, cb),
85
93
  clusterByEventProperty: (propertyName, cb) =>
86
- this.clusterByEventProperty(specificClusterEvents[actionName], propertyName, cb),
94
+ this.clusterByEventProperty(actionName, specificClusterEvents[actionName], propertyName, cb),
95
+ clusterByDataProperty: (propertyName, cb) =>
96
+ this.clusterByDataProperty(actionName, specificClusterEvents[actionName], propertyName, cb),
87
97
  },
88
98
  });
89
99
  const handlerCluster = await this.__srvUnboxed.tx(this.context).send(msg);
@@ -92,55 +102,66 @@ class EventQueueGenericOutboxHandler extends EventQueueBaseClass {
92
102
  }
93
103
 
94
104
  clusterBase(queueEntriesWithPayloadMap, propertyName, refCb, cb) {
95
- return Object.entries(queueEntriesWithPayloadMap).reduce((result, [, { queueEntry, payload }], index) => {
105
+ const clusters = Object.entries(queueEntriesWithPayloadMap).reduce((result, [, { queueEntry, payload }]) => {
96
106
  const ref = refCb(result, payload, queueEntry);
97
107
  ref.queueEntries.push(queueEntry);
98
- if (cb) {
99
- const clusterResult = cb(ref.payload.data, queueEntry.payload.data, index);
100
- ref.payload.data ??= clusterResult;
101
- }
102
108
  return result;
103
109
  }, {});
110
+
111
+ if (cb) {
112
+ for (const clustersKey in clusters) {
113
+ const clusterData = clusters[clustersKey];
114
+ const clusterResult = cb(
115
+ clustersKey.split("##").pop(),
116
+ clusterData.queueEntries.map((entry) => entry.payload.data)
117
+ );
118
+ if (!clusterResult) {
119
+ throw new Error("hmm??");
120
+ }
121
+ clusterData.payload.data = clusterResult;
122
+ }
123
+ }
124
+ return clusters;
125
+ }
126
+
127
+ #resolveRefBase(result, propertyName, actionName, payload, startRef) {
128
+ const parts = propertyName.split(".");
129
+ const data = JSON.parse(JSON.stringify(payload.data));
130
+ let ref = startRef;
131
+ for (const part of parts) {
132
+ ref = ref[part];
133
+ }
134
+ const key = [actionName, ref].join("##");
135
+ result[key] ??= {
136
+ queueEntries: [],
137
+ payload: { ...payload, data },
138
+ };
139
+ return result[key];
104
140
  }
105
141
 
106
- clusterByPayloadProperty(queueEntriesWithPayloadMap, propertyName, cb) {
142
+ clusterByPayloadProperty(actionName, queueEntriesWithPayloadMap, propertyName, cb) {
107
143
  return this.clusterBase(
108
144
  queueEntriesWithPayloadMap,
109
145
  propertyName,
110
- (result, payload) => {
111
- const parts = propertyName.split(".");
112
- const data = JSON.parse(JSON.stringify(payload.data));
113
- let ref = payload;
114
- for (const part of parts) {
115
- ref = ref[part];
116
- }
117
- result[ref[propertyName]] ??= {
118
- queueEntries: [],
119
- payload: { ...payload, data },
120
- };
121
- return result[ref[propertyName]];
122
- },
146
+ (result, payload) => this.#resolveRefBase(result, propertyName, actionName, payload, payload),
123
147
  cb
124
148
  );
125
149
  }
126
150
 
127
- clusterByEventProperty(queueEntriesWithPayloadMap, propertyName, cb) {
151
+ clusterByEventProperty(actionName, queueEntriesWithPayloadMap, propertyName, cb) {
128
152
  return this.clusterBase(
129
153
  queueEntriesWithPayloadMap,
130
154
  propertyName,
131
- (result, payload, queueEntry) => {
132
- const parts = propertyName.split(".");
133
- const payloadCopy = JSON.parse(JSON.stringify(payload));
134
- let ref = queueEntry;
135
- for (const part of parts) {
136
- ref = ref[part];
137
- }
138
- result[queueEntry[propertyName]] ??= {
139
- queueEntries: [],
140
- payload: payloadCopy,
141
- };
142
- return result[queueEntry[propertyName]];
143
- },
155
+ (result, payload, queueEntry) => this.#resolveRefBase(result, propertyName, actionName, payload, queueEntry),
156
+ cb
157
+ );
158
+ }
159
+
160
+ clusterByDataProperty(actionName, queueEntriesWithPayloadMap, propertyName, cb) {
161
+ return this.clusterBase(
162
+ queueEntriesWithPayloadMap,
163
+ propertyName,
164
+ (result, payload) => this.#resolveRefBase(result, propertyName, actionName, payload, payload.data),
144
165
  cb
145
166
  );
146
167
  }
@@ -153,7 +174,8 @@ class EventQueueGenericOutboxHandler extends EventQueueBaseClass {
153
174
  result.specificClusterEvents[clusterData.payload.event] ??= {};
154
175
  result.specificClusterEvents[clusterData.payload.event][eventId] = clusterData;
155
176
  } else {
156
- result.genericClusterEvents[eventId] = clusterData;
177
+ result.genericClusterEvents[clusterData.payload.event] ??= {};
178
+ result.genericClusterEvents[clusterData.payload.event][eventId] = clusterData;
157
179
  }
158
180
  return result;
159
181
  },
@@ -198,7 +220,7 @@ class EventQueueGenericOutboxHandler extends EventQueueBaseClass {
198
220
  queueEntries: [queueEntry],
199
221
  });
200
222
  msg.event = handlerName;
201
- await this.#setContextUser(this.context, userId);
223
+ await this.#setContextUser(this.context, userId, msg);
202
224
  const data = await this.__srvUnboxed.tx(this.context).send(msg);
203
225
  if (data) {
204
226
  payload.data = data;
@@ -233,7 +255,7 @@ class EventQueueGenericOutboxHandler extends EventQueueBaseClass {
233
255
  async processPeriodicEvent(processContext, key, queueEntry) {
234
256
  const [, action] = this.eventSubType.split(".");
235
257
  const msg = new cds.Event({ event: action, eventQueue: { processor: this, key, queueEntries: [queueEntry] } });
236
- await this.#setContextUser(processContext, config.userId);
258
+ await this.#setContextUser(processContext, config.userId, msg);
237
259
  await this.__srvUnboxed.tx(processContext).emit(msg);
238
260
  }
239
261
 
@@ -248,17 +270,20 @@ class EventQueueGenericOutboxHandler extends EventQueueBaseClass {
248
270
  return { msg, userId, invocationFn };
249
271
  }
250
272
 
251
- async #setContextUser(context, userId) {
273
+ async #setContextUser(context, userId, data) {
252
274
  context.user = new cds.User.Privileged({
253
275
  id: userId,
254
276
  authInfo: await common.getTokenInfo(this.baseContext.tenant),
255
277
  });
278
+ if (data) {
279
+ data.user = context.user;
280
+ }
256
281
  }
257
282
 
258
283
  async processEvent(processContext, key, queueEntries, payload) {
259
284
  try {
260
285
  const { userId, invocationFn, msg } = this.#buildDispatchData(processContext, payload, { key, queueEntries });
261
- await this.#setContextUser(processContext, userId);
286
+ await this.#setContextUser(processContext, userId, msg);
262
287
  const result = await this.__srvUnboxed.tx(processContext)[invocationFn](msg);
263
288
  return this.#determineResultStatus(result, queueEntries);
264
289
  } catch (err) {