@mulingai-npm/message-broker 2.9.2 → 2.9.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.
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import { RabbitMQClient } from '../rabbitmq-client';
|
|
2
|
+
import { IMulingstreamUsageLimitEvent } from '@mulingai-npm/web-sockets';
|
|
3
|
+
/**
|
|
4
|
+
* RabbitMQ manager for usage limit events (TRIAL_ENDED, USAGE_LIMIT_REACHED).
|
|
5
|
+
*
|
|
6
|
+
* Flow:
|
|
7
|
+
* - Pipeline-service publishes events when limits are exceeded
|
|
8
|
+
* - Speaker-realtime-service subscribes and emits to WebSocket
|
|
9
|
+
* - Frontend receives and stops recording, shows appropriate UI
|
|
10
|
+
*
|
|
11
|
+
* See: docs/plans/USAGE_METRICS.md
|
|
12
|
+
*/
|
|
13
|
+
export declare class MulingstreamUsageEvents {
|
|
14
|
+
private client;
|
|
15
|
+
constructor(client: RabbitMQClient);
|
|
16
|
+
/**
|
|
17
|
+
* Initialize the exchange (call once at service startup)
|
|
18
|
+
*/
|
|
19
|
+
initialize(): Promise<void>;
|
|
20
|
+
/**
|
|
21
|
+
* Publish a usage limit event.
|
|
22
|
+
* Called by pipeline-service when trial or plan limits are exceeded.
|
|
23
|
+
*/
|
|
24
|
+
publish(data: IMulingstreamUsageLimitEvent): Promise<void>;
|
|
25
|
+
/**
|
|
26
|
+
* Subscribe to usage limit events.
|
|
27
|
+
* Called by speaker-realtime-service to receive and emit to WebSocket.
|
|
28
|
+
*
|
|
29
|
+
* @param queueName - Unique queue name per instance (e.g., `speaker-usage-events-{instanceId}`)
|
|
30
|
+
* @param onMessage - Callback to handle received events
|
|
31
|
+
* @param exclusive - If true, queue is deleted when connection closes (default: true)
|
|
32
|
+
*/
|
|
33
|
+
subscribe(queueName: string, onMessage: (data: IMulingstreamUsageLimitEvent) => Promise<void> | void, exclusive?: boolean): Promise<void>;
|
|
34
|
+
}
|
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.MulingstreamUsageEvents = void 0;
|
|
4
|
+
const EXCHANGE_NAME = 'mulingstream.usage.events';
|
|
5
|
+
const EXCHANGE_TYPE = 'fanout';
|
|
6
|
+
/**
|
|
7
|
+
* RabbitMQ manager for usage limit events (TRIAL_ENDED, USAGE_LIMIT_REACHED).
|
|
8
|
+
*
|
|
9
|
+
* Flow:
|
|
10
|
+
* - Pipeline-service publishes events when limits are exceeded
|
|
11
|
+
* - Speaker-realtime-service subscribes and emits to WebSocket
|
|
12
|
+
* - Frontend receives and stops recording, shows appropriate UI
|
|
13
|
+
*
|
|
14
|
+
* See: docs/plans/USAGE_METRICS.md
|
|
15
|
+
*/
|
|
16
|
+
class MulingstreamUsageEvents {
|
|
17
|
+
constructor(client) {
|
|
18
|
+
this.client = client;
|
|
19
|
+
}
|
|
20
|
+
/**
|
|
21
|
+
* Initialize the exchange (call once at service startup)
|
|
22
|
+
*/
|
|
23
|
+
async initialize() {
|
|
24
|
+
const channel = this.client.getChannelOrThrow();
|
|
25
|
+
await channel.assertExchange(EXCHANGE_NAME, EXCHANGE_TYPE, {
|
|
26
|
+
durable: true
|
|
27
|
+
});
|
|
28
|
+
console.log(`MulingstreamUsageEvents exchange '${EXCHANGE_NAME}' asserted.`);
|
|
29
|
+
}
|
|
30
|
+
/**
|
|
31
|
+
* Publish a usage limit event.
|
|
32
|
+
* Called by pipeline-service when trial or plan limits are exceeded.
|
|
33
|
+
*/
|
|
34
|
+
async publish(data) {
|
|
35
|
+
const channel = this.client.getChannelOrThrow();
|
|
36
|
+
const payload = Buffer.from(JSON.stringify(data));
|
|
37
|
+
channel.publish(EXCHANGE_NAME, '', payload);
|
|
38
|
+
console.log(`[UsageEvents] Published ${data.event} for user ${data.userId} in room ${data.roomId}`);
|
|
39
|
+
}
|
|
40
|
+
/**
|
|
41
|
+
* Subscribe to usage limit events.
|
|
42
|
+
* Called by speaker-realtime-service to receive and emit to WebSocket.
|
|
43
|
+
*
|
|
44
|
+
* @param queueName - Unique queue name per instance (e.g., `speaker-usage-events-{instanceId}`)
|
|
45
|
+
* @param onMessage - Callback to handle received events
|
|
46
|
+
* @param exclusive - If true, queue is deleted when connection closes (default: true)
|
|
47
|
+
*/
|
|
48
|
+
async subscribe(queueName, onMessage, exclusive = true) {
|
|
49
|
+
const channel = this.client.getChannelOrThrow();
|
|
50
|
+
// Use exclusive queue that auto-deletes when connection closes
|
|
51
|
+
await channel.assertQueue(queueName, {
|
|
52
|
+
durable: false,
|
|
53
|
+
exclusive: exclusive,
|
|
54
|
+
autoDelete: true
|
|
55
|
+
});
|
|
56
|
+
await channel.bindQueue(queueName, EXCHANGE_NAME, '');
|
|
57
|
+
await channel.consume(queueName, async (msg) => {
|
|
58
|
+
if (!msg) {
|
|
59
|
+
return;
|
|
60
|
+
}
|
|
61
|
+
try {
|
|
62
|
+
const data = JSON.parse(msg.content.toString());
|
|
63
|
+
await onMessage(data);
|
|
64
|
+
channel.ack(msg);
|
|
65
|
+
}
|
|
66
|
+
catch (error) {
|
|
67
|
+
console.error(`Error in MulingstreamUsageEvents subscription queue ${queueName}:`, error);
|
|
68
|
+
channel.nack(msg, false, false); // Don't requeue failed messages
|
|
69
|
+
}
|
|
70
|
+
});
|
|
71
|
+
console.log(`[UsageEvents] Subscribed to queue '${queueName}'`);
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
exports.MulingstreamUsageEvents = MulingstreamUsageEvents;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@mulingai-npm/message-broker",
|
|
3
|
-
"version": "2.9.
|
|
3
|
+
"version": "2.9.4",
|
|
4
4
|
"main": "dist/index.js",
|
|
5
5
|
"types": "dist/index.d.ts",
|
|
6
6
|
"repository": {
|
|
@@ -17,7 +17,7 @@
|
|
|
17
17
|
"prepublishOnly": "npm run build"
|
|
18
18
|
},
|
|
19
19
|
"dependencies": {
|
|
20
|
-
"@mulingai-npm/web-sockets": "^1.44.
|
|
20
|
+
"@mulingai-npm/web-sockets": "^1.44.3",
|
|
21
21
|
"amqplib": "^0.10.5"
|
|
22
22
|
},
|
|
23
23
|
"devDependencies": {
|