UNPKG

@awesomeniko/kafka-trail

Version:

A Node.js library for managing message queue with Kafka

95 lines 3.41 kB
import Kafka, { CompressionTypes } from "kafkajs"; import { UnableDecreasePartitionsError } from "../custom-errors/kafka-errors.js"; import { CustomPartitioner } from "./custom-partitioner.js"; import { KTKafkaBroker } from "./kafka-broker.js"; class KTKafkaProducer extends KTKafkaBroker { #producer; #admin; #logger; constructor(params) { super(params); const { createPartitioner, logger } = params; let customPartitioner = createPartitioner; if (!customPartitioner) { customPartitioner = CustomPartitioner.roundRobin; } this.#producer = this._kafka.producer({ createPartitioner: customPartitioner, allowAutoTopicCreation: false, }); this.#admin = this._kafka.admin(); this.#logger = logger; } init() { return Promise.all([this.#admin.connect(), this.#producer.connect()]); } destroy() { return Promise.all([this.#admin.disconnect(), this.#producer.disconnect()]); } async createTopic(topicName, partitions = 1, customConfigArray = []) { this.#logger.info({ topicName, partitions, customConfigArray, }, "Resolving topics..."); try { const topicMetadata = await this.#admin.fetchTopicMetadata({ topics: [topicName] }); const currentTopic = topicMetadata.topics.find((topicMetadata) => topicMetadata.name === topicName); if (!currentTopic) { throw new Kafka.KafkaJSProtocolError('Topic not found'); } if (partitions === currentTopic.partitions.length) { return; } if (partitions > currentTopic.partitions.length) { await this.#admin.createPartitions({ topicPartitions: [ { topic: topicName, count: partitions, }, ], }); this.#logger.info(`Expanded partitions for ${topicName} topic`); } else { throw new UnableDecreasePartitionsError(); } this.#logger.info("Topics resolved successful"); } catch (e) { if (e instanceof Kafka.KafkaJSProtocolError) { await this.#admin.createTopics({ topics: [ { topic: topicName, numPartitions: partitions, configEntries: customConfigArray, }, ], waitForLeaders: true, }); } else { this.#logger.error(e, "Error from createTopic"); throw e; } } } async sendSingleMessage(params, headers = {}) { const { topicName, messageKey, message } = params; await this.#producer.send({ topic: topicName, compression: CompressionTypes.LZ4, messages: [ { key: messageKey ?? null, value: message, headers, }, ], }); } } export { KTKafkaProducer }; //# sourceMappingURL=kafka-producer.js.map