@cap-js-community/event-queue 1.4.2 → 1.4.3

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,8 +1,9 @@
1
1
  {
2
2
  "name": "@cap-js-community/event-queue",
3
- "version": "1.4.2",
3
+ "version": "1.4.3",
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
+ "types": "src/index.d.ts",
6
7
  "files": [
7
8
  "src",
8
9
  "db",
@@ -22,6 +22,7 @@ const SELECT_LIMIT_EVENTS_PER_TICK = 100;
22
22
  const TRIES_FOR_EXCEEDED_EVENTS = 3;
23
23
  const EVENT_START_AFTER_HEADROOM = 3 * 1000;
24
24
  const ETAG_CHECK_AFTER_MIN = 10;
25
+ const SUFFIX_PERIODIC = "_PERIODIC";
25
26
 
26
27
  class EventQueueProcessorBase {
27
28
  #eventsWithExceededTries = [];
@@ -1095,7 +1096,7 @@ class EventQueueProcessorBase {
1095
1096
  }
1096
1097
 
1097
1098
  get eventType() {
1098
- return this.#eventType;
1099
+ return this.#eventType.replace(SUFFIX_PERIODIC, "");
1099
1100
  }
1100
1101
 
1101
1102
  get eventSubType() {
package/src/config.js CHANGED
@@ -242,8 +242,8 @@ class Config {
242
242
  return key;
243
243
  }
244
244
 
245
- isEventBlocked(type, subType, tenant) {
246
- const map = this.#blockedEvents[this.generateKey(type, subType)];
245
+ isEventBlocked(type, subType, isPeriodicEvent, tenant) {
246
+ const map = this.#blockedEvents[this.generateKey(`${type}${isPeriodicEvent ? SUFFIX_PERIODIC : ""}`, subType)];
247
247
  if (!map) {
248
248
  return false;
249
249
  }
package/src/index.d.ts ADDED
@@ -0,0 +1,138 @@
1
+ import * as cds from "@sap/cds";
2
+
3
+ export declare const EventProcessingStatus: {
4
+ Open: 0;
5
+ InProgress: 1;
6
+ Done: 2;
7
+ Error: 3;
8
+ Exceeded: 4;
9
+ };
10
+
11
+ declare type EventProcessingStatusKeysType = keyof typeof EventProcessingStatus;
12
+ export declare type EventProcessingStatusType = (typeof EventProcessingStatus)[EventProcessingStatusKeysType];
13
+
14
+ export declare const TransactionMode: {
15
+ isolated: "isolated";
16
+ alwaysCommit: "alwaysCommit";
17
+ alwaysRollback: "alwaysRollback";
18
+ };
19
+
20
+ export declare type TransactionModeType = keyof typeof TransactionMode;
21
+
22
+ export declare const Priorities: {
23
+ Low: "low";
24
+ Medium: "medium";
25
+ High: "high";
26
+ VeryHigh: "veryHigh";
27
+ };
28
+ export declare type PrioritiesType = keyof typeof Priorities;
29
+
30
+ interface RedisOptions {
31
+ host: string;
32
+ port: number;
33
+ }
34
+
35
+ interface InitializeParams {
36
+ configFilePath: string;
37
+ registerAsEventProcessor?: boolean;
38
+ processEventsAfterPublish?: boolean;
39
+ isEventQueueActive?: boolean;
40
+ runInterval?: number;
41
+ disableRedis?: boolean;
42
+ updatePeriodicEvents?: boolean;
43
+ thresholdLoggingEventProcessing?: number;
44
+ useAsCAPOutbox?: boolean;
45
+ userId?: string | null;
46
+ cleanupLocksAndEventsForDev?: boolean;
47
+ redisOptions?: RedisOptions;
48
+ insertEventsBeforeCommit?: boolean;
49
+ }
50
+
51
+ type CdsLogger = ReturnType<typeof cds.log>;
52
+
53
+ export function initialize(params: InitializeParams): Promise<void>;
54
+
55
+ type EventConfigType = {
56
+ type: string;
57
+ subType: string;
58
+ priority: string;
59
+ impl: string;
60
+ load: number;
61
+ interval: number;
62
+ internalEvent: boolean;
63
+ isPeriodic: boolean;
64
+ };
65
+
66
+ // Define Status Type
67
+ type Status = 0 | 1 | 2 | 3 | 4;
68
+
69
+ // Define Event Entity Type
70
+ interface EventEntity {
71
+ type: string;
72
+ subType: string;
73
+ referenceEntity?: string;
74
+ referenceEntityKey?: string;
75
+ status: Status;
76
+ payload?: string;
77
+ attempts: number;
78
+ lastAttemptTimestamp?: string;
79
+ createdAt: string;
80
+ startAfter?: string;
81
+ }
82
+
83
+ interface EventEntityPublish {
84
+ type: string;
85
+ subType: string;
86
+ referenceEntity?: string;
87
+ referenceEntityKey?: string;
88
+ payload?: string;
89
+ }
90
+
91
+ interface QueueEntriesPayloadMap {
92
+ [key: string]: {
93
+ queueEntry: EventEntity;
94
+ payload: Object;
95
+ };
96
+ }
97
+
98
+ export declare class EventQueueProcessorBase {
99
+ constructor(context: cds.EventContext, eventType: string, eventSubType: string, config: EventConfigType);
100
+
101
+ processEvent(
102
+ processContext: cds.EventContext,
103
+ key: string,
104
+ queueEntries: EventEntity[],
105
+ payload: Object
106
+ ): Promise<Array<[string, EventProcessingStatusType]>>;
107
+
108
+ processPeriodicEvent(processContext: cds.EventContext, key: string, queueEntry: EventEntity): Promise<undefined>;
109
+ checkEventAndGeneratePayload(queueEntry: EventEntity): Promise<Object>;
110
+ addEventWithPayloadForProcessing(queueEntry: EventEntity, payload: Object): void;
111
+ clusterQueueEntries(queueEntriesWithPayloadMap: Object): void;
112
+ hookForExceededEvents(exceededEvent: EventEntity): Promise<void>;
113
+ clusterQueueEntries(queueEntriesWithPayloadMap: QueueEntriesPayloadMap): void;
114
+ getLastSuccessfulRunTimestamp(): Promise<string | null>;
115
+ getContextForEventProcessing(key: string): cds.EventContext;
116
+ getTxForEventProcessing(key: string): cds.Transaction;
117
+ setShouldRollbackTransaction(key: string): void;
118
+ shouldRollbackTransaction(key: string): boolean;
119
+
120
+ set logger(value: CdsLogger);
121
+ get logger(): CdsLogger;
122
+ get tx(): cds.Transaction;
123
+ get context(): cds.EventContext;
124
+ get isPeriodicEvent(): boolean;
125
+ }
126
+
127
+ export function publishEvent(
128
+ tx: cds.Transaction,
129
+ events: EventEntityPublish[] | EventEntityPublish,
130
+ skipBroadcast?: boolean
131
+ ): Promise<any>;
132
+
133
+ export function processEventQueue(
134
+ context: cds.EventContext,
135
+ eventType: string,
136
+ eventSubType: string,
137
+ startTime: Date
138
+ ): Promise<any>;
package/src/index.js CHANGED
@@ -1,6 +1,5 @@
1
1
  "use strict";
2
2
 
3
- // TODO: how to deal with fatal logs
4
3
  // TODO: add tests for config --> similar to csn check
5
4
 
6
5
  module.exports = {
@@ -263,6 +263,7 @@ const _checkEventIsBlocked = async (baseInstance) => {
263
263
  eventBlocked = config.isEventBlocked(
264
264
  baseInstance.eventType,
265
265
  baseInstance.eventSubType,
266
+ baseInstance.isPeriodicEvent,
266
267
  baseInstance.context.tenant
267
268
  );
268
269
  }
@@ -29,7 +29,9 @@ const broadcastEvent = async (tenantId, events) => {
29
29
  if (config.registerAsEventProcessor) {
30
30
  let context = {};
31
31
  if (tenantId) {
32
- const user = new cds.User.Privileged({ id: config.userId, authInfo: await common.getAuthInfo(tenantId) });
32
+ const user = await cds.tx({ tenant: tenantId }, async () => {
33
+ return new cds.User.Privileged({ id: config.userId, authInfo: await common.getAuthInfo(tenantId) });
34
+ });
33
35
  context = {
34
36
  tenant: tenantId,
35
37
  user,
@@ -35,7 +35,9 @@ const _messageHandlerProcessEvents = async (messageData) => {
35
35
  return;
36
36
  }
37
37
 
38
- const user = new cds.User.Privileged({ id: config.userId, authInfo: await common.getAuthInfo(tenantId) });
38
+ const user = await cds.tx({ tenant: tenantId }, async () => {
39
+ return new cds.User.Privileged({ id: config.userId, authInfo: await common.getAuthInfo(tenantId) });
40
+ });
39
41
  const tenantContext = {
40
42
  tenant: tenantId,
41
43
  user,
@@ -111,6 +111,7 @@ const _executeEventsAllTenantsRedis = async (tenantIds) => {
111
111
 
112
112
  for (const tenantId of tenantIds) {
113
113
  await cds.tx({ tenant: tenantId }, async (tx) => {
114
+ tx.context.user = new cds.User.Privileged({ id: config.userId, authInfo: await common.getAuthInfo(tenantId) });
114
115
  const entries = await openEvents.getOpenQueueEntries(tx);
115
116
  logger.info("broadcasting events for run", {
116
117
  tenantId,
@@ -136,7 +137,9 @@ const _executeEventsAllTenants = async (tenantIds, runId) => {
136
137
  const promises = [];
137
138
 
138
139
  for (const tenantId of tenantIds) {
139
- const user = new cds.User.Privileged({ id: config.userId, authInfo: await common.getAuthInfo(tenantId) });
140
+ const user = await cds.tx({ tenant: tenantId }, async () => {
141
+ return new cds.User.Privileged({ id: config.userId, authInfo: await common.getAuthInfo(tenantId) });
142
+ });
140
143
  const tenantContext = {
141
144
  tenant: tenantId,
142
145
  user,
@@ -180,7 +183,9 @@ const _executeEventsAllTenants = async (tenantIds, runId) => {
180
183
  const _executePeriodicEventsAllTenants = async (tenantIds) => {
181
184
  for (const tenantId of tenantIds) {
182
185
  try {
183
- const user = new cds.User.Privileged({ id: config.userId, authInfo: await common.getAuthInfo(tenantId) });
186
+ const user = await cds.tx({ tenant: tenantId }, async () => {
187
+ return new cds.User.Privileged({ id: config.userId, authInfo: await common.getAuthInfo(tenantId) });
188
+ });
184
189
  const tenantContext = {
185
190
  tenant: tenantId,
186
191
  user,