@platformatic/kafka
Version:
Modern and performant client for Apache Kafka
89 lines (88 loc) • 3.45 kB
JavaScript
import { ResponseError } from "../../errors.js";
import { createRecordsBatch } from "../../protocol/records.js";
import { Writer } from "../../protocol/writer.js";
import { groupByProperty } from "../../utils.js";
import { createAPI } from "../definitions.js";
import { ProduceAcks } from "../enumerations.js";
/*
Produce Request (Version: 7) => transactional_id acks timeout_ms [topic_data]
transactional_id => NULLABLE_STRING
acks => INT16
timeout_ms => INT32
topic_data => name [partition_data]
name => STRING
partition_data => index records
index => INT32
records => RECORDS
*/
export function createRequest(acks = 1, timeout = 0, topicData, options = {}) {
// Normalize the messages
const now = BigInt(Date.now());
for (const message of topicData) {
if (typeof message.partition === 'undefined') {
message.partition = 0;
}
if (typeof message.timestamp === 'undefined') {
message.timestamp = now;
}
}
const writer = Writer.create()
.appendString(options.transactionalId, false)
.appendInt16(acks)
.appendInt32(timeout)
.appendArray(groupByProperty(topicData, 'topic'), (w, [topic, messages]) => {
w.appendString(topic, false).appendArray(groupByProperty(messages, 'partition'), (w, [partition, messages]) => {
const records = createRecordsBatch(messages, options);
w.appendInt32(partition).appendInt32(records.length).appendFrom(records);
}, false, false);
}, false, false);
if (acks === ProduceAcks.NO_RESPONSE) {
writer.context.noResponse = true;
}
return writer;
}
/*
Produce Response (Version: 7) => [responses] throttle_time_ms
responses => name [partition_responses]
name => STRING
partition_responses => index error_code base_offset log_append_time_ms log_start_offset [record_errors] error_message
index => INT32
error_code => INT16
base_offset => INT64
log_append_time_ms => INT64
log_start_offset => INT64
throttle_time_ms => INT32
*/
export function parseResponse(_correlationId, apiKey, apiVersion, reader) {
const errors = [];
const response = {
responses: reader.readArray((r, i) => {
const topicResponse = {
name: r.readString(false),
partitionResponses: r.readArray((r, j) => {
const index = r.readInt32();
const errorCode = r.readInt16();
if (errorCode !== 0) {
errors.push([`/responses/${i}/partition_responses/${j}`, errorCode]);
}
return {
index,
errorCode,
baseOffset: r.readInt64(),
logAppendTimeMs: r.readInt64(),
logStartOffset: r.readInt64(),
recordErrors: [],
errorMessage: null
};
}, false, false)
};
return topicResponse;
}, false, false),
throttleTimeMs: reader.readInt32()
};
if (errors.length) {
throw new ResponseError(apiKey, apiVersion, Object.fromEntries(errors), response);
}
return response;
}
export const api = createAPI(0, 7, createRequest, parseResponse, false, false);