podverse-mq 5.0.0

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.
Files changed (33) hide show
  1. package/LICENSE +661 -0
  2. package/README.md +37 -0
  3. package/dist/functions/queue/rss/add.d.ts +9 -0
  4. package/dist/functions/queue/rss/add.d.ts.map +1 -0
  5. package/dist/functions/queue/rss/add.js +26 -0
  6. package/dist/functions/queue/rss/addAll.d.ts +6 -0
  7. package/dist/functions/queue/rss/addAll.d.ts.map +1 -0
  8. package/dist/functions/queue/rss/addAll.js +31 -0
  9. package/dist/functions/queue/rss/addRecentlyUpdatedFeedsFromPodcastIndex.d.ts +9 -0
  10. package/dist/functions/queue/rss/addRecentlyUpdatedFeedsFromPodcastIndex.d.ts.map +1 -0
  11. package/dist/functions/queue/rss/addRecentlyUpdatedFeedsFromPodcastIndex.js +36 -0
  12. package/dist/functions/queue/rss/addTrendingPodcastsFromPodcastIndex.d.ts +9 -0
  13. package/dist/functions/queue/rss/addTrendingPodcastsFromPodcastIndex.d.ts.map +1 -0
  14. package/dist/functions/queue/rss/addTrendingPodcastsFromPodcastIndex.js +36 -0
  15. package/dist/functions/queue/rss/runParser.d.ts +3 -0
  16. package/dist/functions/queue/rss/runParser.d.ts.map +1 -0
  17. package/dist/functions/queue/rss/runParser.js +33 -0
  18. package/dist/index.d.ts +6 -0
  19. package/dist/index.d.ts.map +1 -0
  20. package/dist/index.js +12 -0
  21. package/dist/module-alias-config.d.ts +2 -0
  22. package/dist/module-alias-config.d.ts.map +1 -0
  23. package/dist/module-alias-config.js +7 -0
  24. package/dist/services/activeMQArtemis/index.d.ts +44 -0
  25. package/dist/services/activeMQArtemis/index.d.ts.map +1 -0
  26. package/dist/services/activeMQArtemis/index.js +230 -0
  27. package/dist/services/activeMQArtemis/requestService.d.ts +11 -0
  28. package/dist/services/activeMQArtemis/requestService.d.ts.map +1 -0
  29. package/dist/services/activeMQArtemis/requestService.js +43 -0
  30. package/dist/types/mq.d.ts +5 -0
  31. package/dist/types/mq.d.ts.map +1 -0
  32. package/dist/types/mq.js +2 -0
  33. package/package.json +37 -0
