@platformatic/kafka 0.1.0
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.
- package/LICENSE +201 -0
- package/README.md +270 -0
- package/dist/apis/admin/alter-client-quotas.d.ts +33 -0
- package/dist/apis/admin/alter-client-quotas.js +64 -0
- package/dist/apis/admin/alter-configs.d.ts +26 -0
- package/dist/apis/admin/alter-configs.js +57 -0
- package/dist/apis/admin/alter-partition-reassignments.d.ts +30 -0
- package/dist/apis/admin/alter-partition-reassignments.js +68 -0
- package/dist/apis/admin/alter-partition.d.ts +39 -0
- package/dist/apis/admin/alter-partition.js +87 -0
- package/dist/apis/admin/alter-replica-log-dirs.d.ts +26 -0
- package/dist/apis/admin/alter-replica-log-dirs.js +55 -0
- package/dist/apis/admin/alter-user-scram-credentials.d.ts +27 -0
- package/dist/apis/admin/alter-user-scram-credentials.js +60 -0
- package/dist/apis/admin/consumer-group-describe.d.ts +41 -0
- package/dist/apis/admin/consumer-group-describe.js +103 -0
- package/dist/apis/admin/create-acls.d.ts +24 -0
- package/dist/apis/admin/create-acls.js +55 -0
- package/dist/apis/admin/create-delegation-token.d.ts +24 -0
- package/dist/apis/admin/create-delegation-token.js +54 -0
- package/dist/apis/admin/create-partitions.d.ts +24 -0
- package/dist/apis/admin/create-partitions.js +54 -0
- package/dist/apis/admin/create-topics.d.ts +42 -0
- package/dist/apis/admin/create-topics.js +86 -0
- package/dist/apis/admin/delete-acls.d.ts +36 -0
- package/dist/apis/admin/delete-acls.js +82 -0
- package/dist/apis/admin/delete-groups.d.ts +14 -0
- package/dist/apis/admin/delete-groups.js +40 -0
- package/dist/apis/admin/delete-records.d.ts +27 -0
- package/dist/apis/admin/delete-records.js +59 -0
- package/dist/apis/admin/delete-topics.d.ts +21 -0
- package/dist/apis/admin/delete-topics.js +50 -0
- package/dist/apis/admin/describe-acls.d.ts +25 -0
- package/dist/apis/admin/describe-acls.js +66 -0
- package/dist/apis/admin/describe-client-quotas.d.ts +30 -0
- package/dist/apis/admin/describe-client-quotas.js +57 -0
- package/dist/apis/admin/describe-cluster.d.ts +23 -0
- package/dist/apis/admin/describe-cluster.js +50 -0
- package/dist/apis/admin/describe-configs.d.ts +38 -0
- package/dist/apis/admin/describe-configs.js +85 -0
- package/dist/apis/admin/describe-delegation-token.d.ts +31 -0
- package/dist/apis/admin/describe-delegation-token.js +62 -0
- package/dist/apis/admin/describe-groups.d.ts +28 -0
- package/dist/apis/admin/describe-groups.js +67 -0
- package/dist/apis/admin/describe-log-dirs.d.ts +32 -0
- package/dist/apis/admin/describe-log-dirs.js +75 -0
- package/dist/apis/admin/describe-producers.d.ts +33 -0
- package/dist/apis/admin/describe-producers.js +70 -0
- package/dist/apis/admin/describe-quorum.d.ts +50 -0
- package/dist/apis/admin/describe-quorum.js +116 -0
- package/dist/apis/admin/describe-topic-partitions.d.ts +42 -0
- package/dist/apis/admin/describe-topic-partitions.js +94 -0
- package/dist/apis/admin/describe-transactions.d.ts +24 -0
- package/dist/apis/admin/describe-transactions.js +59 -0
- package/dist/apis/admin/describe-user-scram-credentials.d.ts +26 -0
- package/dist/apis/admin/describe-user-scram-credentials.js +62 -0
- package/dist/apis/admin/envelope.d.ts +10 -0
- package/dist/apis/admin/envelope.js +32 -0
- package/dist/apis/admin/expire-delegation-token.d.ts +11 -0
- package/dist/apis/admin/expire-delegation-token.js +29 -0
- package/dist/apis/admin/incremental-alter-configs.d.ts +27 -0
- package/dist/apis/admin/incremental-alter-configs.js +58 -0
- package/dist/apis/admin/index.d.ts +37 -0
- package/dist/apis/admin/index.js +37 -0
- package/dist/apis/admin/list-groups.d.ts +18 -0
- package/dist/apis/admin/list-groups.js +43 -0
- package/dist/apis/admin/list-partition-reassignments.d.ts +27 -0
- package/dist/apis/admin/list-partition-reassignments.js +56 -0
- package/dist/apis/admin/list-transactions.d.ts +18 -0
- package/dist/apis/admin/list-transactions.js +45 -0
- package/dist/apis/admin/offset-delete.d.ts +26 -0
- package/dist/apis/admin/offset-delete.js +59 -0
- package/dist/apis/admin/renew-delegation-token.d.ts +11 -0
- package/dist/apis/admin/renew-delegation-token.js +29 -0
- package/dist/apis/admin/unregister-broker.d.ts +12 -0
- package/dist/apis/admin/unregister-broker.js +28 -0
- package/dist/apis/admin/update-features.d.ts +23 -0
- package/dist/apis/admin/update-features.js +60 -0
- package/dist/apis/consumer/consumer-group-heartbeat.d.ts +27 -0
- package/dist/apis/consumer/consumer-group-heartbeat.js +70 -0
- package/dist/apis/consumer/fetch.d.ts +46 -0
- package/dist/apis/consumer/fetch.js +121 -0
- package/dist/apis/consumer/heartbeat.d.ts +11 -0
- package/dist/apis/consumer/heartbeat.js +34 -0
- package/dist/apis/consumer/index.d.ts +9 -0
- package/dist/apis/consumer/index.js +9 -0
- package/dist/apis/consumer/join-group.d.ts +27 -0
- package/dist/apis/consumer/join-group.js +71 -0
- package/dist/apis/consumer/leave-group.d.ts +22 -0
- package/dist/apis/consumer/leave-group.js +57 -0
- package/dist/apis/consumer/list-offsets.d.ts +30 -0
- package/dist/apis/consumer/list-offsets.js +68 -0
- package/dist/apis/consumer/offset-commit.d.ts +29 -0
- package/dist/apis/consumer/offset-commit.js +68 -0
- package/dist/apis/consumer/offset-fetch.d.ts +37 -0
- package/dist/apis/consumer/offset-fetch.js +81 -0
- package/dist/apis/consumer/sync-group.d.ts +18 -0
- package/dist/apis/consumer/sync-group.js +49 -0
- package/dist/apis/definitions.d.ts +16 -0
- package/dist/apis/definitions.js +12 -0
- package/dist/apis/enumerations.d.ts +114 -0
- package/dist/apis/enumerations.js +78 -0
- package/dist/apis/index.d.ts +8 -0
- package/dist/apis/index.js +10 -0
- package/dist/apis/metadata/api-versions.d.ts +17 -0
- package/dist/apis/metadata/api-versions.js +41 -0
- package/dist/apis/metadata/find-coordinator.d.ts +19 -0
- package/dist/apis/metadata/find-coordinator.js +50 -0
- package/dist/apis/metadata/index.d.ts +3 -0
- package/dist/apis/metadata/index.js +3 -0
- package/dist/apis/metadata/metadata.d.ts +37 -0
- package/dist/apis/metadata/metadata.js +92 -0
- package/dist/apis/producer/add-offsets-to-txn.d.ts +10 -0
- package/dist/apis/producer/add-offsets-to-txn.js +34 -0
- package/dist/apis/producer/add-partitions-to-txn.d.ts +34 -0
- package/dist/apis/producer/add-partitions-to-txn.js +79 -0
- package/dist/apis/producer/end-txn.d.ts +10 -0
- package/dist/apis/producer/end-txn.js +34 -0
- package/dist/apis/producer/index.d.ts +6 -0
- package/dist/apis/producer/index.js +6 -0
- package/dist/apis/producer/init-producer-id.d.ts +21 -0
- package/dist/apis/producer/init-producer-id.js +38 -0
- package/dist/apis/producer/produce.d.ts +29 -0
- package/dist/apis/producer/produce.js +104 -0
- package/dist/apis/producer/txn-offset-commit.d.ts +29 -0
- package/dist/apis/producer/txn-offset-commit.js +77 -0
- package/dist/apis/security/index.d.ts +2 -0
- package/dist/apis/security/index.js +2 -0
- package/dist/apis/security/sasl-authenticate.d.ts +15 -0
- package/dist/apis/security/sasl-authenticate.js +30 -0
- package/dist/apis/security/sasl-handshake.d.ts +10 -0
- package/dist/apis/security/sasl-handshake.js +28 -0
- package/dist/apis/telemetry/get-telemetry-subscriptions.d.ts +18 -0
- package/dist/apis/telemetry/get-telemetry-subscriptions.js +46 -0
- package/dist/apis/telemetry/index.d.ts +3 -0
- package/dist/apis/telemetry/index.js +3 -0
- package/dist/apis/telemetry/list-client-metrics-resources.d.ts +14 -0
- package/dist/apis/telemetry/list-client-metrics-resources.js +32 -0
- package/dist/apis/telemetry/push-telemetry.d.ts +10 -0
- package/dist/apis/telemetry/push-telemetry.js +36 -0
- package/dist/clients/admin/admin.d.ts +18 -0
- package/dist/clients/admin/admin.js +322 -0
- package/dist/clients/admin/index.d.ts +3 -0
- package/dist/clients/admin/index.js +3 -0
- package/dist/clients/admin/options.d.ts +135 -0
- package/dist/clients/admin/options.js +81 -0
- package/dist/clients/admin/types.d.ts +56 -0
- package/dist/clients/admin/types.js +1 -0
- package/dist/clients/base/base.d.ts +48 -0
- package/dist/clients/base/base.js +242 -0
- package/dist/clients/base/index.d.ts +3 -0
- package/dist/clients/base/index.js +3 -0
- package/dist/clients/base/options.d.ts +115 -0
- package/dist/clients/base/options.js +59 -0
- package/dist/clients/base/types.d.ts +38 -0
- package/dist/clients/base/types.js +1 -0
- package/dist/clients/callbacks.d.ts +8 -0
- package/dist/clients/callbacks.js +42 -0
- package/dist/clients/consumer/consumer.d.ts +33 -0
- package/dist/clients/consumer/consumer.js +767 -0
- package/dist/clients/consumer/index.d.ts +5 -0
- package/dist/clients/consumer/index.js +5 -0
- package/dist/clients/consumer/messages-stream.d.ts +56 -0
- package/dist/clients/consumer/messages-stream.js +404 -0
- package/dist/clients/consumer/options.d.ts +521 -0
- package/dist/clients/consumer/options.js +177 -0
- package/dist/clients/consumer/topics-map.d.ts +8 -0
- package/dist/clients/consumer/topics-map.js +48 -0
- package/dist/clients/consumer/types.d.ts +74 -0
- package/dist/clients/consumer/types.js +11 -0
- package/dist/clients/index.d.ts +6 -0
- package/dist/clients/index.js +6 -0
- package/dist/clients/producer/index.d.ts +3 -0
- package/dist/clients/producer/index.js +3 -0
- package/dist/clients/producer/options.d.ts +122 -0
- package/dist/clients/producer/options.js +47 -0
- package/dist/clients/producer/producer.d.ts +13 -0
- package/dist/clients/producer/producer.js +272 -0
- package/dist/clients/producer/types.d.ts +29 -0
- package/dist/clients/producer/types.js +1 -0
- package/dist/clients/serde.d.ts +40 -0
- package/dist/clients/serde.js +49 -0
- package/dist/errors.d.ts +67 -0
- package/dist/errors.js +160 -0
- package/dist/index.d.ts +6 -0
- package/dist/index.js +10 -0
- package/dist/network/connection-pool.d.ts +11 -0
- package/dist/network/connection-pool.js +101 -0
- package/dist/network/connection.d.ts +49 -0
- package/dist/network/connection.js +319 -0
- package/dist/network/index.d.ts +2 -0
- package/dist/network/index.js +2 -0
- package/dist/protocol/apis.d.ts +2 -0
- package/dist/protocol/apis.js +191 -0
- package/dist/protocol/compression.d.ts +70 -0
- package/dist/protocol/compression.js +114 -0
- package/dist/protocol/crc32c.d.ts +2 -0
- package/dist/protocol/crc32c.js +83 -0
- package/dist/protocol/definitions.d.ts +12 -0
- package/dist/protocol/definitions.js +11 -0
- package/dist/protocol/dynamic-buffer.d.ts +65 -0
- package/dist/protocol/dynamic-buffer.js +557 -0
- package/dist/protocol/errors.d.ts +8 -0
- package/dist/protocol/errors.js +908 -0
- package/dist/protocol/index.d.ts +14 -0
- package/dist/protocol/index.js +14 -0
- package/dist/protocol/murmur2.d.ts +1 -0
- package/dist/protocol/murmur2.js +55 -0
- package/dist/protocol/reader.d.ts +58 -0
- package/dist/protocol/reader.js +296 -0
- package/dist/protocol/records.d.ts +110 -0
- package/dist/protocol/records.js +149 -0
- package/dist/protocol/sasl/plain.d.ts +3 -0
- package/dist/protocol/sasl/plain.js +3 -0
- package/dist/protocol/sasl/scram-sha.d.ts +28 -0
- package/dist/protocol/sasl/scram-sha.js +104 -0
- package/dist/protocol/varint.d.ts +12 -0
- package/dist/protocol/varint.js +36 -0
- package/dist/protocol/writer.d.ts +48 -0
- package/dist/protocol/writer.js +223 -0
- package/dist/utils.d.ts +20 -0
- package/dist/utils.js +127 -0
- package/package.json +75 -0
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
export * from './apis.ts';
|
|
2
|
+
export * from './compression.ts';
|
|
3
|
+
export * from './crc32c.ts';
|
|
4
|
+
export * from './definitions.ts';
|
|
5
|
+
export * from './dynamic-buffer.ts';
|
|
6
|
+
export * from './errors.ts';
|
|
7
|
+
export * from './index.ts';
|
|
8
|
+
export * from './murmur2.ts';
|
|
9
|
+
export * from './reader.ts';
|
|
10
|
+
export * from './records.ts';
|
|
11
|
+
export * as saslPlain from './sasl/plain.ts';
|
|
12
|
+
export * as saslScramSha from './sasl/scram-sha.ts';
|
|
13
|
+
export * from './varint.ts';
|
|
14
|
+
export * from './writer.ts';
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
export * from "./apis.js";
|
|
2
|
+
export * from "./compression.js";
|
|
3
|
+
export * from "./crc32c.js";
|
|
4
|
+
export * from "./definitions.js";
|
|
5
|
+
export * from "./dynamic-buffer.js";
|
|
6
|
+
export * from "./errors.js";
|
|
7
|
+
export * from "./index.js";
|
|
8
|
+
export * from "./murmur2.js";
|
|
9
|
+
export * from "./reader.js";
|
|
10
|
+
export * from "./records.js";
|
|
11
|
+
export * as saslPlain from "./sasl/plain.js";
|
|
12
|
+
export * as saslScramSha from "./sasl/scram-sha.js";
|
|
13
|
+
export * from "./varint.js";
|
|
14
|
+
export * from "./writer.js";
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare function murmur2(data: string | Buffer, useCache?: boolean): number;
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
import { LRUCache } from 'mnemonist';
|
|
2
|
+
// This is a Javascript port of
|
|
3
|
+
// https://github.com/apache/kafka/blob/trunk/clients/src/main/java/org/apache/kafka/common/utils/Utils.java#L492
|
|
4
|
+
// 'm' and 'r' are mixing constants generated offline. They're not really 'magic', they just happen to work well.
|
|
5
|
+
const seed = 0x9747b28cn;
|
|
6
|
+
const m = 0x5bd1e995n;
|
|
7
|
+
const r = 24;
|
|
8
|
+
const cache = new LRUCache(1000);
|
|
9
|
+
const tail = Buffer.alloc(4);
|
|
10
|
+
function tripleRightShift(num, bits) {
|
|
11
|
+
return BigInt(Number(BigInt.asIntN(32, num)) >>> bits);
|
|
12
|
+
}
|
|
13
|
+
export function murmur2(data, useCache = false) {
|
|
14
|
+
let key;
|
|
15
|
+
if (typeof data === 'string') {
|
|
16
|
+
if (useCache) {
|
|
17
|
+
key = data;
|
|
18
|
+
const existing = key ? cache.get(key) : undefined;
|
|
19
|
+
if (existing) {
|
|
20
|
+
return existing;
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
data = Buffer.from(data);
|
|
24
|
+
}
|
|
25
|
+
const length = data.length;
|
|
26
|
+
// Initialize the hash to a random value
|
|
27
|
+
let h = seed ^ BigInt(length);
|
|
28
|
+
let i = 0;
|
|
29
|
+
while (i < length - 3) {
|
|
30
|
+
let k = BigInt(data.readInt32LE(i));
|
|
31
|
+
i += 4;
|
|
32
|
+
k *= m;
|
|
33
|
+
k ^= tripleRightShift(k, r);
|
|
34
|
+
k *= m;
|
|
35
|
+
h *= m;
|
|
36
|
+
h ^= k;
|
|
37
|
+
}
|
|
38
|
+
// Read the last few bytes of the input array
|
|
39
|
+
// If this becomes an hot-path, consider to optimize it further and avoid copying
|
|
40
|
+
if (length % 4 > 0) {
|
|
41
|
+
data.copy(tail, 0, length - (length % 4));
|
|
42
|
+
h ^= BigInt(tail.readInt32LE(0));
|
|
43
|
+
tail.fill(0);
|
|
44
|
+
h *= m;
|
|
45
|
+
}
|
|
46
|
+
// Perform the final mixing
|
|
47
|
+
h ^= tripleRightShift(h, 13);
|
|
48
|
+
h *= m;
|
|
49
|
+
h ^= tripleRightShift(h, 15);
|
|
50
|
+
const hash = Number(BigInt.asIntN(32, h));
|
|
51
|
+
if (key !== undefined) {
|
|
52
|
+
cache.set(key, hash);
|
|
53
|
+
}
|
|
54
|
+
return hash;
|
|
55
|
+
}
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
import { DynamicBuffer } from './dynamic-buffer.ts';
|
|
2
|
+
import { Writer } from './writer.ts';
|
|
3
|
+
export type EntryReader<OutputType> = (reader: Reader, index: number) => OutputType;
|
|
4
|
+
declare const instanceIdentifier: unique symbol;
|
|
5
|
+
export declare class Reader {
|
|
6
|
+
buffer: DynamicBuffer;
|
|
7
|
+
position: number;
|
|
8
|
+
[instanceIdentifier]: boolean;
|
|
9
|
+
static isReader(target: any): boolean;
|
|
10
|
+
static from(buffer: Buffer | DynamicBuffer | Writer): Reader;
|
|
11
|
+
constructor(buffer: DynamicBuffer);
|
|
12
|
+
reset(buffer?: Buffer | DynamicBuffer): void;
|
|
13
|
+
inspect(): string;
|
|
14
|
+
skip(length: number): this;
|
|
15
|
+
peekUnsignedInt8(): number;
|
|
16
|
+
peekUnsignedInt16(): number;
|
|
17
|
+
peekUnsignedInt32(): number;
|
|
18
|
+
peekUnsignedInt64(): bigint;
|
|
19
|
+
peekUnsignedVarInt(): number;
|
|
20
|
+
peekUnsignedVarInt64(): bigint;
|
|
21
|
+
peekInt8(): number;
|
|
22
|
+
peekInt16(): number;
|
|
23
|
+
peekInt32(): number;
|
|
24
|
+
peekInt64(): bigint;
|
|
25
|
+
peekFloat64(): number;
|
|
26
|
+
peekVarInt(): number;
|
|
27
|
+
peekVarInt64(): bigint;
|
|
28
|
+
peekBoolean(): boolean;
|
|
29
|
+
peekUUID(): string;
|
|
30
|
+
readUnsignedInt8(): number;
|
|
31
|
+
readUnsignedInt16(): number;
|
|
32
|
+
readUnsignedInt32(): number;
|
|
33
|
+
readUnsignedInt64(): bigint;
|
|
34
|
+
readUnsignedVarInt(): number;
|
|
35
|
+
readUnsignedVarInt64(): bigint;
|
|
36
|
+
readInt8(): number;
|
|
37
|
+
readInt16(): number;
|
|
38
|
+
readInt32(): number;
|
|
39
|
+
readInt64(): bigint;
|
|
40
|
+
readFloat64(): number;
|
|
41
|
+
readVarInt(): number;
|
|
42
|
+
readVarInt64(): bigint;
|
|
43
|
+
readBoolean(): boolean;
|
|
44
|
+
readNullableString(compact?: boolean, encoding?: BufferEncoding): string | null;
|
|
45
|
+
readString(compact?: boolean, encoding?: BufferEncoding): string;
|
|
46
|
+
readUUID(): string;
|
|
47
|
+
readNullableBytes(compact?: boolean): Buffer | null;
|
|
48
|
+
readBytes(compact?: boolean): Buffer;
|
|
49
|
+
readVarIntBytes(): Buffer;
|
|
50
|
+
readNullableArray<OutputType>(reader: EntryReader<OutputType>, compact?: boolean, discardTrailingTaggedFields?: boolean): OutputType[] | null;
|
|
51
|
+
readNullableMap<Key, Value>(reader: EntryReader<[Key, Value]>, compact?: boolean, discardTrailingTaggedFields?: boolean): Map<Key, Value> | null;
|
|
52
|
+
readArray<OutputType>(reader: EntryReader<OutputType>, compact?: boolean, discardTrailingTaggedFields?: boolean): OutputType[];
|
|
53
|
+
readMap<Key, Value>(reader: EntryReader<[Key, Value]>, compact?: boolean, discardTrailingTaggedFields?: boolean): Map<Key, Value>;
|
|
54
|
+
readVarIntArray<OutputType>(reader: EntryReader<OutputType>): OutputType[];
|
|
55
|
+
readVarIntMap<Key, Value>(reader: EntryReader<[Key, Value]>): Map<Key, Value>;
|
|
56
|
+
readTaggedFields(): void;
|
|
57
|
+
}
|
|
58
|
+
export {};
|
|
@@ -0,0 +1,296 @@
|
|
|
1
|
+
import { EMPTY_BUFFER, INT16_SIZE, INT32_SIZE, INT64_SIZE, INT8_SIZE, UUID_SIZE } from "./definitions.js";
|
|
2
|
+
import { DynamicBuffer } from "./dynamic-buffer.js";
|
|
3
|
+
import { Writer } from "./writer.js";
|
|
4
|
+
const instanceIdentifier = Symbol('plt.kafka.reader.instanceIdentifier');
|
|
5
|
+
export class Reader {
|
|
6
|
+
buffer;
|
|
7
|
+
position;
|
|
8
|
+
[instanceIdentifier];
|
|
9
|
+
static isReader(target) {
|
|
10
|
+
return target?.[instanceIdentifier] === true;
|
|
11
|
+
}
|
|
12
|
+
static from(buffer) {
|
|
13
|
+
if (Writer.isWriter(buffer)) {
|
|
14
|
+
return new Reader(buffer.dynamicBuffer);
|
|
15
|
+
}
|
|
16
|
+
else if (Buffer.isBuffer(buffer)) {
|
|
17
|
+
buffer = new DynamicBuffer(buffer);
|
|
18
|
+
}
|
|
19
|
+
return new Reader(buffer);
|
|
20
|
+
}
|
|
21
|
+
constructor(buffer) {
|
|
22
|
+
this.buffer = buffer;
|
|
23
|
+
this.position = 0;
|
|
24
|
+
this[instanceIdentifier] = true;
|
|
25
|
+
}
|
|
26
|
+
reset(buffer) {
|
|
27
|
+
if (buffer) {
|
|
28
|
+
if (Buffer.isBuffer(buffer)) {
|
|
29
|
+
buffer = new DynamicBuffer(buffer);
|
|
30
|
+
}
|
|
31
|
+
this.buffer = buffer;
|
|
32
|
+
}
|
|
33
|
+
this.position = 0;
|
|
34
|
+
}
|
|
35
|
+
inspect() {
|
|
36
|
+
return this.buffer
|
|
37
|
+
.subarray(this.position)
|
|
38
|
+
.toString('hex')
|
|
39
|
+
.replaceAll(/(.{4})/g, '$1 ')
|
|
40
|
+
.trim();
|
|
41
|
+
}
|
|
42
|
+
skip(length) {
|
|
43
|
+
this.position += length;
|
|
44
|
+
return this;
|
|
45
|
+
}
|
|
46
|
+
peekUnsignedInt8() {
|
|
47
|
+
return this.buffer.readUInt8(this.position);
|
|
48
|
+
}
|
|
49
|
+
peekUnsignedInt16() {
|
|
50
|
+
return this.buffer.readUInt16BE(this.position);
|
|
51
|
+
}
|
|
52
|
+
peekUnsignedInt32() {
|
|
53
|
+
return this.buffer.readUInt32BE(this.position);
|
|
54
|
+
}
|
|
55
|
+
peekUnsignedInt64() {
|
|
56
|
+
return this.buffer.readBigUInt64BE(this.position);
|
|
57
|
+
}
|
|
58
|
+
peekUnsignedVarInt() {
|
|
59
|
+
return this.buffer.readUnsignedVarInt(this.position)[0];
|
|
60
|
+
}
|
|
61
|
+
peekUnsignedVarInt64() {
|
|
62
|
+
return this.buffer.readUnsignedVarInt64(this.position)[0];
|
|
63
|
+
}
|
|
64
|
+
peekInt8() {
|
|
65
|
+
return this.buffer.readInt8(this.position);
|
|
66
|
+
}
|
|
67
|
+
peekInt16() {
|
|
68
|
+
return this.buffer.readInt16BE(this.position);
|
|
69
|
+
}
|
|
70
|
+
peekInt32() {
|
|
71
|
+
return this.buffer.readInt32BE(this.position);
|
|
72
|
+
}
|
|
73
|
+
peekInt64() {
|
|
74
|
+
return this.buffer.readBigInt64BE(this.position);
|
|
75
|
+
}
|
|
76
|
+
peekFloat64() {
|
|
77
|
+
return this.buffer.readDoubleBE(this.position);
|
|
78
|
+
}
|
|
79
|
+
peekVarInt() {
|
|
80
|
+
return this.buffer.readVarInt(this.position)[0];
|
|
81
|
+
}
|
|
82
|
+
peekVarInt64() {
|
|
83
|
+
return this.buffer.readVarInt64(this.position)[0];
|
|
84
|
+
}
|
|
85
|
+
peekBoolean() {
|
|
86
|
+
return this.buffer.readInt8(this.position) === 1;
|
|
87
|
+
}
|
|
88
|
+
peekUUID() {
|
|
89
|
+
return this.buffer.toString('hex', this.position, this.position + UUID_SIZE);
|
|
90
|
+
}
|
|
91
|
+
readUnsignedInt8() {
|
|
92
|
+
const value = this.peekUnsignedInt8();
|
|
93
|
+
this.position += INT8_SIZE;
|
|
94
|
+
return value;
|
|
95
|
+
}
|
|
96
|
+
readUnsignedInt16() {
|
|
97
|
+
const value = this.peekUnsignedInt16();
|
|
98
|
+
this.position += INT16_SIZE;
|
|
99
|
+
return value;
|
|
100
|
+
}
|
|
101
|
+
readUnsignedInt32() {
|
|
102
|
+
const value = this.peekUnsignedInt32();
|
|
103
|
+
this.position += INT32_SIZE;
|
|
104
|
+
return value;
|
|
105
|
+
}
|
|
106
|
+
readUnsignedInt64() {
|
|
107
|
+
const value = this.peekUnsignedInt64();
|
|
108
|
+
this.position += INT64_SIZE;
|
|
109
|
+
return value;
|
|
110
|
+
}
|
|
111
|
+
readUnsignedVarInt() {
|
|
112
|
+
const [value, read] = this.buffer.readUnsignedVarInt(this.position);
|
|
113
|
+
this.position += read;
|
|
114
|
+
return value;
|
|
115
|
+
}
|
|
116
|
+
readUnsignedVarInt64() {
|
|
117
|
+
const [value, read] = this.buffer.readUnsignedVarInt64(this.position);
|
|
118
|
+
this.position += read;
|
|
119
|
+
return value;
|
|
120
|
+
}
|
|
121
|
+
readInt8() {
|
|
122
|
+
const value = this.peekInt8();
|
|
123
|
+
this.position += INT8_SIZE;
|
|
124
|
+
return value;
|
|
125
|
+
}
|
|
126
|
+
readInt16() {
|
|
127
|
+
const value = this.peekInt16();
|
|
128
|
+
this.position += INT16_SIZE;
|
|
129
|
+
return value;
|
|
130
|
+
}
|
|
131
|
+
readInt32() {
|
|
132
|
+
const value = this.peekInt32();
|
|
133
|
+
this.position += INT32_SIZE;
|
|
134
|
+
return value;
|
|
135
|
+
}
|
|
136
|
+
readInt64() {
|
|
137
|
+
const value = this.peekInt64();
|
|
138
|
+
this.position += INT64_SIZE;
|
|
139
|
+
return value;
|
|
140
|
+
}
|
|
141
|
+
readFloat64() {
|
|
142
|
+
const value = this.peekFloat64();
|
|
143
|
+
this.position += INT64_SIZE;
|
|
144
|
+
return value;
|
|
145
|
+
}
|
|
146
|
+
readVarInt() {
|
|
147
|
+
const [value, read] = this.buffer.readVarInt(this.position);
|
|
148
|
+
this.position += read;
|
|
149
|
+
return value;
|
|
150
|
+
}
|
|
151
|
+
readVarInt64() {
|
|
152
|
+
const [value, read] = this.buffer.readVarInt64(this.position);
|
|
153
|
+
this.position += read;
|
|
154
|
+
return value;
|
|
155
|
+
}
|
|
156
|
+
readBoolean() {
|
|
157
|
+
const value = this.peekUnsignedInt8();
|
|
158
|
+
this.position += INT8_SIZE;
|
|
159
|
+
return value === 1;
|
|
160
|
+
}
|
|
161
|
+
readNullableString(compact = true, encoding = 'utf-8') {
|
|
162
|
+
let length;
|
|
163
|
+
if (compact) {
|
|
164
|
+
length = this.readUnsignedVarInt();
|
|
165
|
+
if (length === 0) {
|
|
166
|
+
return null;
|
|
167
|
+
}
|
|
168
|
+
length--;
|
|
169
|
+
}
|
|
170
|
+
else {
|
|
171
|
+
length = this.readInt16();
|
|
172
|
+
if (length === -1) {
|
|
173
|
+
return null;
|
|
174
|
+
}
|
|
175
|
+
}
|
|
176
|
+
const value = this.buffer.toString(encoding, this.position, this.position + length);
|
|
177
|
+
this.position += length;
|
|
178
|
+
return value;
|
|
179
|
+
}
|
|
180
|
+
readString(compact = true, encoding = 'utf-8') {
|
|
181
|
+
return this.readNullableString(compact, encoding) || '';
|
|
182
|
+
}
|
|
183
|
+
readUUID() {
|
|
184
|
+
const value = this.peekUUID();
|
|
185
|
+
this.position += UUID_SIZE;
|
|
186
|
+
return value.replace(/(.{8})(.{4})(.{4})(.{4})(.{12})/, '$1-$2-$3-$4-$5');
|
|
187
|
+
}
|
|
188
|
+
readNullableBytes(compact = true) {
|
|
189
|
+
let length;
|
|
190
|
+
if (compact) {
|
|
191
|
+
length = this.readUnsignedVarInt();
|
|
192
|
+
if (length === 0) {
|
|
193
|
+
return null;
|
|
194
|
+
}
|
|
195
|
+
length--;
|
|
196
|
+
}
|
|
197
|
+
else {
|
|
198
|
+
length = this.readInt32();
|
|
199
|
+
if (length === -1) {
|
|
200
|
+
return null;
|
|
201
|
+
}
|
|
202
|
+
}
|
|
203
|
+
const value = this.buffer.slice(this.position, this.position + length);
|
|
204
|
+
this.position += length;
|
|
205
|
+
return value;
|
|
206
|
+
}
|
|
207
|
+
readBytes(compact = true) {
|
|
208
|
+
/* c8 ignore next */
|
|
209
|
+
return this.readNullableBytes(compact) || EMPTY_BUFFER;
|
|
210
|
+
}
|
|
211
|
+
readVarIntBytes() {
|
|
212
|
+
const length = this.readVarInt();
|
|
213
|
+
const value = this.buffer.slice(this.position, this.position + length);
|
|
214
|
+
this.position += length;
|
|
215
|
+
return value;
|
|
216
|
+
}
|
|
217
|
+
readNullableArray(reader, compact = true, discardTrailingTaggedFields = true) {
|
|
218
|
+
let length;
|
|
219
|
+
if (compact) {
|
|
220
|
+
length = this.readUnsignedVarInt();
|
|
221
|
+
if (length === 0) {
|
|
222
|
+
return null;
|
|
223
|
+
}
|
|
224
|
+
length--;
|
|
225
|
+
}
|
|
226
|
+
else {
|
|
227
|
+
length = this.readInt32();
|
|
228
|
+
if (length === -1) {
|
|
229
|
+
return null;
|
|
230
|
+
}
|
|
231
|
+
}
|
|
232
|
+
const value = [];
|
|
233
|
+
for (let i = 0; i < length; i++) {
|
|
234
|
+
value.push(reader(this, i));
|
|
235
|
+
if (discardTrailingTaggedFields) {
|
|
236
|
+
this.readTaggedFields();
|
|
237
|
+
}
|
|
238
|
+
}
|
|
239
|
+
return value;
|
|
240
|
+
}
|
|
241
|
+
readNullableMap(reader, compact = true, discardTrailingTaggedFields = true) {
|
|
242
|
+
let length;
|
|
243
|
+
if (compact) {
|
|
244
|
+
length = this.readUnsignedVarInt();
|
|
245
|
+
if (length === 0) {
|
|
246
|
+
return null;
|
|
247
|
+
}
|
|
248
|
+
length--;
|
|
249
|
+
}
|
|
250
|
+
else {
|
|
251
|
+
length = this.readInt32();
|
|
252
|
+
if (length === -1) {
|
|
253
|
+
return null;
|
|
254
|
+
}
|
|
255
|
+
}
|
|
256
|
+
const map = new Map();
|
|
257
|
+
for (let i = 0; i < length; i++) {
|
|
258
|
+
const [key, value] = reader(this, i);
|
|
259
|
+
map.set(key, value);
|
|
260
|
+
if (discardTrailingTaggedFields) {
|
|
261
|
+
this.readTaggedFields();
|
|
262
|
+
}
|
|
263
|
+
}
|
|
264
|
+
return map;
|
|
265
|
+
}
|
|
266
|
+
readArray(reader, compact = true, discardTrailingTaggedFields = true) {
|
|
267
|
+
return this.readNullableArray(reader, compact, discardTrailingTaggedFields) || [];
|
|
268
|
+
}
|
|
269
|
+
readMap(reader, compact = true, discardTrailingTaggedFields = true) {
|
|
270
|
+
return this.readNullableMap(reader, compact, discardTrailingTaggedFields) ?? new Map();
|
|
271
|
+
}
|
|
272
|
+
readVarIntArray(reader) {
|
|
273
|
+
const length = this.readVarInt();
|
|
274
|
+
const value = [];
|
|
275
|
+
for (let i = 0; i < length; i++) {
|
|
276
|
+
value.push(reader(this, i));
|
|
277
|
+
}
|
|
278
|
+
return value;
|
|
279
|
+
}
|
|
280
|
+
readVarIntMap(reader) {
|
|
281
|
+
const length = this.readVarInt();
|
|
282
|
+
const map = new Map();
|
|
283
|
+
for (let i = 0; i < length; i++) {
|
|
284
|
+
const [key, value] = reader(this, i);
|
|
285
|
+
map.set(key, value);
|
|
286
|
+
}
|
|
287
|
+
return map;
|
|
288
|
+
}
|
|
289
|
+
// TODO(ShogunPanda): Tagged fields are not supported yet
|
|
290
|
+
readTaggedFields() {
|
|
291
|
+
const length = this.readVarInt();
|
|
292
|
+
if (length > 0) {
|
|
293
|
+
this.skip(length);
|
|
294
|
+
}
|
|
295
|
+
}
|
|
296
|
+
}
|
|
@@ -0,0 +1,110 @@
|
|
|
1
|
+
import { type NumericMap } from '../utils.ts';
|
|
2
|
+
import { type CompressionAlgorithms } from './compression.ts';
|
|
3
|
+
import { type NullableString } from './definitions.ts';
|
|
4
|
+
import { Reader } from './reader.ts';
|
|
5
|
+
import { Writer } from './writer.ts';
|
|
6
|
+
export interface MessageBase<Key = Buffer, Value = Buffer> {
|
|
7
|
+
key?: Key;
|
|
8
|
+
value?: Value;
|
|
9
|
+
topic: string;
|
|
10
|
+
partition?: number;
|
|
11
|
+
timestamp?: bigint;
|
|
12
|
+
}
|
|
13
|
+
export interface MessageToProduce<Key = Buffer, Value = Buffer, HeaderKey = Buffer, HeaderValue = Buffer> extends MessageBase<Key, Value> {
|
|
14
|
+
headers?: Map<HeaderKey, HeaderValue> | Record<string, HeaderValue>;
|
|
15
|
+
}
|
|
16
|
+
export interface Message<Key = Buffer, Value = Buffer, HeaderKey = Buffer, HeaderValue = Buffer> extends Required<MessageBase<Key, Value>> {
|
|
17
|
+
headers: Map<HeaderKey, HeaderValue>;
|
|
18
|
+
offset: bigint;
|
|
19
|
+
commit(callback?: (error?: Error) => void): void | Promise<void>;
|
|
20
|
+
}
|
|
21
|
+
export interface MessageRecord {
|
|
22
|
+
key?: Buffer;
|
|
23
|
+
value: Buffer;
|
|
24
|
+
headers?: Map<Buffer, Buffer>;
|
|
25
|
+
topic: string;
|
|
26
|
+
partition?: number;
|
|
27
|
+
timestamp?: bigint;
|
|
28
|
+
}
|
|
29
|
+
export interface CreateRecordsBatchOptions {
|
|
30
|
+
transactionalId?: NullableString;
|
|
31
|
+
compression: CompressionAlgorithms;
|
|
32
|
+
firstSequence?: number;
|
|
33
|
+
producerId: bigint;
|
|
34
|
+
producerEpoch: number;
|
|
35
|
+
sequences: NumericMap;
|
|
36
|
+
partitionLeaderEpoch: number;
|
|
37
|
+
}
|
|
38
|
+
export interface KafkaRecord {
|
|
39
|
+
length: number;
|
|
40
|
+
attributes: number;
|
|
41
|
+
timestampDelta: bigint;
|
|
42
|
+
offsetDelta: number;
|
|
43
|
+
key: Buffer;
|
|
44
|
+
value: Buffer;
|
|
45
|
+
headers: [Buffer, Buffer][];
|
|
46
|
+
}
|
|
47
|
+
export interface RecordsBatch {
|
|
48
|
+
firstOffset: bigint;
|
|
49
|
+
length: number;
|
|
50
|
+
partitionLeaderEpoch: number;
|
|
51
|
+
magic: number;
|
|
52
|
+
crc: number;
|
|
53
|
+
attributes: number;
|
|
54
|
+
lastOffsetDelta: number;
|
|
55
|
+
firstTimestamp: bigint;
|
|
56
|
+
maxTimestamp: bigint;
|
|
57
|
+
producerId: bigint;
|
|
58
|
+
producerEpoch: number;
|
|
59
|
+
firstSequence: number;
|
|
60
|
+
records: KafkaRecord[];
|
|
61
|
+
}
|
|
62
|
+
export declare const messageSchema: {
|
|
63
|
+
type: string;
|
|
64
|
+
properties: {
|
|
65
|
+
key: {
|
|
66
|
+
oneOf: ({
|
|
67
|
+
type: string;
|
|
68
|
+
buffer?: undefined;
|
|
69
|
+
} | {
|
|
70
|
+
buffer: boolean;
|
|
71
|
+
type?: undefined;
|
|
72
|
+
})[];
|
|
73
|
+
};
|
|
74
|
+
value: {
|
|
75
|
+
oneOf: ({
|
|
76
|
+
type: string;
|
|
77
|
+
buffer?: undefined;
|
|
78
|
+
} | {
|
|
79
|
+
buffer: boolean;
|
|
80
|
+
type?: undefined;
|
|
81
|
+
})[];
|
|
82
|
+
};
|
|
83
|
+
headers: {
|
|
84
|
+
anyOf: ({
|
|
85
|
+
map: boolean;
|
|
86
|
+
type?: undefined;
|
|
87
|
+
additionalProperties?: undefined;
|
|
88
|
+
} | {
|
|
89
|
+
type: string;
|
|
90
|
+
additionalProperties: boolean;
|
|
91
|
+
map?: undefined;
|
|
92
|
+
})[];
|
|
93
|
+
};
|
|
94
|
+
topic: {
|
|
95
|
+
type: string;
|
|
96
|
+
};
|
|
97
|
+
partition: {
|
|
98
|
+
type: string;
|
|
99
|
+
};
|
|
100
|
+
timestamp: {
|
|
101
|
+
bigint: boolean;
|
|
102
|
+
};
|
|
103
|
+
};
|
|
104
|
+
required: string[];
|
|
105
|
+
additionalProperties: boolean;
|
|
106
|
+
};
|
|
107
|
+
export declare function createRecord(message: MessageRecord, offsetDelta: number, firstTimestamp: bigint): Writer;
|
|
108
|
+
export declare function readRecord(reader: Reader): KafkaRecord;
|
|
109
|
+
export declare function createRecordsBatch(messages: MessageRecord[], options?: Partial<CreateRecordsBatchOptions>): Writer;
|
|
110
|
+
export declare function readRecordsBatch(reader: Reader): RecordsBatch;
|
|
@@ -0,0 +1,149 @@
|
|
|
1
|
+
import { UnsupportedCompressionError } from "../errors.js";
|
|
2
|
+
import { compressionsAlgorithms, compressionsAlgorithmsByBitmask } from "./compression.js";
|
|
3
|
+
import { crc32c } from "./crc32c.js";
|
|
4
|
+
import { DynamicBuffer } from "./dynamic-buffer.js";
|
|
5
|
+
import { Reader } from "./reader.js";
|
|
6
|
+
import { Writer } from "./writer.js";
|
|
7
|
+
const CURRENT_RECORD_VERSION = 2;
|
|
8
|
+
const IS_TRANSACTIONAL = 0b10000; // Bit 4 set
|
|
9
|
+
const IS_COMPRESSED = 0b111; // Bits 0, 1 and/or 2 set
|
|
10
|
+
export const messageSchema = {
|
|
11
|
+
type: 'object',
|
|
12
|
+
properties: {
|
|
13
|
+
key: {
|
|
14
|
+
oneOf: [{ type: 'string' }, { buffer: true }]
|
|
15
|
+
},
|
|
16
|
+
value: {
|
|
17
|
+
oneOf: [{ type: 'string' }, { buffer: true }]
|
|
18
|
+
},
|
|
19
|
+
headers: {
|
|
20
|
+
// Note: we can't use oneOf here since a Map is also a 'object'. Thanks JS.
|
|
21
|
+
anyOf: [
|
|
22
|
+
{
|
|
23
|
+
map: true
|
|
24
|
+
},
|
|
25
|
+
{
|
|
26
|
+
type: 'object',
|
|
27
|
+
additionalProperties: true
|
|
28
|
+
}
|
|
29
|
+
]
|
|
30
|
+
},
|
|
31
|
+
topic: { type: 'string' },
|
|
32
|
+
partition: { type: 'integer' },
|
|
33
|
+
timestamp: { bigint: true }
|
|
34
|
+
},
|
|
35
|
+
required: ['value', 'topic'],
|
|
36
|
+
additionalProperties: true
|
|
37
|
+
};
|
|
38
|
+
export function createRecord(message, offsetDelta, firstTimestamp) {
|
|
39
|
+
return Writer.create()
|
|
40
|
+
.appendInt8(0) // Attributes are unused for now
|
|
41
|
+
.appendVarInt64((message.timestamp ?? BigInt(Date.now())) - firstTimestamp)
|
|
42
|
+
.appendVarInt(offsetDelta)
|
|
43
|
+
.appendVarIntBytes(message.key)
|
|
44
|
+
.appendVarIntBytes(message.value)
|
|
45
|
+
.appendVarIntMap(message.headers, (w, [key, value]) => {
|
|
46
|
+
w.appendVarIntBytes(key).appendVarIntBytes(value);
|
|
47
|
+
})
|
|
48
|
+
.prependVarIntLength();
|
|
49
|
+
}
|
|
50
|
+
export function readRecord(reader) {
|
|
51
|
+
return {
|
|
52
|
+
length: reader.readVarInt(),
|
|
53
|
+
attributes: reader.readInt8(),
|
|
54
|
+
timestampDelta: reader.readVarInt64(),
|
|
55
|
+
offsetDelta: reader.readVarInt(),
|
|
56
|
+
key: reader.readVarIntBytes(),
|
|
57
|
+
value: reader.readVarIntBytes(),
|
|
58
|
+
headers: reader.readVarIntArray(r => [r.readVarIntBytes(), r.readVarIntBytes()])
|
|
59
|
+
};
|
|
60
|
+
}
|
|
61
|
+
export function createRecordsBatch(messages, options = {}) {
|
|
62
|
+
const now = BigInt(Date.now());
|
|
63
|
+
const timestamps = [];
|
|
64
|
+
for (let i = 0; i < messages.length; i++) {
|
|
65
|
+
timestamps.push(messages[i].timestamp ?? now);
|
|
66
|
+
}
|
|
67
|
+
messages.sort();
|
|
68
|
+
const firstTimestamp = timestamps[0];
|
|
69
|
+
const maxTimestamp = timestamps[timestamps.length - 1];
|
|
70
|
+
let buffer = new DynamicBuffer();
|
|
71
|
+
for (let i = 0; i < messages.length; i++) {
|
|
72
|
+
const record = createRecord(messages[i], i, firstTimestamp);
|
|
73
|
+
buffer.appendFrom(record.dynamicBuffer);
|
|
74
|
+
}
|
|
75
|
+
let attributes = 0;
|
|
76
|
+
let firstSequence = 0;
|
|
77
|
+
if (options.sequences) {
|
|
78
|
+
const firstMessage = messages[0];
|
|
79
|
+
firstSequence = options.sequences.getWithDefault(`${firstMessage.topic}:${firstMessage.partition}`, 0);
|
|
80
|
+
}
|
|
81
|
+
// Set the transaction
|
|
82
|
+
if (options.transactionalId) {
|
|
83
|
+
attributes |= IS_TRANSACTIONAL;
|
|
84
|
+
}
|
|
85
|
+
// Set the compression, if any
|
|
86
|
+
/* c8 ignore next */
|
|
87
|
+
if ((options.compression ?? 'none') !== 'none') {
|
|
88
|
+
const algorithm = compressionsAlgorithms[options.compression];
|
|
89
|
+
if (!algorithm) {
|
|
90
|
+
throw new UnsupportedCompressionError(`Unsupported compression algorithm ${options.compression}`);
|
|
91
|
+
}
|
|
92
|
+
attributes |= algorithm.bitmask;
|
|
93
|
+
const compressed = algorithm.compressSync(buffer.buffer);
|
|
94
|
+
buffer = new DynamicBuffer(compressed);
|
|
95
|
+
}
|
|
96
|
+
const writer = Writer.create()
|
|
97
|
+
// Phase 1: Prepare the message from Attributes (included) to the end
|
|
98
|
+
.appendInt16(attributes)
|
|
99
|
+
// LastOffsetDelta, FirstTimestamp and MaxTimestamp are extracted from the messages
|
|
100
|
+
.appendInt32(messages.length - 1)
|
|
101
|
+
.appendInt64(BigInt(firstTimestamp))
|
|
102
|
+
.appendInt64(BigInt(maxTimestamp))
|
|
103
|
+
/* c8 ignore next */
|
|
104
|
+
.appendInt64(options.producerId ?? -1n)
|
|
105
|
+
/* c8 ignore next */
|
|
106
|
+
.appendInt16(options.producerEpoch ?? 0)
|
|
107
|
+
.appendInt32(firstSequence)
|
|
108
|
+
.appendInt32(messages.length) // Number of records
|
|
109
|
+
.appendFrom(buffer);
|
|
110
|
+
// Phase 2: Prepend the PartitionLeaderEpoch, Magic and CRC, then the Length and firstOffset, in reverse order
|
|
111
|
+
return (writer
|
|
112
|
+
.appendUnsignedInt32(crc32c(writer.dynamicBuffer), false)
|
|
113
|
+
.appendInt8(CURRENT_RECORD_VERSION, false)
|
|
114
|
+
.appendInt32(options.partitionLeaderEpoch ?? 0, false)
|
|
115
|
+
.prependLength()
|
|
116
|
+
// FirstOffset is 0
|
|
117
|
+
.appendInt64(0n, false));
|
|
118
|
+
}
|
|
119
|
+
export function readRecordsBatch(reader) {
|
|
120
|
+
const batch = {
|
|
121
|
+
firstOffset: reader.readInt64(),
|
|
122
|
+
length: reader.readInt32(),
|
|
123
|
+
partitionLeaderEpoch: reader.readInt32(),
|
|
124
|
+
magic: reader.readInt8(),
|
|
125
|
+
crc: reader.readUnsignedInt32(),
|
|
126
|
+
attributes: reader.readInt16(),
|
|
127
|
+
lastOffsetDelta: reader.readInt32(),
|
|
128
|
+
firstTimestamp: reader.readInt64(),
|
|
129
|
+
maxTimestamp: reader.readInt64(),
|
|
130
|
+
producerId: reader.readInt64(),
|
|
131
|
+
producerEpoch: reader.readInt16(),
|
|
132
|
+
firstSequence: reader.readInt32(),
|
|
133
|
+
records: []
|
|
134
|
+
};
|
|
135
|
+
const recordsLength = reader.readInt32();
|
|
136
|
+
const compression = batch.attributes & IS_COMPRESSED;
|
|
137
|
+
if (compression !== 0) {
|
|
138
|
+
const algorithm = compressionsAlgorithmsByBitmask[compression];
|
|
139
|
+
if (!algorithm) {
|
|
140
|
+
throw new UnsupportedCompressionError(`Unsupported compression algorithm with bitmask ${compression}`);
|
|
141
|
+
}
|
|
142
|
+
const buffer = algorithm.decompressSync(reader.buffer.slice(reader.position, reader.buffer.length));
|
|
143
|
+
reader = Reader.from(buffer);
|
|
144
|
+
}
|
|
145
|
+
for (let i = 0; i < recordsLength; i++) {
|
|
146
|
+
batch.records.push(readRecord(reader));
|
|
147
|
+
}
|
|
148
|
+
return batch;
|
|
149
|
+
}
|