@hahnpro/flow-sdk 4.23.8 → 4.24.1

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.
@@ -1,45 +1,56 @@
1
1
  import 'reflect-metadata';
2
- import { CloudEvent } from 'cloudevents';
3
- import { PartialObserver } from 'rxjs';
4
2
  import { API } from '@hahnpro/hpc-api';
5
- import { AmqpConnection, Nack } from './amqp';
3
+ import { ConsumeMessage } from 'amqplib';
4
+ import { AmqpConnectionManager } from 'amqp-connection-manager';
5
+ import { PartialObserver } from 'rxjs';
6
+ import { AmqpConnection, AmqpConnectionConfig } from './amqp';
6
7
  import { ClassType, Flow, FlowElementContext } from './flow.interface';
7
8
  import { FlowEvent } from './FlowEvent';
8
9
  import { Logger } from './FlowLogger';
9
10
  import { RpcClient } from './RpcClient';
11
+ interface FlowAppConfig {
12
+ logger?: Logger;
13
+ amqpConfig?: AmqpConnectionConfig;
14
+ amqpConnection?: AmqpConnectionManager;
15
+ skipApi?: boolean;
16
+ explicitInit?: boolean;
17
+ }
10
18
  export declare class FlowApplication {
11
19
  private modules;
12
20
  private flow;
13
- private readonly baseLogger?;
14
- private amqpConnection?;
15
- private skipApi;
16
- api: API;
21
+ private _api;
22
+ private _rpcClient;
23
+ private amqpChannel;
24
+ private readonly amqpConnection;
25
+ private readonly baseLogger;
17
26
  private context;
18
27
  private declarations;
19
28
  private elements;
29
+ private initialized;
20
30
  private readonly logger;
21
31
  private outputStreamMap;
22
32
  private outputQueueMetrics;
23
33
  private performanceMap;
24
34
  private properties;
25
- private _rpcClient;
26
- private initialized;
35
+ private readonly skipApi;
36
+ constructor(modules: ClassType<any>[], flow: Flow, config?: FlowAppConfig);
27
37
  constructor(modules: ClassType<any>[], flow: Flow, baseLogger?: Logger, amqpConnection?: AmqpConnection, skipApi?: boolean, explicitInit?: boolean);
38
+ get rpcClient(): RpcClient;
39
+ get api(): API;
28
40
  init(): Promise<void>;
29
41
  private publishLifecycleEvent;
30
42
  private setQueueMetrics;
31
43
  private updateMetrics;
32
44
  subscribe: (streamId: string, observer: PartialObserver<FlowEvent>) => import("rxjs").Subscription;
33
- rpcClient: () => RpcClient;
34
45
  emit: (event: FlowEvent) => void;
35
46
  emitPartial: (completeEvent: FlowEvent, partialEvent: FlowEvent) => void;
36
47
  getProperties(): Record<string, any>;
37
- onMessage: (event: CloudEvent<any>) => Promise<Nack | undefined>;
48
+ onMessage: (msg: ConsumeMessage) => Promise<void>;
38
49
  /**
39
50
  * Publish a flow event to the amqp flowlogs exchange.
40
51
  * If the event size exceeds the limit it will be truncated
41
52
  */
42
- publishEvent: (event: FlowEvent) => void;
53
+ publishEvent: (event: FlowEvent) => Promise<boolean>;
43
54
  /**
44
55
  * Calls onDestroy lifecycle method on all flow elements,
45
56
  * closes amqp connection after allowing logs to be processed and published
@@ -56,3 +67,4 @@ export interface Context extends FlowElementContext {
56
67
  app?: FlowApplication;
57
68
  logger?: Logger;
58
69
  }
70
+ export {};
@@ -3,36 +3,33 @@ Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.FlowApplication = void 0;
4
4
  const tslib_1 = require("tslib");
5
5
  require("reflect-metadata");
6
+ const hpc_api_1 = require("@hahnpro/hpc-api");
6
7
  const cloudevents_1 = require("cloudevents");
8
+ const crypto_1 = require("crypto");
7
9
  const object_sizeof_1 = tslib_1.__importDefault(require("object-sizeof"));
8
10
  const perf_hooks_1 = require("perf_hooks");
9
11
  const rxjs_1 = require("rxjs");
10
12
  const operators_1 = require("rxjs/operators");
11
- const crypto_1 = require("crypto");
12
- const hpc_api_1 = require("@hahnpro/hpc-api");
13
13
  const amqp_1 = require("./amqp");
14
- const utils_1 = require("./utils");
15
14
  const flow_interface_1 = require("./flow.interface");
16
15
  const FlowLogger_1 = require("./FlowLogger");
17
16
  const RpcClient_1 = require("./RpcClient");
17
+ const utils_1 = require("./utils");
18
18
  const MAX_EVENT_SIZE_BYTES = +process.env.MAX_EVENT_SIZE_BYTES || 512 * 1024;
19
19
  const WARN_EVENT_PROCESSING_SEC = +process.env.WARN_EVENT_PROCESSING_SEC || 60;
20
20
  const WARN_EVENT_QUEUE_SIZE = +process.env.WARN_EVENT_QUEUE_SIZE || 100;
21
21
  class FlowApplication {
22
- constructor(modules, flow, baseLogger, amqpConnection, skipApi = false, explicitInit = false) {
22
+ constructor(modules, flow, baseLoggerOrConfig, amqpConnection, skipApi, explicitInit) {
23
23
  this.modules = modules;
24
24
  this.flow = flow;
25
- this.baseLogger = baseLogger;
26
- this.amqpConnection = amqpConnection;
27
- this.skipApi = skipApi;
28
25
  this.declarations = {};
29
26
  this.elements = {};
27
+ this.initialized = false;
30
28
  this.outputStreamMap = new Map();
31
29
  this.outputQueueMetrics = new Map();
32
30
  this.performanceMap = new Map();
33
- this.initialized = false;
34
31
  this.publishLifecycleEvent = (element, flowEventId, eventType, data = {}) => {
35
- if (!this.amqpConnection) {
32
+ if (!this.amqpChannel) {
36
33
  return;
37
34
  }
38
35
  try {
@@ -46,7 +43,7 @@ class FlowApplication {
46
43
  time: new Date().toISOString(),
47
44
  });
48
45
  const message = event.toJSON();
49
- return this.amqpConnection.publish('flow', 'lifecycle', message);
46
+ return this.amqpChannel.publish('flow', 'lifecycle', message);
50
47
  }
51
48
  catch (err) {
52
49
  this.logger.error(err);
@@ -76,7 +73,6 @@ class FlowApplication {
76
73
  }
77
74
  };
78
75
  this.subscribe = (streamId, observer) => this.getOutputStream(streamId).subscribe(observer);
79
- this.rpcClient = () => this._rpcClient;
80
76
  this.emit = (event) => {
81
77
  if (event) {
82
78
  try {
@@ -103,13 +99,22 @@ class FlowApplication {
103
99
  this.logger.error(err);
104
100
  }
105
101
  };
106
- this.onMessage = async (event) => {
102
+ this.onMessage = async (msg) => {
107
103
  var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l;
104
+ let event;
105
+ try {
106
+ event = JSON.parse(msg.content.toString());
107
+ }
108
+ catch (err) {
109
+ this.logger.error(err);
110
+ return;
111
+ }
108
112
  if (event.type === 'com.flowstudio.deployment.update') {
109
113
  try {
110
114
  const flow = event.data;
111
115
  if (!flow) {
112
- return new amqp_1.Nack(false);
116
+ this.amqpChannel.nack(msg, false, false);
117
+ return;
113
118
  }
114
119
  let context = {};
115
120
  if (flow.context) {
@@ -139,7 +144,7 @@ class FlowApplication {
139
144
  data: { deploymentId: this.context.deploymentId, status: 'updated' },
140
145
  };
141
146
  try {
142
- (_f = this.amqpConnection) === null || _f === void 0 ? void 0 : _f.publish('deployment', 'health', statusEvent);
147
+ (_f = this.amqpChannel) === null || _f === void 0 ? void 0 : _f.publish('deployment', 'health', statusEvent);
143
148
  }
144
149
  catch (err) {
145
150
  this.logger.error(err);
@@ -155,7 +160,7 @@ class FlowApplication {
155
160
  data: { deploymentId: this.context.deploymentId, status: 'updating failed' },
156
161
  };
157
162
  try {
158
- (_g = this.amqpConnection) === null || _g === void 0 ? void 0 : _g.publish('deployment', 'health', statusEvent);
163
+ (_g = this.amqpChannel) === null || _g === void 0 ? void 0 : _g.publish('deployment', 'health', statusEvent);
159
164
  }
160
165
  catch (e) {
161
166
  this.logger.error(e);
@@ -178,12 +183,11 @@ class FlowApplication {
178
183
  this.destroy();
179
184
  }
180
185
  else {
181
- return new amqp_1.Nack(false);
186
+ this.amqpChannel.nack(msg, false, false);
182
187
  }
183
- return undefined;
184
188
  };
185
189
  this.publishEvent = (event) => {
186
- if (!this.amqpConnection) {
190
+ if (!this.amqpChannel) {
187
191
  return;
188
192
  }
189
193
  try {
@@ -191,13 +195,26 @@ class FlowApplication {
191
195
  if ((0, object_sizeof_1.default)(message) > MAX_EVENT_SIZE_BYTES) {
192
196
  message.data = (0, utils_1.truncate)(message.data);
193
197
  }
194
- return this.amqpConnection.publish('flowlogs', '', message);
198
+ return this.amqpChannel.publish('flowlogs', '', message);
195
199
  }
196
200
  catch (err) {
197
201
  this.logger.error(err);
198
202
  }
199
203
  };
200
- this.logger = new FlowLogger_1.FlowLogger(Object.assign({ id: 'none', functionFqn: 'FlowApplication' }, flow === null || flow === void 0 ? void 0 : flow.context), baseLogger || undefined, this.publishEvent);
204
+ if (baseLoggerOrConfig && !baseLoggerOrConfig.log) {
205
+ const config = baseLoggerOrConfig;
206
+ this.baseLogger = config.logger;
207
+ this.amqpConnection = config.amqpConnection || (0, amqp_1.createAmqpConnection)(config.amqpConfig);
208
+ this.skipApi = config.skipApi || false;
209
+ explicitInit = config.explicitInit || false;
210
+ }
211
+ else {
212
+ this.baseLogger = baseLoggerOrConfig;
213
+ this.amqpConnection = amqpConnection === null || amqpConnection === void 0 ? void 0 : amqpConnection.managedConnection;
214
+ this.skipApi = skipApi || false;
215
+ explicitInit = explicitInit || false;
216
+ }
217
+ this.logger = new FlowLogger_1.FlowLogger(Object.assign({ id: 'none', functionFqn: 'FlowApplication' }, flow === null || flow === void 0 ? void 0 : flow.context), this.baseLogger || undefined, this.publishEvent);
201
218
  process.once('uncaughtException', (err) => {
202
219
  this.logger.error('Uncaught exception!');
203
220
  this.logger.error(err);
@@ -215,14 +232,24 @@ class FlowApplication {
215
232
  this.init();
216
233
  }
217
234
  }
235
+ get rpcClient() {
236
+ if (!this._rpcClient && this.amqpConnection) {
237
+ this._rpcClient = new RpcClient_1.RpcClient(this.amqpConnection, this.logger);
238
+ }
239
+ return this._rpcClient;
240
+ }
241
+ get api() {
242
+ return this._api;
243
+ }
218
244
  async init() {
245
+ var _a;
219
246
  if (this.initialized)
220
247
  return;
221
248
  this.context = Object.assign({}, this.flow.context);
222
249
  this.properties = this.flow.properties || {};
223
250
  try {
224
251
  if (!this.skipApi) {
225
- this.api = new hpc_api_1.API();
252
+ this._api = new hpc_api_1.API();
226
253
  }
227
254
  }
228
255
  catch (err) {
@@ -232,29 +259,28 @@ class FlowApplication {
232
259
  this.logger.error(new Error(err));
233
260
  await this.destroy(1);
234
261
  };
235
- if (this.amqpConnection) {
236
- try {
237
- await this.amqpConnection.managedChannel.assertExchange('deployment', 'direct', { durable: true });
238
- await this.amqpConnection.managedChannel.assertExchange('flowlogs', 'fanout', { durable: true });
239
- await this.amqpConnection.managedChannel.assertExchange('flow', 'direct', { durable: true });
240
- }
241
- catch (e) {
242
- await logErrorAndExit(`Could not assert exchanges: ${e}`);
243
- return;
244
- }
245
- try {
246
- await this.amqpConnection.createSubscriber((msg) => this.onMessage(msg), {
247
- exchange: 'deployment',
248
- routingKey: this.context.deploymentId,
249
- queueOptions: { durable: false, exclusive: true },
250
- }, 'FlowApplication.onMessage');
251
- }
252
- catch (err) {
253
- await logErrorAndExit(`Could not subscribe to deployment exchange: ${err}`);
254
- return;
255
- }
256
- this._rpcClient = new RpcClient_1.RpcClient(this.amqpConnection);
257
- }
262
+ this.amqpChannel = (_a = this.amqpConnection) === null || _a === void 0 ? void 0 : _a.createChannel({
263
+ json: true,
264
+ setup: async (channel) => {
265
+ try {
266
+ await channel.assertExchange('deployment', 'direct', { durable: true });
267
+ await channel.assertExchange('flowlogs', 'fanout', { durable: true });
268
+ await channel.assertExchange('flow', 'direct', { durable: true });
269
+ }
270
+ catch (e) {
271
+ await logErrorAndExit(`Could not assert exchanges: ${e}`);
272
+ }
273
+ try {
274
+ const queue = await channel.assertQueue(null, { durable: false, exclusive: true });
275
+ await channel.bindQueue(queue.queue, 'deployment', this.context.deploymentId);
276
+ await channel.consume(queue.queue, (msg) => this.onMessage(msg));
277
+ }
278
+ catch (err) {
279
+ await logErrorAndExit(`Could not subscribe to deployment exchange: ${err}`);
280
+ }
281
+ },
282
+ });
283
+ this.amqpChannel && (await this.amqpChannel.waitForConnect());
258
284
  for (const module of this.modules) {
259
285
  const moduleName = Reflect.getMetadata('module:name', module);
260
286
  const moduleDeclarations = Reflect.getMetadata('module:declarations', module);
@@ -344,19 +370,19 @@ class FlowApplication {
344
370
  return this.properties;
345
371
  }
346
372
  async destroy(exitCode = 0) {
347
- var _a, _b, _c, _d;
373
+ var _a;
348
374
  try {
349
375
  try {
350
376
  for (const element of Object.values(this.elements)) {
351
377
  (_a = element === null || element === void 0 ? void 0 : element.onDestroy) === null || _a === void 0 ? void 0 : _a.call(element);
352
378
  }
353
- await ((_b = this._rpcClient) === null || _b === void 0 ? void 0 : _b.close());
379
+ this._rpcClient && (await this._rpcClient.close());
354
380
  }
355
381
  catch (err) {
356
382
  this.logger.error(err);
357
383
  }
358
384
  await (0, utils_1.delay)(250);
359
- await ((_d = (_c = this.amqpConnection) === null || _c === void 0 ? void 0 : _c.managedConnection) === null || _d === void 0 ? void 0 : _d.close());
385
+ this.amqpConnection && (await this.amqpConnection.close());
360
386
  }
361
387
  catch (err) {
362
388
  console.error(err);
@@ -93,7 +93,7 @@ class FlowElement {
93
93
  }
94
94
  async callRpcFunction(functionName, ...args) {
95
95
  var _a;
96
- return (_a = this.app) === null || _a === void 0 ? void 0 : _a.rpcClient().callFunction(this.rpcRoutingKey, functionName, ...args);
96
+ return (_a = this.app) === null || _a === void 0 ? void 0 : _a.rpcClient.callFunction(this.rpcRoutingKey, functionName, ...args);
97
97
  }
98
98
  runPyRpcScript(scriptPath, ...args) {
99
99
  const options = {
@@ -1,9 +1,10 @@
1
- import { AmqpConnection } from './amqp';
1
+ import type { AmqpConnectionManager } from 'amqp-connection-manager';
2
+ import { FlowLogger } from './FlowLogger';
2
3
  export declare class RpcClient {
3
- private amqpConnection;
4
- private channel;
4
+ private readonly logger?;
5
+ private readonly channel;
5
6
  private openRequests;
6
- constructor(amqpConnection: AmqpConnection);
7
+ constructor(amqpConnection: AmqpConnectionManager, logger?: FlowLogger);
7
8
  private onMessage;
8
9
  callFunction: (routingKey: string, functionName: string, ...args: any[]) => Promise<unknown>;
9
10
  declareFunction: (routingKey: string, name: string) => (...args: any[]) => Promise<unknown>;
package/dist/RpcClient.js CHANGED
@@ -1,10 +1,14 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.RpcClient = void 0;
4
+ const tslib_1 = require("tslib");
4
5
  const crypto_1 = require("crypto");
6
+ const object_sizeof_1 = tslib_1.__importDefault(require("object-sizeof"));
7
+ const MAX_MSG_SIZE = +process.env.MAX_RPC_MSG_SIZE_BYTES;
8
+ const WARN_MSG_SIZE = +process.env.WARN_RPC_MSG_SIZE_BYTES;
5
9
  class RpcClient {
6
- constructor(amqpConnection) {
7
- this.amqpConnection = amqpConnection;
10
+ constructor(amqpConnection, logger) {
11
+ this.logger = logger;
8
12
  this.openRequests = new Map();
9
13
  this.onMessage = (msg) => {
10
14
  if (this.openRequests.has(msg.properties.correlationId)) {
@@ -39,6 +43,16 @@ class RpcClient {
39
43
  this.callFunction = (routingKey, functionName, ...args) => {
40
44
  const stack = new Error('test').stack;
41
45
  return new Promise((resolve, reject) => {
46
+ var _a;
47
+ if (MAX_MSG_SIZE || WARN_MSG_SIZE) {
48
+ const messageSize = (0, object_sizeof_1.default)(args);
49
+ if (messageSize > MAX_MSG_SIZE) {
50
+ throw new Error(`Max RPC message size exceeded: ${messageSize} bytes / ${MAX_MSG_SIZE} bytes`);
51
+ }
52
+ if (messageSize > WARN_MSG_SIZE) {
53
+ (_a = this.logger) === null || _a === void 0 ? void 0 : _a.warn(`Large RPC message size detected: ${messageSize} bytes`);
54
+ }
55
+ }
42
56
  const call = { functionName, arguments: args };
43
57
  const correlationId = (0, crypto_1.randomUUID)();
44
58
  this.openRequests.set(correlationId, { resolve, reject, trace: RpcClient.formatTrace(stack) });
@@ -53,7 +67,7 @@ class RpcClient {
53
67
  if (!amqpConnection) {
54
68
  throw new Error('currently no amqp connection available');
55
69
  }
56
- this.channel = this.amqpConnection.managedConnection.createChannel({
70
+ this.channel = amqpConnection.createChannel({
57
71
  json: true,
58
72
  setup: async (channel) => {
59
73
  await channel.assertExchange('rpc_direct_exchange', 'direct', { durable: false });
package/dist/amqp.d.ts CHANGED
@@ -1,37 +1,14 @@
1
- import type { AmqpConnectionManager, ChannelWrapper } from 'amqp-connection-manager';
2
- import type { Channel, Connection, ConsumeMessage, Options } from 'amqplib';
3
- interface SubscriptionResult {
4
- consumerTag: string;
5
- }
1
+ import { AmqpConnectionManager, ChannelWrapper } from 'amqp-connection-manager';
6
2
  export interface AmqpConnection {
7
- channel: Channel;
8
- connection: Connection;
9
3
  managedChannel: ChannelWrapper;
10
4
  managedConnection: AmqpConnectionManager;
11
- createSubscriber<T>(handler: (msg: T | undefined, rawMessage?: ConsumeMessage) => Promise<any | undefined | void>, msgOptions: MessageHandlerOptions, originalHandlerName: string): Promise<SubscriptionResult>;
12
- publish(exchange: string, routingKey: string, message: any, options?: Options.Publish): void;
13
- }
14
- export declare class Nack {
15
- private readonly _requeue;
16
- constructor(_requeue?: boolean);
17
- get requeue(): boolean;
18
- }
19
- export interface MessageHandlerOptions {
20
- exchange: string;
21
- routingKey: string | string[];
22
- queue?: string;
23
- queueOptions?: QueueOptions;
24
5
  }
25
- export interface QueueOptions {
26
- durable?: boolean;
27
- exclusive?: boolean;
28
- autoDelete?: boolean;
29
- arguments?: any;
30
- messageTtl?: number;
31
- expires?: number;
32
- deadLetterExchange?: string;
33
- deadLetterRoutingKey?: string;
34
- maxLength?: number;
35
- maxPriority?: number;
6
+ export interface AmqpConnectionConfig {
7
+ protocol?: string;
8
+ hostname?: string;
9
+ vhost?: string;
10
+ user?: string;
11
+ password?: string;
12
+ port?: number;
36
13
  }
37
- export {};
14
+ export declare function createAmqpConnection(config: AmqpConnectionConfig): AmqpConnectionManager;
package/dist/amqp.js CHANGED
@@ -1,12 +1,13 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.Nack = void 0;
4
- class Nack {
5
- constructor(_requeue = false) {
6
- this._requeue = _requeue;
7
- }
8
- get requeue() {
9
- return this._requeue;
3
+ exports.createAmqpConnection = void 0;
4
+ const amqp_connection_manager_1 = require("amqp-connection-manager");
5
+ function createAmqpConnection(config) {
6
+ if (!config) {
7
+ return;
10
8
  }
9
+ const { protocol = process.env.RABBIT_PROTOCOL || 'amqp', hostname = process.env.RABBIT_HOST || 'localhost', port = +process.env.RABBIT_PORT || 5672, user = process.env.RABBIT_USER || 'guest', password = process.env.RABBIT_PASSWORD || 'guest', vhost = process.env.RABBIT_VHOST || '', } = config;
10
+ const uri = `${protocol}://${user}:${password}@${hostname}:${port}${vhost ? '/' + vhost : ''}`;
11
+ return (0, amqp_connection_manager_1.connect)(uri);
11
12
  }
12
- exports.Nack = Nack;
13
+ exports.createAmqpConnection = createAmqpConnection;
@@ -12,6 +12,7 @@ host = os.getenv("RABBIT_HOST", "localhost")
12
12
  port = os.getenv("RABBIT_PORT", "5672")
13
13
  vhost = os.getenv("RABBIT_VHOST", "")
14
14
  routingKey = os.getenv("RPC_ROUTING_KEY", "rpc")
15
+ max_msg_size = int(os.getenv("MAX_RPC_MSG_SIZE_BYTES", "0"))
15
16
 
16
17
  remote_procedures = {}
17
18
  flow_logs_exchange: AbstractRobustExchange
@@ -64,11 +65,18 @@ async def on_message(exchange: Exchange, message: IncomingMessage):
64
65
 
65
66
 
66
67
  async def send_reply(exchange: Exchange, reply, original_message: Message):
68
+ body = json.dumps(reply).encode("utf-8")
69
+
70
+ if max_msg_size > 0 and len(body) > max_msg_size:
71
+ body = json.dumps(
72
+ {
73
+ "type": "error",
74
+ "message": "Max RPC message size exceeded: " + str(len(body)) + " bytes / " + max_msg_size + " bytes",
75
+ }
76
+ ).encode("utf-8")
77
+
67
78
  await exchange.publish(
68
- Message(
69
- body=json.dumps(reply).encode("utf-8"),
70
- correlation_id=original_message.correlation_id
71
- ),
79
+ Message(body=body, correlation_id=original_message.correlation_id),
72
80
  routing_key=original_message.reply_to,
73
81
  )
74
82
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@hahnpro/flow-sdk",
3
- "version": "4.23.8",
3
+ "version": "4.24.1",
4
4
  "description": "SDK for building Flow Modules",
5
5
  "license": "MIT",
6
6
  "author": {
@@ -24,7 +24,7 @@
24
24
  "access": "public"
25
25
  },
26
26
  "dependencies": {
27
- "amqp-connection-manager": "^3.9.0",
27
+ "amqp-connection-manager": "^4.1.11",
28
28
  "amqplib": "^0.10.3",
29
29
  "class-transformer": "0.5.1",
30
30
  "class-validator": "~0.14.0",
@@ -38,9 +38,6 @@
38
38
  "@hahnpro/hpc-api": "3.7.1"
39
39
  },
40
40
  "devDependencies": {
41
- "@golevelup/nestjs-rabbitmq": "^3.5.0",
42
- "@nestjs/common": "^9.3.9",
43
- "@types/amqp-connection-manager": "^2.0.12",
44
41
  "@types/amqplib": "^0.10.1",
45
42
  "@types/jest": "^29.4.2",
46
43
  "@types/lodash": "^4.14.191",