package/README.md ADDED
@@ -0,0 +1,37 @@
1
+ # podverse-mq
2
+
3
+ A module for handling Podverse Queue (ActiveMQArtemis / AMQP) interactions.
4
+
5
+ ## Dev Setup
6
+
7
+ ### Environment Variables
8
+
9
+ The environment variables for this module must be set within the app that consumes this module (ex. `podverse-api` or `podverse-workers`). See `podverse-mq/config/index.ts` for a list of the env vars expected.
10
+
11
+ ### Local Dev Workflow
12
+
13
+ Podverse uses many modules that are maintained in separate repos, and they need to be linked and running for a local dev workflow. Please read the `podverse-ops/dev/local-dev-setup.md` file to set up the required dependencies and module linking.
14
+
15
+ ### Running Locally
16
+
17
+ Install the node_modules:
18
+
19
+ ```
20
+ npm install
21
+ ```
22
+
23
+ Then to build:
24
+
25
+ ```
26
+ npm run build
27
+ ```
28
+
29
+ Or if you want the app to auto-build on saved changes:
30
+
31
+ ```
32
+ npm run build:watch
33
+ ```
34
+
35
+ ## Publishing
36
+
37
+ To publish your changes to npm, increment the version number is `package.json` then run `npm publish`.
@@ -0,0 +1,9 @@
1
+ import { ActiveMQArtemisService } from "@queue/services/activeMQArtemis";
2
+ import { MQQueueConfig } from "podverse-helpers";
3
+ type MQRSSAddOptions = MQQueueConfig & {
4
+ feedUrl: string;
5
+ podcastIndexId: number;
6
+ };
7
+ export declare const mqRSSAdd: (activeMQArtemisService: ActiveMQArtemisService, options: MQRSSAddOptions) => Promise<void>;
8
+ export {};
9
+ //# sourceMappingURL=add.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"add.d.ts","sourceRoot":"","sources":["../../../../src/functions/queue/rss/add.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,sBAAsB,EAAE,MAAM,iCAAiC,CAAC;AAEzE,OAAO,EAAE,aAAa,EAAE,MAAM,kBAAkB,CAAC;AAEjD,KAAK,eAAe,GAAG,aAAa,GAAG;IACrC,OAAO,EAAE,MAAM,CAAC;IAChB,cAAc,EAAE,MAAM,CAAC;CACxB,CAAA;AAED,eAAO,MAAM,QAAQ,GACnB,wBAAwB,sBAAsB,EAC9C,SAAS,eAAe,kBAezB,CAAC"}
@@ -0,0 +1,26 @@
1
+ "use strict";
2
+ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
3
+ function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
4
+ return new (P || (P = Promise))(function (resolve, reject) {
5
+ function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
6
+ function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
7
+ function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
8
+ step((generator = generator.apply(thisArg, _arguments || [])).next());
9
+ });
10
+ };
11
+ Object.defineProperty(exports, "__esModule", { value: true });
12
+ exports.mqRSSAdd = void 0;
13
+ const mqRSSAdd = (activeMQArtemisService, options) => __awaiter(void 0, void 0, void 0, function* () {
14
+ yield activeMQArtemisService.initialize();
15
+ const message = {
16
+ url: options.feedUrl,
17
+ podcast_index_id: options.podcastIndexId
18
+ };
19
+ yield activeMQArtemisService.sendMessage({
20
+ queueName: options.queueName,
21
+ message,
22
+ priority: options.priority,
23
+ dedupeCacheTimeMS: options.dedupeCacheTimeMS
24
+ });
25
+ });
26
+ exports.mqRSSAdd = mqRSSAdd;
@@ -0,0 +1,6 @@
1
+ import { ActiveMQArtemisService } from "@queue/services/activeMQArtemis";
2
+ import { MQQueueConfig } from "podverse-helpers";
3
+ type MQRSSAddAllConfig = MQQueueConfig;
4
+ export declare const mqRSSAddAll: (activeMQArtemisService: ActiveMQArtemisService, config: MQRSSAddAllConfig) => Promise<void>;
5
+ export {};
6
+ //# sourceMappingURL=addAll.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"addAll.d.ts","sourceRoot":"","sources":["../../../../src/functions/queue/rss/addAll.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,sBAAsB,EAAE,MAAM,iCAAiC,CAAC;AAEzE,OAAO,EAAE,aAAa,EAAE,MAAM,kBAAkB,CAAC;AAEjD,KAAK,iBAAiB,GAAG,aAAa,CAAC;AAEvC,eAAO,MAAM,WAAW,GACtB,wBAAwB,sBAAsB,EAC9C,QAAQ,iBAAiB,kBAoB1B,CAAC"}
@@ -0,0 +1,31 @@
1
+ "use strict";
2
+ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
3
+ function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
4
+ return new (P || (P = Promise))(function (resolve, reject) {
5
+ function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
6
+ function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
7
+ function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
8
+ step((generator = generator.apply(thisArg, _arguments || [])).next());
9
+ });
10
+ };
11
+ Object.defineProperty(exports, "__esModule", { value: true });
12
+ exports.mqRSSAddAll = void 0;
13
+ const podverse_orm_1 = require("podverse-orm");
14
+ const mqRSSAddAll = (activeMQArtemisService, config) => __awaiter(void 0, void 0, void 0, function* () {
15
+ const feedService = new podverse_orm_1.FeedService();
16
+ const feeds = yield feedService.getAll();
17
+ yield activeMQArtemisService.initialize();
18
+ for (const feed of feeds) {
19
+ const message = {
20
+ url: feed.url,
21
+ podcast_index_id: feed.channel.podcast_index_id
22
+ };
23
+ yield activeMQArtemisService.sendMessage({
24
+ queueName: config.queueName,
25
+ message,
26
+ priority: config.priority,
27
+ dedupeCacheTimeMS: config.dedupeCacheTimeMS
28
+ });
29
+ }
30
+ });
31
+ exports.mqRSSAddAll = mqRSSAddAll;
@@ -0,0 +1,9 @@
1
+ import { PodcastIndexService } from 'podverse-external-services';
2
+ import { MQQueueConfig } from 'podverse-helpers';
3
+ import { ActiveMQArtemisService } from "@queue/services/activeMQArtemis";
4
+ type MQRSSAddAllRecentlyUpdatedFeedsOptions = MQQueueConfig & {
5
+ sinceRange: number;
6
+ };
7
+ export declare const mqRSSAddRecentlyUpdatedFeedsFromPodcastIndex: (activeMQArtemisService: ActiveMQArtemisService, podcastIndexService: PodcastIndexService, options: MQRSSAddAllRecentlyUpdatedFeedsOptions) => Promise<void>;
8
+ export {};
9
+ //# sourceMappingURL=addRecentlyUpdatedFeedsFromPodcastIndex.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"addRecentlyUpdatedFeedsFromPodcastIndex.d.ts","sourceRoot":"","sources":["../../../../src/functions/queue/rss/addRecentlyUpdatedFeedsFromPodcastIndex.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,mBAAmB,EAAE,MAAM,4BAA4B,CAAC;AACjE,OAAO,EAAE,aAAa,EAAE,MAAM,kBAAkB,CAAC;AAEjD,OAAO,EAAE,sBAAsB,EAAE,MAAM,iCAAiC,CAAC;AAGzE,KAAK,sCAAsC,GAAG,aAAa,GAAG;IAC5D,UAAU,EAAE,MAAM,CAAC;CACpB,CAAA;AAED,eAAO,MAAM,4CAA4C,GACvD,wBAAwB,sBAAsB,EAC9C,qBAAqB,mBAAmB,EACxC,SAAS,sCAAsC,kBA0BhD,CAAC"}
@@ -0,0 +1,36 @@
1
+ "use strict";
2
+ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
3
+ function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
4
+ return new (P || (P = Promise))(function (resolve, reject) {
5
+ function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
6
+ function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
7
+ function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
8
+ step((generator = generator.apply(thisArg, _arguments || [])).next());
9
+ });
10
+ };
11
+ Object.defineProperty(exports, "__esModule", { value: true });
12
+ exports.mqRSSAddRecentlyUpdatedFeedsFromPodcastIndex = void 0;
13
+ const podverse_orm_1 = require("podverse-orm");
14
+ const mqRSSAddRecentlyUpdatedFeedsFromPodcastIndex = (activeMQArtemisService, podcastIndexService, options) => __awaiter(void 0, void 0, void 0, function* () {
15
+ const sinceRange = options.sinceRange;
16
+ const recentlyUpdatedFeeds = yield podcastIndexService.recentGetData(sinceRange);
17
+ yield activeMQArtemisService.initialize();
18
+ for (const feed of recentlyUpdatedFeeds) {
19
+ const feedService = new podverse_orm_1.FeedService();
20
+ const dbFeed = yield feedService.getByPodcastIndexId({ podcast_index_id: feed.feedId });
21
+ const shouldAddToQueue = !!dbFeed;
22
+ if (shouldAddToQueue) {
23
+ const message = {
24
+ url: feed.feedUrl,
25
+ podcast_index_id: feed.feedId
26
+ };
27
+ yield activeMQArtemisService.sendMessage({
28
+ queueName: options.queueName,
29
+ message,
30
+ priority: options.priority,
31
+ dedupeCacheTimeMS: options.dedupeCacheTimeMS
32
+ });
33
+ }
34
+ }
35
+ });
36
+ exports.mqRSSAddRecentlyUpdatedFeedsFromPodcastIndex = mqRSSAddRecentlyUpdatedFeedsFromPodcastIndex;
@@ -0,0 +1,9 @@
1
+ import { PodcastIndexService } from 'podverse-external-services';
2
+ import { MQQueueConfig } from 'podverse-helpers';
3
+ import { ActiveMQArtemisService } from '@queue/services/activeMQArtemis';
4
+ type AddTrendingPodcastsOptions = MQQueueConfig & {
5
+ maxFeeds?: number;
6
+ };
7
+ export declare const mqRSSAddTrendingPodcastsFromPodcastIndex: (activeMQArtemisService: ActiveMQArtemisService, podcastIndexService: PodcastIndexService, options: AddTrendingPodcastsOptions) => Promise<void>;
8
+ export {};
9
+ //# sourceMappingURL=addTrendingPodcastsFromPodcastIndex.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"addTrendingPodcastsFromPodcastIndex.d.ts","sourceRoot":"","sources":["../../../../src/functions/queue/rss/addTrendingPodcastsFromPodcastIndex.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,mBAAmB,EAAE,MAAM,4BAA4B,CAAC;AACjE,OAAO,EAAE,aAAa,EAAE,MAAM,kBAAkB,CAAC;AACjD,OAAO,EAAE,sBAAsB,EAAE,MAAM,iCAAiC,CAAC;AAGzE,KAAK,0BAA0B,GAAG,aAAa,GAAG;IAChD,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB,CAAC;AAEF,eAAO,MAAM,wCAAwC,GACnD,wBAAwB,sBAAsB,EAC9C,qBAAqB,mBAAmB,EACxC,SAAS,0BAA0B,KAClC,OAAO,CAAC,IAAI,CAyBd,CAAC"}
@@ -0,0 +1,36 @@
1
+ "use strict";
2
+ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
3
+ function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
4
+ return new (P || (P = Promise))(function (resolve, reject) {
5
+ function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
6
+ function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
7
+ function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
8
+ step((generator = generator.apply(thisArg, _arguments || [])).next());
9
+ });
10
+ };
11
+ Object.defineProperty(exports, "__esModule", { value: true });
12
+ exports.mqRSSAddTrendingPodcastsFromPodcastIndex = void 0;
13
+ const mqRSSAddTrendingPodcastsFromPodcastIndex = (activeMQArtemisService, podcastIndexService, options) => __awaiter(void 0, void 0, void 0, function* () {
14
+ const { queueName, maxFeeds = 1000 } = options;
15
+ try {
16
+ const { feeds } = yield podcastIndexService.trendingGetPodcasts(maxFeeds);
17
+ yield activeMQArtemisService.initialize();
18
+ for (const feed of feeds) {
19
+ const message = {
20
+ url: feed.url,
21
+ podcast_index_id: feed.id
22
+ };
23
+ yield activeMQArtemisService.sendMessage({
24
+ queueName,
25
+ message,
26
+ priority: options.priority,
27
+ dedupeCacheTimeMS: options.dedupeCacheTimeMS
28
+ });
29
+ }
30
+ }
31
+ catch (error) {
32
+ console.error('[mqRSSAddTrendingPodcastsFromPodcastIndex] Error adding trending podcasts:', error);
33
+ throw error;
34
+ }
35
+ });
36
+ exports.mqRSSAddTrendingPodcastsFromPodcastIndex = mqRSSAddTrendingPodcastsFromPodcastIndex;
@@ -0,0 +1,3 @@
1
+ import { MQQueueName, ActiveMQArtemisService } from "@queue/services/activeMQArtemis";
2
+ export declare const mqRSSRunParser: (activeMQArtemisService: ActiveMQArtemisService, queueName: MQQueueName) => Promise<void>;
3
+ //# sourceMappingURL=runParser.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"runParser.d.ts","sourceRoot":"","sources":["../../../../src/functions/queue/rss/runParser.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,WAAW,EAAE,sBAAsB,EAAE,MAAM,iCAAiC,CAAC;AAEtF,eAAO,MAAM,cAAc,GACzB,wBAAwB,sBAAsB,EAC9C,WAAW,WAAW,kBAmBvB,CAAC"}
@@ -0,0 +1,33 @@
1
+ "use strict";
2
+ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
3
+ function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
4
+ return new (P || (P = Promise))(function (resolve, reject) {
5
+ function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
6
+ function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
7
+ function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
8
+ step((generator = generator.apply(thisArg, _arguments || [])).next());
9
+ });
10
+ };
11
+ Object.defineProperty(exports, "__esModule", { value: true });
12
+ exports.mqRSSRunParser = void 0;
13
+ const podverse_parser_1 = require("podverse-parser");
14
+ const mqRSSRunParser = (activeMQArtemisService, queueName) => __awaiter(void 0, void 0, void 0, function* () {
15
+ yield activeMQArtemisService.initialize();
16
+ yield activeMQArtemisService.consumeMessages(queueName, (message) => __awaiter(void 0, void 0, void 0, function* () {
17
+ try {
18
+ const receivedMessageString = message.content.toString();
19
+ const receivedMessage = JSON.parse(receivedMessageString);
20
+ const { url, podcast_index_id } = receivedMessage;
21
+ if (url || podcast_index_id) {
22
+ yield (0, podverse_parser_1.parseRSSFeedAndSaveToDatabase)(url, podcast_index_id);
23
+ }
24
+ else {
25
+ throw new Error(`mqRSSRunParser: url or podcast_index_id not found in message ${receivedMessage === null || receivedMessage === void 0 ? void 0 : receivedMessage.toString()}`);
26
+ }
27
+ }
28
+ catch (error) {
29
+ console.error('Error processing message', error);
30
+ }
31
+ }));
32
+ });
33
+ exports.mqRSSRunParser = mqRSSRunParser;
@@ -0,0 +1,6 @@
1
+ import './module-alias-config';
2
+ export { mqRSSAdd } from './functions/queue/rss/add';
3
+ export { mqRSSAddAll } from './functions/queue/rss/addAll';
4
+ export { mqRSSRunParser } from './functions/queue/rss/runParser';
5
+ export { ActiveMQArtemisService, ActiveMQArtemisServiceParams } from './services/activeMQArtemis';
6
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,uBAAuB,CAAC;AAE/B,OAAO,EAAE,QAAQ,EAAE,MAAM,2BAA2B,CAAC;AACrD,OAAO,EAAE,WAAW,EAAE,MAAM,8BAA8B,CAAC;AAC3D,OAAO,EAAE,cAAc,EAAE,MAAM,iCAAiC,CAAC;AAEjE,OAAO,EAAE,sBAAsB,EAAE,4BAA4B,EAAE,MAAM,4BAA4B,CAAC"}
package/dist/index.js ADDED
@@ -0,0 +1,12 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.ActiveMQArtemisService = exports.mqRSSRunParser = exports.mqRSSAddAll = exports.mqRSSAdd = void 0;
4
+ require("./module-alias-config");
5
+ var add_1 = require("./functions/queue/rss/add");
6
+ Object.defineProperty(exports, "mqRSSAdd", { enumerable: true, get: function () { return add_1.mqRSSAdd; } });
7
+ var addAll_1 = require("./functions/queue/rss/addAll");
8
+ Object.defineProperty(exports, "mqRSSAddAll", { enumerable: true, get: function () { return addAll_1.mqRSSAddAll; } });
9
+ var runParser_1 = require("./functions/queue/rss/runParser");
10
+ Object.defineProperty(exports, "mqRSSRunParser", { enumerable: true, get: function () { return runParser_1.mqRSSRunParser; } });
11
+ var activeMQArtemis_1 = require("./services/activeMQArtemis");
12
+ Object.defineProperty(exports, "ActiveMQArtemisService", { enumerable: true, get: function () { return activeMQArtemis_1.ActiveMQArtemisService; } });
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=module-alias-config.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"module-alias-config.d.ts","sourceRoot":"","sources":["../src/module-alias-config.ts"],"names":[],"mappings":"AAOA,OAAO,EAAE,CAAC"}
@@ -0,0 +1,7 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ const moduleAlias = require('module-alias');
4
+ const path = require('path');
5
+ moduleAlias.addAliases({
6
+ '@queue': path.join(__dirname, '')
7
+ });
@@ -0,0 +1,44 @@
1
+ import { Delivery } from 'rhea';
2
+ import { LoggerService } from 'podverse-helpers/dist/lib/backend/logger';
3
+ export type MQQueueName = 'rss-normal' | 'rss-on-demand' | 'rss-live';
4
+ type MQRSSMessage = {
5
+ url: string;
6
+ podcast_index_id: number | null;
7
+ };
8
+ type Message = MQRSSMessage;
9
+ type SendMessageParams = {
10
+ queueName: MQQueueName;
11
+ message: Message;
12
+ priority: 'normal' | 'slow';
13
+ dedupeCacheTimeMS: number | null;
14
+ };
15
+ export interface ActiveMQArtemisServiceParams {
16
+ protocol: string;
17
+ host: string;
18
+ username: string;
19
+ password: string;
20
+ port: number;
21
+ }
22
+ export declare class ActiveMQArtemisService {
23
+ private connection;
24
+ private senders;
25
+ private receivers;
26
+ private params;
27
+ private logger;
28
+ private connecting;
29
+ constructor(params: ActiveMQArtemisServiceParams, logger: LoggerService);
30
+ initialize(): Promise<void>;
31
+ private connect;
32
+ private ensureSender;
33
+ private ensureReceiver;
34
+ private computeDuplicateId;
35
+ sendMessage(params: SendMessageParams): Promise<void>;
36
+ getMessage(queueName: MQQueueName): Promise<Message | null>;
37
+ consumeMessages(queueName: MQQueueName, processMessage: (msg: {
38
+ content: Buffer;
39
+ raw: Delivery;
40
+ queue: MQQueueName;
41
+ }) => Promise<void> | void): Promise<void>;
42
+ }
43
+ export {};
44
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/services/activeMQArtemis/index.ts"],"names":[],"mappings":"AACA,OAAO,EAA8C,QAAQ,EAAE,MAAM,MAAM,CAAC;AAC5E,OAAO,EAAE,aAAa,EAAE,MAAM,0CAA0C,CAAC;AAIzE,MAAM,MAAM,WAAW,GAAG,YAAY,GAAI,eAAe,GAAG,UAAU,CAAC;AAEvE,KAAK,YAAY,GAAG;IAClB,GAAG,EAAE,MAAM,CAAC;IACZ,gBAAgB,EAAE,MAAM,GAAG,IAAI,CAAC;CACjC,CAAC;AAEF,KAAK,OAAO,GAAG,YAAY,CAAC;AAE5B,KAAK,iBAAiB,GAAG;IACvB,SAAS,EAAE,WAAW,CAAA;IACtB,OAAO,EAAE,OAAO,CAAA;IAChB,QAAQ,EAAE,QAAQ,GAAG,MAAM,CAAA;IAC3B,iBAAiB,EAAE,MAAM,GAAG,IAAI,CAAA;CACjC,CAAA;AAED,MAAM,WAAW,4BAA4B;IAC3C,QAAQ,EAAE,MAAM,CAAC;IACjB,IAAI,EAAE,MAAM,CAAC;IACb,QAAQ,EAAE,MAAM,CAAC;IACjB,QAAQ,EAAE,MAAM,CAAC;IACjB,IAAI,EAAE,MAAM,CAAC;CACd;AAED,qBAAa,sBAAsB;IACjC,OAAO,CAAC,UAAU,CAA2B;IAC7C,OAAO,CAAC,OAAO,CAAuC;IACtD,OAAO,CAAC,SAAS,CAAyC;IAC1D,OAAO,CAAC,MAAM,CAA+B;IAC7C,OAAO,CAAC,MAAM,CAAgB;IAC9B,OAAO,CAAC,UAAU,CAAS;gBAEf,MAAM,EAAE,4BAA4B,EAAE,MAAM,EAAE,aAAa;IAKjE,UAAU;YASF,OAAO;YAwDP,YAAY;YAaZ,cAAc;IAa5B,OAAO,CAAC,kBAAkB;IAQpB,WAAW,CAAC,MAAM,EAAE,iBAAiB,GAAG,OAAO,CAAC,IAAI,CAAC;IAyCrD,UAAU,CAAC,SAAS,EAAE,WAAW,GAAG,OAAO,CAAC,OAAO,GAAG,IAAI,CAAC;IA8B3D,eAAe,CAAC,SAAS,EAAE,WAAW,EAAE,cAAc,EAAE,CAAC,GAAG,EAAE;QAAE,OAAO,EAAE,MAAM,CAAC;QAAC,GAAG,EAAE,QAAQ,CAAC;QAAC,KAAK,EAAE,WAAW,CAAA;KAAE,KAAK,OAAO,CAAC,IAAI,CAAC,GAAG,IAAI;CA2BpJ"}
@@ -0,0 +1,230 @@
1
+ "use strict";
2
+ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
3
+ function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
4
+ return new (P || (P = Promise))(function (resolve, reject) {
5
+ function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
6
+ function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
7
+ function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
8
+ step((generator = generator.apply(thisArg, _arguments || [])).next());
9
+ });
10
+ };
11
+ var __importDefault = (this && this.__importDefault) || function (mod) {
12
+ return (mod && mod.__esModule) ? mod : { "default": mod };
13
+ };
14
+ Object.defineProperty(exports, "__esModule", { value: true });
15
+ exports.ActiveMQArtemisService = void 0;
16
+ const rhea_1 = __importDefault(require("rhea"));
17
+ const crypto_1 = __importDefault(require("crypto"));
18
+ class ActiveMQArtemisService {
19
+ constructor(params, logger) {
20
+ this.connection = null;
21
+ this.senders = new Map();
22
+ this.receivers = new Map();
23
+ this.connecting = false;
24
+ this.params = params;
25
+ this.logger = logger;
26
+ }
27
+ initialize() {
28
+ return __awaiter(this, void 0, void 0, function* () {
29
+ // Queues are assumed to be pre-created externally (e.g. via provisioning script or broker config).
30
+ try {
31
+ yield this.connect();
32
+ }
33
+ catch (error) {
34
+ this.logger.logError('Failed to initialize Artemis connection', error);
35
+ }
36
+ });
37
+ }
38
+ connect() {
39
+ return __awaiter(this, void 0, void 0, function* () {
40
+ if (this.connection || this.connecting)
41
+ return;
42
+ this.connecting = true;
43
+ return new Promise((resolve, reject) => {
44
+ // Debug info about imported rhea module
45
+ try {
46
+ const rheaLike = rhea_1.default;
47
+ // Log a minimal snapshot of the rhea import for troubleshooting
48
+ if (typeof rheaLike.connect !== 'function') {
49
+ const err = new TypeError('rhea.connect is not a function – possible ESM/CJS import mismatch');
50
+ this.logger.logError('Artemis connect failed early', err);
51
+ this.connecting = false; // allow retry attempts later
52
+ return reject(err);
53
+ }
54
+ const connection = rheaLike.connect({
55
+ host: this.params.host,
56
+ port: this.params.port,
57
+ username: this.params.username,
58
+ password: this.params.password,
59
+ reconnect: true,
60
+ reconnect_limit: -1
61
+ });
62
+ connection.on('connection_open', () => {
63
+ this.logger.info('Artemis AMQP connection established');
64
+ this.connection = connection;
65
+ this.connecting = false;
66
+ resolve();
67
+ });
68
+ connection.on('connection_error', (context) => {
69
+ this.logger.logError('Artemis connection error', context.error);
70
+ });
71
+ connection.on('disconnected', () => {
72
+ this.logger.info('Artemis connection disconnected – will attempt reconnect');
73
+ this.connection = null;
74
+ });
75
+ }
76
+ catch (err) {
77
+ this.logger.logError('Artemis connect threw synchronously', err);
78
+ this.connecting = false; // reset so future retries can occur
79
+ reject(err);
80
+ }
81
+ });
82
+ });
83
+ }
84
+ ensureSender(queueName) {
85
+ return __awaiter(this, void 0, void 0, function* () {
86
+ if (this.senders.has(queueName))
87
+ return this.senders.get(queueName);
88
+ if (!this.connection)
89
+ yield this.connect();
90
+ const sender = this.connection.open_sender({ target: { address: queueName } });
91
+ return new Promise((resolve) => {
92
+ sender.on('sender_open', () => {
93
+ this.logger.info(`Sender ready for queue ${queueName}`);
94
+ this.senders.set(queueName, sender);
95
+ resolve(sender);
96
+ });
97
+ });
98
+ });
99
+ }
100
+ ensureReceiver(queueName) {
101
+ return __awaiter(this, void 0, void 0, function* () {
102
+ if (this.receivers.has(queueName))
103
+ return this.receivers.get(queueName);
104
+ if (!this.connection)
105
+ yield this.connect();
106
+ const receiver = this.connection.open_receiver({ source: { address: queueName }, credit_window: 0 });
107
+ return new Promise((resolve) => {
108
+ receiver.on('receiver_open', () => {
109
+ this.logger.info(`Receiver ready for queue ${queueName}`);
110
+ this.receivers.set(queueName, receiver);
111
+ resolve(receiver);
112
+ });
113
+ });
114
+ });
115
+ }
116
+ computeDuplicateId(queueName, message, dedupeCacheTimeMS) {
117
+ if (!dedupeCacheTimeMS || dedupeCacheTimeMS <= 0)
118
+ return null;
119
+ const baseHash = crypto_1.default.createHash('sha256').update(JSON.stringify(message)).digest('hex');
120
+ const now = Date.now();
121
+ const bucketStart = Math.floor(now / dedupeCacheTimeMS) * dedupeCacheTimeMS;
122
+ return `${queueName}:${bucketStart}:${baseHash}`;
123
+ }
124
+ sendMessage(params) {
125
+ return __awaiter(this, void 0, void 0, function* () {
126
+ const { queueName, message, priority, dedupeCacheTimeMS } = params;
127
+ try {
128
+ const sender = yield this.ensureSender(queueName);
129
+ const bodyString = JSON.stringify(message);
130
+ const duplicateId = this.computeDuplicateId(queueName, message, dedupeCacheTimeMS);
131
+ const priorityValue = !priority || priority === 'normal' ? 5 : 1;
132
+ yield new Promise((resolve, reject) => {
133
+ const delivery = sender.send(Object.assign({ body: bodyString, durable: true, priority: priorityValue, content_type: 'application/json' }, (duplicateId
134
+ ? { application_properties: { _AMQ_DUPL_ID: duplicateId } }
135
+ : {}) // omit property when no dedupe
136
+ ));
137
+ const onAccepted = (context) => {
138
+ if (context.delivery === delivery) {
139
+ this.logger.info(`Message sent to queue ${queueName}: ${bodyString}`);
140
+ sender.removeListener('accepted', onAccepted);
141
+ sender.removeListener('rejected', onRejected);
142
+ resolve();
143
+ }
144
+ };
145
+ const onRejected = (context) => {
146
+ if (context.delivery === delivery) {
147
+ this.logger.logError(`sendMessage: Rejected by broker ${queueName}: ${bodyString}`);
148
+ sender.removeListener('accepted', onAccepted);
149
+ sender.removeListener('rejected', onRejected);
150
+ reject(new Error('Message rejected'));
151
+ }
152
+ };
153
+ sender.on('accepted', onAccepted);
154
+ sender.on('rejected', onRejected);
155
+ });
156
+ }
157
+ catch (error) {
158
+ this.logger.logError(`sendMessage: Error sending message to queue ${queueName}`, error);
159
+ }
160
+ });
161
+ }
162
+ getMessage(queueName) {
163
+ return __awaiter(this, void 0, void 0, function* () {
164
+ try {
165
+ const receiver = yield this.ensureReceiver(queueName);
166
+ // Request one message (credit 1)
167
+ receiver.add_credit(1);
168
+ return yield new Promise((resolve) => {
169
+ const onMessage = (context) => {
170
+ var _a, _b;
171
+ if (context.receiver === receiver) {
172
+ const body = (_a = context.message) === null || _a === void 0 ? void 0 : _a.body;
173
+ const parsed = JSON.parse(body);
174
+ this.logger.info(`Message received from queue ${queueName}: ${body}`);
175
+ (_b = context.delivery) === null || _b === void 0 ? void 0 : _b.accept();
176
+ receiver.removeListener('message', onMessage);
177
+ resolve(parsed);
178
+ }
179
+ };
180
+ const onNoMessageTimeout = () => {
181
+ receiver.removeListener('message', onMessage);
182
+ resolve(null);
183
+ };
184
+ receiver.on('message', onMessage);
185
+ // Timeout after 1 second if none
186
+ setTimeout(onNoMessageTimeout, 1000);
187
+ });
188
+ }
189
+ catch (error) {
190
+ this.logger.logError('getMessage: Error receiving message', error);
191
+ return null;
192
+ }
193
+ });
194
+ }
195
+ consumeMessages(queueName, processMessage) {
196
+ return __awaiter(this, void 0, void 0, function* () {
197
+ try {
198
+ const receiver = yield this.ensureReceiver(queueName);
199
+ const handleMessage = (context) => __awaiter(this, void 0, void 0, function* () {
200
+ var _a, _b;
201
+ if (context.receiver !== receiver)
202
+ return;
203
+ try {
204
+ const body = (_a = context.message) === null || _a === void 0 ? void 0 : _a.body;
205
+ this.logger.info(`Received message from queue ${queueName}: ${body}`);
206
+ const delivery = context.delivery;
207
+ const buffer = Buffer.from(body);
208
+ yield processMessage({ content: buffer, raw: delivery, queue: queueName });
209
+ delivery.accept();
210
+ }
211
+ catch (err) {
212
+ this.logger.logError('Error processing message', err);
213
+ (_b = context.delivery) === null || _b === void 0 ? void 0 : _b.reject();
214
+ }
215
+ finally {
216
+ // Request next message (one at a time for FIFO semantics)
217
+ receiver.add_credit(1);
218
+ }
219
+ });
220
+ receiver.on('message', handleMessage);
221
+ receiver.add_credit(1); // Start consumption
222
+ this.logger.info(`Consumer is set up for queue ${queueName}`);
223
+ }
224
+ catch (error) {
225
+ this.logger.logError('consumeMessages: Failed to set consumer', error);
226
+ }
227
+ });
228
+ }
229
+ }
230
+ exports.ActiveMQArtemisService = ActiveMQArtemisService;
@@ -0,0 +1,11 @@
1
+ import { ActiveMQArtemisServiceParams } from '.';
2
+ export declare class ActiveMQArtemisRequestService {
3
+ private protocol;
4
+ private host;
5
+ private username;
6
+ private password;
7
+ private port;
8
+ constructor({ protocol, host, username, password, port }: ActiveMQArtemisServiceParams);
9
+ request<T>(path: string): Promise<T>;
10
+ }
11
+ //# sourceMappingURL=requestService.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"requestService.d.ts","sourceRoot":"","sources":["../../../src/services/activeMQArtemis/requestService.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,4BAA4B,EAAE,MAAM,GAAG,CAAC;AAEjD,qBAAa,6BAA6B;IACxC,OAAO,CAAC,QAAQ,CAAS;IACzB,OAAO,CAAC,IAAI,CAAS;IACrB,OAAO,CAAC,QAAQ,CAAS;IACzB,OAAO,CAAC,QAAQ,CAAS;IACzB,OAAO,CAAC,IAAI,CAAS;gBAET,EAAE,QAAQ,EAAE,IAAI,EAAE,QAAQ,EAAE,QAAQ,EAAE,IAAI,EAAE,EAAE,4BAA4B;IAQhF,OAAO,CAAC,CAAC,EAAE,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,CAAC,CAAC;CAmB3C"}