@seidor-cloud-produtos/orbit-backend-lib 2.0.8 → 2.0.10

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.
@@ -4,7 +4,7 @@ exports.Cache = void 0;
4
4
  const tslib_1 = require("tslib");
5
5
  const logger_in_memory_1 = tslib_1.__importDefault(require("lib/clean-arch/infra/logger/logger-in-memory"));
6
6
  const env_1 = require("../../infra/environment/env");
7
- const logger_1 = require("../logger");
7
+ const types_1 = require("lib/clean-arch/infra/environment/types");
8
8
  class Cache {
9
9
  client;
10
10
  elegibleClients;
@@ -47,7 +47,7 @@ class Cache {
47
47
  }
48
48
  currentClient?.close();
49
49
  }
50
- await logger_in_memory_1.default.log(`Changed cache client to ${this.client.constructor.name}`, { level: logger_1.LevelEnum.WARN });
50
+ await logger_in_memory_1.default.log(`Changed cache client to ${this.client.constructor.name}`, { level: types_1.LOG_LEVEL.warn });
51
51
  return this;
52
52
  }
53
53
  async start(options) {
@@ -159,7 +159,7 @@ class Cache {
159
159
  }
160
160
  async handleException(e) {
161
161
  try {
162
- await logger_in_memory_1.default.log(JSON.stringify(e), { level: logger_1.LevelEnum.ERROR });
162
+ await logger_in_memory_1.default.log(JSON.stringify(e), { level: types_1.LOG_LEVEL.error });
163
163
  }
164
164
  catch { }
165
165
  throw e;
@@ -1,3 +1,4 @@
1
+ import { LOG_LEVEL } from '../../infra/environment/types';
1
2
  export declare enum ActorEnum {
2
3
  SYSTEM = "system",
3
4
  USER = "user"
@@ -6,17 +7,11 @@ export declare enum CategoryEnum {
6
7
  BUSINESS = "business",
7
8
  TECHNICAL = "technical"
8
9
  }
9
- export declare enum LevelEnum {
10
- INFO = "info",
11
- WARN = "warn",
12
- ERROR = "error",
13
- DEBUG = "debug"
14
- }
15
10
  export type LogProperties = {
16
11
  id?: string;
17
12
  actorType: ActorEnum;
18
13
  category: CategoryEnum;
19
- level: LevelEnum;
14
+ level: LOG_LEVEL;
20
15
  actor: string;
21
16
  type: string;
22
17
  tenantId?: string;
@@ -1,6 +1,6 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.LevelEnum = exports.CategoryEnum = exports.ActorEnum = void 0;
3
+ exports.CategoryEnum = exports.ActorEnum = void 0;
4
4
  var ActorEnum;
5
5
  (function (ActorEnum) {
6
6
  ActorEnum["SYSTEM"] = "system";
@@ -11,13 +11,6 @@ var CategoryEnum;
11
11
  CategoryEnum["BUSINESS"] = "business";
12
12
  CategoryEnum["TECHNICAL"] = "technical";
13
13
  })(CategoryEnum || (exports.CategoryEnum = CategoryEnum = {}));
14
- var LevelEnum;
15
- (function (LevelEnum) {
16
- LevelEnum["INFO"] = "info";
17
- LevelEnum["WARN"] = "warn";
18
- LevelEnum["ERROR"] = "error";
19
- LevelEnum["DEBUG"] = "debug";
20
- })(LevelEnum || (exports.LevelEnum = LevelEnum = {}));
21
14
  class LoggerGateway {
22
15
  }
23
16
  exports.default = LoggerGateway;
@@ -3,4 +3,5 @@ import Handler from './handler';
3
3
  export default interface Queue {
4
4
  on(queueName: string, callback: Handler): Promise<void>;
5
5
  publish(exchangeName: string, domainEvent: DomainEvent, configs?: Record<string, any>): Promise<void>;
6
+ get?(queueName: string, options?: any): Promise<unknown>;
6
7
  }
@@ -1,9 +1,8 @@
1
1
  import 'dotenv/config';
2
- import { ENVIRONMENT_TYPES } from './environment';
3
- import { LevelEnum } from '../../application/logger';
2
+ import { ENVIRONMENT_TYPES, LOG_LEVEL } from './types';
4
3
  export declare const env: {
5
4
  NODE_ENV: "test" | "production";
6
5
  CURRENT_ENVIRONMENT: ENVIRONMENT_TYPES;
7
- LOG_LEVEL: LevelEnum.INFO | LevelEnum.ERROR | LevelEnum.DEBUG;
6
+ LOG_LEVEL: LOG_LEVEL.debug | LOG_LEVEL.info | LOG_LEVEL.error;
8
7
  DEFAULT_CACHE_EXPIRATION: number;
9
8
  };
@@ -3,22 +3,21 @@ Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.env = void 0;
4
4
  require("dotenv/config");
5
5
  const zod_1 = require("zod");
6
- const environment_1 = require("./environment");
7
- const logger_1 = require("../../application/logger");
6
+ const types_1 = require("./types");
8
7
  const envSchema = zod_1.z.object({
9
8
  NODE_ENV: zod_1.z.enum(['test', 'production']).default('production'),
10
9
  CURRENT_ENVIRONMENT: zod_1.z
11
10
  .enum([
12
- environment_1.ENVIRONMENT_TYPES.TEST,
13
- environment_1.ENVIRONMENT_TYPES.LOCAL,
14
- environment_1.ENVIRONMENT_TYPES.DEVELOPMENT,
15
- environment_1.ENVIRONMENT_TYPES.HOMOLOGATION,
16
- environment_1.ENVIRONMENT_TYPES.PRODUCTION,
11
+ types_1.ENVIRONMENT_TYPES.TEST,
12
+ types_1.ENVIRONMENT_TYPES.LOCAL,
13
+ types_1.ENVIRONMENT_TYPES.DEVELOPMENT,
14
+ types_1.ENVIRONMENT_TYPES.HOMOLOGATION,
15
+ types_1.ENVIRONMENT_TYPES.PRODUCTION,
17
16
  ])
18
- .default(environment_1.ENVIRONMENT_TYPES.LOCAL),
17
+ .default(types_1.ENVIRONMENT_TYPES.LOCAL),
19
18
  LOG_LEVEL: zod_1.z
20
- .enum([logger_1.LevelEnum.DEBUG, logger_1.LevelEnum.INFO, logger_1.LevelEnum.ERROR])
21
- .default(logger_1.LevelEnum.ERROR),
19
+ .enum([types_1.LOG_LEVEL.debug, types_1.LOG_LEVEL.info, types_1.LOG_LEVEL.error])
20
+ .default(types_1.LOG_LEVEL.error),
22
21
  DEFAULT_CACHE_EXPIRATION: zod_1.z.number().default(360),
23
22
  });
24
23
  const _env = envSchema.safeParse(process.env);
@@ -5,3 +5,9 @@ export declare enum ENVIRONMENT_TYPES {
5
5
  LOCAL = "local",
6
6
  TEST = "test"
7
7
  }
8
+ export declare enum LOG_LEVEL {
9
+ debug = "debug",
10
+ info = "info",
11
+ warn = "warn",
12
+ error = "error"
13
+ }
@@ -1,6 +1,6 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.ENVIRONMENT_TYPES = void 0;
3
+ exports.LOG_LEVEL = exports.ENVIRONMENT_TYPES = void 0;
4
4
  var ENVIRONMENT_TYPES;
5
5
  (function (ENVIRONMENT_TYPES) {
6
6
  ENVIRONMENT_TYPES["PRODUCTION"] = "prod";
@@ -9,3 +9,10 @@ var ENVIRONMENT_TYPES;
9
9
  ENVIRONMENT_TYPES["LOCAL"] = "local";
10
10
  ENVIRONMENT_TYPES["TEST"] = "test";
11
11
  })(ENVIRONMENT_TYPES || (exports.ENVIRONMENT_TYPES = ENVIRONMENT_TYPES = {}));
12
+ var LOG_LEVEL;
13
+ (function (LOG_LEVEL) {
14
+ LOG_LEVEL["debug"] = "debug";
15
+ LOG_LEVEL["info"] = "info";
16
+ LOG_LEVEL["warn"] = "warn";
17
+ LOG_LEVEL["error"] = "error";
18
+ })(LOG_LEVEL || (exports.LOG_LEVEL = LOG_LEVEL = {}));
@@ -3,13 +3,14 @@ Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.LoggerInMemory = void 0;
4
4
  const tslib_1 = require("tslib");
5
5
  const env_1 = require("../../infra/environment/env");
6
- const logger_1 = tslib_1.__importStar(require("../../application/logger"));
6
+ const logger_1 = tslib_1.__importDefault(require("../../application/logger"));
7
+ const types_1 = require("../environment/types");
7
8
  class LoggerInMemory extends logger_1.default {
8
9
  async log(payload, props) {
9
10
  switch (props?.level) {
10
- case logger_1.LevelEnum.ERROR:
11
+ case types_1.LOG_LEVEL.error:
11
12
  return this.error(payload, props);
12
- case logger_1.LevelEnum.WARN:
13
+ case types_1.LOG_LEVEL.warn:
13
14
  return this.warning(payload, props);
14
15
  default:
15
16
  return this.info(payload, props);
@@ -25,7 +26,7 @@ class LoggerInMemory extends logger_1.default {
25
26
  console.warn(error, props);
26
27
  }
27
28
  debug() {
28
- if (env_1.env.LOG_LEVEL === logger_1.LevelEnum.DEBUG)
29
+ if (env_1.env.LOG_LEVEL === types_1.LOG_LEVEL.debug)
29
30
  return this;
30
31
  return undefined;
31
32
  }
@@ -5,6 +5,7 @@ const tslib_1 = require("tslib");
5
5
  const logger_1 = tslib_1.__importStar(require("../../application/logger"));
6
6
  const logger_in_memory_1 = tslib_1.__importDefault(require("./logger-in-memory"));
7
7
  const log_error_1 = tslib_1.__importDefault(require("../../domain/errors/log-error"));
8
+ const types_1 = require("../environment/types");
8
9
  class LogEvent {
9
10
  input;
10
11
  name = 'logservice.log';
@@ -60,7 +61,7 @@ class LoggerOrbit extends logger_1.default {
60
61
  type: 'default',
61
62
  actorType: logger_1.ActorEnum.SYSTEM,
62
63
  category: logger_1.CategoryEnum.TECHNICAL,
63
- level: logger_1.LevelEnum.INFO,
64
+ level: types_1.LOG_LEVEL.info,
64
65
  expirationHours: sevenDaysInHours,
65
66
  };
66
67
  }
@@ -1,7 +1,9 @@
1
+ import amqp from 'amqplib';
1
2
  import Handler from '../../../application/queue/handler';
2
3
  import QueueConnection from '../../../application/queue/queue-connection';
3
4
  import DomainEvent from '../../../domain/events/domain-event';
4
5
  import QueueController from '../queue-controller';
6
+ import { AmqpQueueGetResult } from './types';
5
7
  export default class AmqpQueue implements QueueConnection {
6
8
  private uri;
7
9
  private static instance;
@@ -10,9 +12,12 @@ export default class AmqpQueue implements QueueConnection {
10
12
  private messagesInMemory;
11
13
  private controller;
12
14
  private channels;
13
- constructor();
15
+ constructor(uri?: string);
14
16
  connect(vHost: string): Promise<AmqpQueue>;
15
17
  close(): Promise<void>;
18
+ get(queueName: string, options?: amqp.Options.Get | undefined): Promise<AmqpQueueGetResult | null>;
19
+ ack(channel: amqp.Channel, msg: any): Promise<void>;
20
+ nack(channel: amqp.Channel, msg: any, requeue?: boolean): Promise<void>;
16
21
  on(queueName: string, callback: Handler): Promise<void>;
17
22
  publish(exchangeName: string, domainEvent: DomainEvent, configs?: Record<string, any>): Promise<void>;
18
23
  createConsumers(queueName: string, configs: CreateConsumers): Promise<void>;
@@ -10,8 +10,8 @@ class AmqpQueue {
10
10
  messagesInMemory = [];
11
11
  controller;
12
12
  channels = new Map();
13
- constructor() {
14
- this.uri = process.env.BROKER_AMQP;
13
+ constructor(uri = process.env.BROKER_AMQP) {
14
+ this.uri = uri;
15
15
  }
16
16
  async connect(vHost) {
17
17
  const urlConnection = `${this.uri}/${vHost}`;
@@ -30,6 +30,39 @@ class AmqpQueue {
30
30
  console.log(`⛔ Queue closed on vHost ${this.vHost}`);
31
31
  }
32
32
  }
33
+ async get(queueName, options) {
34
+ try {
35
+ const channel = await this.connection.createChannel();
36
+ const rawMessage = await channel.get(queueName, options);
37
+ if (!rawMessage) {
38
+ await channel.close();
39
+ return null;
40
+ }
41
+ return { rawMessage, channel };
42
+ }
43
+ catch (err) {
44
+ console.log(`⛔ Erro ao obter mensagem de ${queueName}:`, err);
45
+ return null;
46
+ }
47
+ }
48
+ async ack(channel, msg) {
49
+ try {
50
+ channel.ack(msg);
51
+ await channel.close();
52
+ }
53
+ catch (err) {
54
+ console.log("⛔ Erro ao dar ack:", err);
55
+ }
56
+ }
57
+ async nack(channel, msg, requeue = false) {
58
+ try {
59
+ channel.nack(msg, false, requeue);
60
+ await channel.close();
61
+ }
62
+ catch (err) {
63
+ console.log("⛔ Erro ao dar nack:", err);
64
+ }
65
+ }
33
66
  async on(queueName, callback) {
34
67
  try {
35
68
  const channel = await this.connection.createChannel();
@@ -26,10 +26,80 @@ describe('AmqpQueue', () => {
26
26
  ];
27
27
  const mockPublish = (mq['publish'] = vi.fn());
28
28
  await mq['publishMessagesOfMemory']();
29
- console.log(mockPublish.mock.calls);
30
29
  expect(mockPublish.mock.calls).toEqual([
31
30
  ['exchangeName_1', 'domainEvent_1', 'my_cfg_1'],
32
31
  ['exchangeName_2', 'domainEvent_2', 'my_cfg_2'],
33
32
  ]);
34
33
  });
34
+ describe('get', () => {
35
+ it('should return null if no message is found', async () => {
36
+ const mq = new amqp_lib_1.default();
37
+ mq['connection'] = {
38
+ createChannel: vi.fn().mockResolvedValue({
39
+ get: vi.fn().mockResolvedValue(null),
40
+ close: vi.fn(),
41
+ }),
42
+ };
43
+ const result = await mq.get('queueName');
44
+ expect(result).toBeNull();
45
+ });
46
+ it('should return rawMessage and channel if message is found', async () => {
47
+ const fakeMsg = { content: Buffer.from('msg') };
48
+ const fakeChannel = {
49
+ get: vi.fn().mockResolvedValue(fakeMsg),
50
+ close: vi.fn(),
51
+ };
52
+ const mq = new amqp_lib_1.default();
53
+ mq['connection'] = {
54
+ createChannel: vi.fn().mockResolvedValue(fakeChannel),
55
+ };
56
+ const result = await mq.get('queueName');
57
+ expect(result).toEqual({ rawMessage: fakeMsg, channel: fakeChannel });
58
+ expect(fakeChannel.get).toHaveBeenCalledWith('queueName', undefined);
59
+ });
60
+ it('should handle errors and return null', async () => {
61
+ const mq = new amqp_lib_1.default();
62
+ mq['connection'] = {
63
+ createChannel: vi.fn().mockRejectedValue(new Error('fail')),
64
+ };
65
+ const result = await mq.get('queueName');
66
+ expect(result).toBeNull();
67
+ });
68
+ });
69
+ describe('ack', () => {
70
+ it('should call channel.ack and close', async () => {
71
+ const ack = vi.fn();
72
+ const close = vi.fn();
73
+ const channel = { ack, close };
74
+ const mq = new amqp_lib_1.default();
75
+ await mq.ack(channel, 'msg');
76
+ expect(ack).toHaveBeenCalledWith('msg');
77
+ expect(close).toHaveBeenCalled();
78
+ });
79
+ it('should handle errors gracefully', async () => {
80
+ const ack = vi.fn(() => { throw new Error('fail'); });
81
+ const close = vi.fn();
82
+ const channel = { ack, close };
83
+ const mq = new amqp_lib_1.default();
84
+ await expect(mq.ack(channel, 'msg')).resolves.toBeUndefined();
85
+ });
86
+ });
87
+ describe('nack', () => {
88
+ it('should call channel.nack and close', async () => {
89
+ const nack = vi.fn();
90
+ const close = vi.fn();
91
+ const channel = { nack, close };
92
+ const mq = new amqp_lib_1.default();
93
+ await mq.nack(channel, 'msg', true);
94
+ expect(nack).toHaveBeenCalledWith('msg', false, true);
95
+ expect(close).toHaveBeenCalled();
96
+ });
97
+ it('should handle errors gracefully', async () => {
98
+ const nack = vi.fn(() => { throw new Error('fail'); });
99
+ const close = vi.fn();
100
+ const channel = { nack, close };
101
+ const mq = new amqp_lib_1.default();
102
+ await expect(mq.nack(channel, 'msg')).resolves.toBeUndefined();
103
+ });
104
+ });
35
105
  });
@@ -0,0 +1,5 @@
1
+ import amqp from "amqplib";
2
+ export type AmqpQueueGetResult = {
3
+ rawMessage: any;
4
+ channel: amqp.Channel;
5
+ };
@@ -0,0 +1,2 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
@@ -0,0 +1,19 @@
1
+ import Handler from 'lib/clean-arch/application/queue/handler';
2
+ import AmqpQueue from '../queue/rabbitmq/amqp-lib';
3
+ import { AmqpQueueGetResult } from '../queue/rabbitmq/types';
4
+ import { RabbitMQScaledJobOptions } from './types';
5
+ import LoggerGateway from 'lib/clean-arch/application/logger';
6
+ export declare class RabbitMQScaledJobRunner<T = any> {
7
+ private readonly amqpQueue;
8
+ private readonly queueName;
9
+ private readonly vHost;
10
+ private readonly handler;
11
+ private readonly options;
12
+ private readonly logger;
13
+ constructor(amqpQueue: AmqpQueue, queueName: string, vHost: string, handler: Handler, options: RabbitMQScaledJobOptions, logger: LoggerGateway);
14
+ private handleError;
15
+ protected errorStrategy(getResult: AmqpQueueGetResult): Promise<void>;
16
+ private rejectTimeout;
17
+ private finishProcess;
18
+ run(): Promise<void>;
19
+ }
@@ -0,0 +1,80 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.RabbitMQScaledJobRunner = void 0;
4
+ class RabbitMQScaledJobRunner {
5
+ amqpQueue;
6
+ queueName;
7
+ vHost;
8
+ handler;
9
+ options;
10
+ logger;
11
+ constructor(amqpQueue, queueName, vHost, handler, options, logger) {
12
+ this.amqpQueue = amqpQueue;
13
+ this.queueName = queueName;
14
+ this.vHost = vHost;
15
+ this.handler = handler;
16
+ this.options = options;
17
+ this.logger = logger;
18
+ }
19
+ async handleError(error, getResult) {
20
+ this.logger.log(`[RabbitMQScaledJobRunner] Erro: ${error.message}`);
21
+ if (!getResult) {
22
+ return;
23
+ }
24
+ return await this.errorStrategy(getResult);
25
+ }
26
+ async errorStrategy(getResult) {
27
+ const { channel, rawMessage } = getResult;
28
+ try {
29
+ if (this.options.errorStrategy === 'nack-requeue') {
30
+ return await this.amqpQueue.nack(channel, rawMessage, true);
31
+ }
32
+ return await this.amqpQueue.nack(channel, rawMessage, false);
33
+ }
34
+ catch {
35
+ this.logger.log('[RabbitMQScaledJobRunner] Falha ao aplicar estratégia de erro');
36
+ }
37
+ }
38
+ rejectTimeout() {
39
+ return new Promise((_, reject) => setTimeout(() => reject(new Error('Timeout')), this.options.timeoutMs));
40
+ }
41
+ async finishProcess() {
42
+ this.logger.log('[RabbitMQScaledJobRunner] Finished process');
43
+ }
44
+ async run() {
45
+ let getResult = null;
46
+ try {
47
+ await this.amqpQueue.connect(this.vHost);
48
+ getResult = await this.amqpQueue.get(this.queueName, {
49
+ noAck: !this.options.manualAck,
50
+ });
51
+ if (!getResult) {
52
+ this.logger.log('[RabbitMQScaledJobRunner] Nenhuma mensagem disponível.');
53
+ return;
54
+ }
55
+ const { channel, rawMessage } = getResult;
56
+ const msg = this.options.parse(rawMessage);
57
+ this.logger.log(`[RabbitMQScaledJobRunner] Mensagem recebida ${JSON.stringify(msg, null, 2)}`);
58
+ await Promise.race([this.handler.handle(msg), this.rejectTimeout()]);
59
+ if (this.options.manualAck) {
60
+ await this.amqpQueue.ack(channel, rawMessage);
61
+ }
62
+ }
63
+ catch (err) {
64
+ this.logger.log(`[RabbitMQScaledJobRunner] Erro: ${err.message}`);
65
+ if (getResult && this.options.manualAck) {
66
+ await this.handleError(err, getResult);
67
+ }
68
+ }
69
+ finally {
70
+ try {
71
+ await this.amqpQueue.close();
72
+ }
73
+ catch {
74
+ this.logger.log('[RabbitMQScaledJobRunner] Erro ao fechar conexão');
75
+ await this.finishProcess();
76
+ }
77
+ }
78
+ }
79
+ }
80
+ exports.RabbitMQScaledJobRunner = RabbitMQScaledJobRunner;
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,127 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ const vitest_1 = require("vitest");
4
+ const runner_1 = require("./runner");
5
+ const logger_in_memory_1 = require("../logger/logger-in-memory");
6
+ (0, vitest_1.describe)('RabbitMQScaledJobRunner', () => {
7
+ let amqpQueue;
8
+ let handler;
9
+ let options;
10
+ let logger;
11
+ let runner;
12
+ (0, vitest_1.beforeEach)(() => {
13
+ amqpQueue = {
14
+ connect: vitest_1.vi.fn().mockResolvedValue(undefined),
15
+ get: vitest_1.vi.fn().mockResolvedValue(null),
16
+ ack: vitest_1.vi.fn().mockResolvedValue(undefined),
17
+ nack: vitest_1.vi.fn().mockResolvedValue(undefined),
18
+ close: vitest_1.vi.fn().mockResolvedValue(undefined),
19
+ };
20
+ handler = { handle: vitest_1.vi.fn().mockResolvedValue(undefined) };
21
+ options = {
22
+ manualAck: true,
23
+ timeoutMs: 1000,
24
+ errorStrategy: 'nack-dlq',
25
+ parse: vitest_1.vi.fn((raw) => ({ ok: true, msg: 'parsed' })),
26
+ };
27
+ runner = new runner_1.RabbitMQScaledJobRunner(amqpQueue, 'queue', 'vhost', handler, options, new logger_in_memory_1.LoggerInMemory());
28
+ });
29
+ (0, vitest_1.it)('should connect, get, handle, ack and close (happy path)', async () => {
30
+ const rawMessage = { content: Buffer.from('msg') };
31
+ const channel = {};
32
+ amqpQueue.get.mockResolvedValue({ channel, rawMessage });
33
+ await runner.run();
34
+ (0, vitest_1.expect)(amqpQueue.connect).toHaveBeenCalledWith('vhost');
35
+ (0, vitest_1.expect)(amqpQueue.get).toHaveBeenCalledWith('queue', { noAck: false });
36
+ (0, vitest_1.expect)(options.parse).toHaveBeenCalledWith(rawMessage);
37
+ (0, vitest_1.expect)(handler.handle).toHaveBeenCalledWith({ ok: true, msg: 'parsed' });
38
+ (0, vitest_1.expect)(amqpQueue.ack).toHaveBeenCalledWith(channel, rawMessage);
39
+ (0, vitest_1.expect)(amqpQueue.close).toHaveBeenCalled();
40
+ });
41
+ (0, vitest_1.it)('should not ack if manualAck is false', async () => {
42
+ options.manualAck = false;
43
+ const rawMessage = { content: Buffer.from('msg') };
44
+ const channel = {};
45
+ amqpQueue.get.mockResolvedValue({ channel, rawMessage });
46
+ await runner.run();
47
+ (0, vitest_1.expect)(amqpQueue.ack).not.toHaveBeenCalled();
48
+ });
49
+ (0, vitest_1.it)('should nack with correct strategy', async () => {
50
+ options.errorStrategy = 'nack-requeue';
51
+ const rawMessage = { content: Buffer.from('msg') };
52
+ const channel = {};
53
+ amqpQueue.get.mockResolvedValue({ channel, rawMessage });
54
+ handler.handle = vitest_1.vi.fn(() => {
55
+ throw new Error('fail');
56
+ });
57
+ await runner.run();
58
+ (0, vitest_1.expect)(amqpQueue.nack).toHaveBeenCalledWith(channel, rawMessage, true);
59
+ });
60
+ (0, vitest_1.it)('should nack with default strategy', async () => {
61
+ options.errorStrategy = 'nack-dlq';
62
+ const rawMessage = { content: Buffer.from('msg') };
63
+ const channel = {};
64
+ amqpQueue.get.mockResolvedValue({ channel, rawMessage });
65
+ handler.handle = vitest_1.vi.fn(() => {
66
+ throw new Error('fail');
67
+ });
68
+ await runner.run();
69
+ (0, vitest_1.expect)(amqpQueue.nack).toHaveBeenCalledWith(channel, rawMessage, false);
70
+ });
71
+ (0, vitest_1.it)('should log and return if no message is available', async () => {
72
+ amqpQueue.get.mockResolvedValue(null);
73
+ await runner.run();
74
+ (0, vitest_1.expect)(handler.handle).not.toHaveBeenCalled();
75
+ });
76
+ (0, vitest_1.it)('should log error if amqpQueue.connect throws', async () => {
77
+ amqpQueue.connect.mockRejectedValue(new Error('fail'));
78
+ await runner.run();
79
+ (0, vitest_1.expect)(amqpQueue.connect).toHaveBeenCalledWith('vhost');
80
+ });
81
+ (0, vitest_1.it)('should log error if amqpQueue.close throws', async () => {
82
+ amqpQueue.close.mockRejectedValue(new Error('fail'));
83
+ const rawMessage = { content: Buffer.from('msg') };
84
+ const channel = {};
85
+ amqpQueue.get.mockResolvedValue({ channel, rawMessage });
86
+ await runner.run();
87
+ (0, vitest_1.expect)(amqpQueue.close).toHaveBeenCalled();
88
+ });
89
+ (0, vitest_1.it)('should call onFinally if close fails', async () => {
90
+ amqpQueue.close.mockRejectedValue(new Error('fail'));
91
+ const rawMessage = { content: Buffer.from('msg') };
92
+ const channel = {};
93
+ amqpQueue.get.mockResolvedValue({ channel, rawMessage });
94
+ await runner.run();
95
+ // onFinally is called inside finishProcess
96
+ // No assertion needed for logger, just ensure no throw
97
+ });
98
+ (0, vitest_1.it)('should handle timeout and call nack', async () => {
99
+ options.timeoutMs = 10;
100
+ handler.handle = vitest_1.vi.fn(() => new Promise(() => { }));
101
+ const rawMessage = { content: Buffer.from('msg') };
102
+ const channel = {};
103
+ amqpQueue.get.mockResolvedValue({ channel, rawMessage });
104
+ await runner.run();
105
+ (0, vitest_1.expect)(amqpQueue.nack).toHaveBeenCalledWith(channel, rawMessage, false);
106
+ });
107
+ (0, vitest_1.it)('should handle error in nack gracefully', async () => {
108
+ amqpQueue.nack.mockRejectedValue(new Error('fail'));
109
+ options.errorStrategy = 'nack-dlq';
110
+ const rawMessage = { content: Buffer.from('msg') };
111
+ const channel = {};
112
+ amqpQueue.get.mockResolvedValue({ channel, rawMessage });
113
+ handler.handle = vitest_1.vi.fn(() => {
114
+ throw new Error('fail');
115
+ });
116
+ await runner.run();
117
+ (0, vitest_1.expect)(amqpQueue.nack).toHaveBeenCalledWith(channel, rawMessage, false);
118
+ });
119
+ (0, vitest_1.it)('should handle error in ack gracefully', async () => {
120
+ amqpQueue.ack.mockRejectedValue(new Error('fail'));
121
+ const rawMessage = { content: Buffer.from('msg') };
122
+ const channel = {};
123
+ amqpQueue.get.mockResolvedValue({ channel, rawMessage });
124
+ await runner.run();
125
+ (0, vitest_1.expect)(amqpQueue.ack).toHaveBeenCalledWith(channel, rawMessage);
126
+ });
127
+ });
@@ -0,0 +1,7 @@
1
+ export type ErrorStrategy = "nack-dlq" | "nack-requeue";
2
+ export type RabbitMQScaledJobOptions = {
3
+ parse: (raw: any) => any;
4
+ manualAck: boolean;
5
+ errorStrategy: ErrorStrategy;
6
+ timeoutMs: number;
7
+ };
@@ -0,0 +1,2 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
@@ -58,6 +58,7 @@ describe('MappingModel', () => {
58
58
  expect(instance['getBody'].mock.calls.length).toBe(1);
59
59
  expect(instance['setHeader'].mock.calls).toStrictEqual([
60
60
  ['authorizations', ['test']],
61
+ ['fiscalidsfromtenant', '[]'],
61
62
  ['accept-encoding', 'identity'],
62
63
  ]);
63
64
  expect(instance['deleteParams'].mock.calls.length).toBe(1);
@@ -116,6 +117,7 @@ describe('MappingModel', () => {
116
117
  ['header_name_2', 'header_value_2'],
117
118
  ['accept', 'new_header_accept'],
118
119
  ['authorizations', ['test']],
120
+ ['fiscalidsfromtenant', '[]'],
119
121
  ['accept-encoding', 'identity'],
120
122
  ]);
121
123
  expect(instance['setQuery'].mock.calls).toStrictEqual([
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@seidor-cloud-produtos/orbit-backend-lib",
3
- "version": "2.0.8",
3
+ "version": "2.0.10",
4
4
  "description": "Internal lib for backend components",
5
5
  "main": "dist/index.js",
6
6
  "types": "dist/index.d.ts",