broker-lib
Version:
Multi-Broker Message Bus with Multi-Topic Support
128 lines • 4.95 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", { value: true });
exports.GCPPubSubBroker = void 0;
const pubsub_1 = require("@google-cloud/pubsub");
const events_1 = require("events");
class GCPPubSubBroker extends events_1.EventEmitter {
constructor(config) {
super();
this.subscriptions = new Map();
this.connected = false;
const pubsubConfig = {
projectId: config.projectId,
};
if (config.keyFilename) {
pubsubConfig.keyFilename = config.keyFilename;
}
if (config.credentials) {
pubsubConfig.credentials = config.credentials;
}
if (config.apiEndpoint) {
pubsubConfig.apiEndpoint = config.apiEndpoint;
}
this.pubsub = new pubsub_1.PubSub(pubsubConfig);
this.connected = true;
this.emit('connect');
}
async connect() {
try {
// GCP PubSub doesn't require explicit connection
// The client is ready to use after instantiation
this.connected = true;
this.emit('connect');
}
catch (error) {
this.connected = false;
this.emit('error', error);
throw new Error(`Failed to connect to GCP PubSub: ${error instanceof Error ? error.message : String(error)}`);
}
}
async publish(topic, message, options) {
try {
const topicRef = this.pubsub.topic(topic);
// Check if topic exists, create if it doesn't
const [exists] = await topicRef.exists();
if (!exists) {
await topicRef.create();
}
const messageBuffer = typeof message === 'string' ? Buffer.from(message) : message;
const messageData = {
data: messageBuffer,
};
if (options?.key) {
messageData.key = options.key;
}
if (options?.headers) {
messageData.attributes = options.headers;
}
await topicRef.publishMessage(messageData);
}
catch (error) {
throw new Error(`Failed to publish message to topic ${topic}: ${error instanceof Error ? error.message : String(error)}`);
}
}
async subscribe(topics, handler, options) {
try {
for (const topicName of topics) {
const subscriptionName = `${topicName}-sub-${Date.now()}`;
const topicRef = this.pubsub.topic(topicName);
// Check if topic exists, create if it doesn't
const [topicExists] = await topicRef.exists();
if (!topicExists) {
await topicRef.create();
}
// Check if subscription exists
const [subscriptions] = await this.pubsub.subscription(subscriptionName).exists();
let subscription;
if (subscriptions) {
subscription = this.pubsub.subscription(subscriptionName);
}
else {
[subscription] = await topicRef.createSubscription(subscriptionName);
}
this.subscriptions.set(topicName, subscription);
subscription.on('message', async (message) => {
try {
await handler(topicName, message.data);
if (options?.autoAck !== false) {
message.ack();
}
}
catch (error) {
console.error(`Error handling message from topic ${topicName}:`, error);
if (options?.autoAck !== false) {
message.nack();
}
}
});
subscription.on('error', (error) => {
console.error(`Subscription error for topic ${topicName}:`, error);
});
}
}
catch (error) {
throw new Error(`Failed to subscribe to topics ${topics.join(', ')}: ${error instanceof Error ? error.message : String(error)}`);
}
}
async disconnect() {
try {
// Close all subscriptions
for (const [, subscription] of this.subscriptions) {
subscription.removeAllListeners();
await subscription.close();
}
this.subscriptions.clear();
this.connected = false;
this.emit('disconnect');
}
catch (error) {
this.emit('error', error);
throw new Error(`Failed to disconnect: ${error instanceof Error ? error.message : String(error)}`);
}
}
isConnected() {
return this.connected;
}
}
exports.GCPPubSubBroker = GCPPubSubBroker;
//# sourceMappingURL=gcpPubSub.js.map