UNPKG

@syntropylog/adapters

Version:
80 lines 3.39 kB
import { PayloadSerializer } from '../utils/PayloadSerializer'; /** * Helper function to normalize Kafka's complex IHeaders object into * the simple Record<string, string | Buffer> that our framework expects. * @param headers The headers object from a Kafka message. * @returns A normalized headers object. */ function normalizeKafkaHeaders(headers) { if (!headers) { return undefined; } const normalized = {}; for (const key in headers) { if (Object.prototype.hasOwnProperty.call(headers, key)) { const value = headers[key]; // We only accept string or Buffer, and we discard undefined or arrays for simplicity. if (typeof value === 'string' || Buffer.isBuffer(value)) { normalized[key] = value; } } } return normalized; } export class KafkaAdapter { // The constructor now receives the Kafka instance already created. // This makes it more flexible and easier to test. constructor(kafkaInstance, groupId) { this.producer = kafkaInstance.producer(); this.consumer = kafkaInstance.consumer({ groupId }); } async connect() { await this.producer.connect(); await this.consumer.connect(); } async disconnect() { await this.producer.disconnect(); await this.consumer.disconnect(); } async publish(topic, message) { const serializedPayload = PayloadSerializer.serializeForBroker(message); await this.producer.send({ topic, messages: [{ value: serializedPayload, headers: message.headers }], }); } async subscribe(topic, handler) { await this.consumer.subscribe({ topic, fromBeginning: true }); await this.consumer.run({ eachMessage: async ({ topic, partition, message }) => { try { const brokerMessage = PayloadSerializer.createBrokerMessage(message.value, normalizeKafkaHeaders(message.headers)); const controls = { ack: async () => { await this.consumer.commitOffsets([ { topic, partition, offset: (Number(message.offset) + 1).toString(), }, ]); }, nack: async () => { // Nacking in Kafka is complex. For now, we just log. // A real implementation might move the message to a dead-letter queue. console.log(`NACK received for message on topic ${topic}.`); }, }; await handler(brokerMessage, controls); } catch (err) { // If there's an error (e.g., JSON parsing), we can't process the message, // but we don't want to crash the whole service. We'll log it. // A more robust implementation might publish to a dead-letter queue. console.error(`Failed to process message from topic ${topic}`, err); } }, }); } } //# sourceMappingURL=KafkaAdapter.js.map