kafka-ts 0.0.3-beta → 0.0.4
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/README.md +72 -8
- package/dist/api/api-versions.d.ts +9 -0
- package/{src/api/api-versions.ts → dist/api/api-versions.js} +8 -5
- package/dist/api/create-topics.d.ts +38 -0
- package/dist/api/create-topics.js +53 -0
- package/dist/api/delete-topics.d.ts +18 -0
- package/dist/api/delete-topics.js +33 -0
- package/dist/api/fetch.d.ts +84 -0
- package/dist/api/fetch.js +142 -0
- package/dist/api/find-coordinator.d.ts +21 -0
- package/{src/api/find-coordinator.ts → dist/api/find-coordinator.js} +14 -14
- package/dist/api/heartbeat.d.ts +11 -0
- package/dist/api/heartbeat.js +27 -0
- package/dist/api/index.d.ts +576 -0
- package/{src/api/index.ts → dist/api/index.js} +42 -41
- package/dist/api/init-producer-id.d.ts +13 -0
- package/dist/api/init-producer-id.js +29 -0
- package/dist/api/join-group.d.ts +34 -0
- package/dist/api/join-group.js +51 -0
- package/dist/api/leave-group.d.ts +19 -0
- package/dist/api/leave-group.js +39 -0
- package/dist/api/list-offsets.d.ts +29 -0
- package/dist/api/list-offsets.js +48 -0
- package/dist/api/metadata.d.ts +40 -0
- package/{src/api/metadata.ts → dist/api/metadata.js} +18 -26
- package/dist/api/offset-commit.d.ts +28 -0
- package/dist/api/offset-commit.js +48 -0
- package/dist/api/offset-fetch.d.ts +31 -0
- package/dist/api/offset-fetch.js +55 -0
- package/dist/api/produce.d.ts +54 -0
- package/{src/api/produce.ts → dist/api/produce.js} +55 -102
- package/dist/api/sasl-authenticate.d.ts +11 -0
- package/dist/api/sasl-authenticate.js +23 -0
- package/dist/api/sasl-handshake.d.ts +6 -0
- package/dist/api/sasl-handshake.js +19 -0
- package/dist/api/sync-group.d.ts +24 -0
- package/dist/api/sync-group.js +36 -0
- package/dist/auth/index.d.ts +2 -0
- package/dist/auth/index.js +8 -0
- package/dist/auth/plain.d.ts +5 -0
- package/dist/auth/plain.js +12 -0
- package/dist/auth/scram.d.ts +9 -0
- package/dist/auth/scram.js +40 -0
- package/dist/broker.d.ts +30 -0
- package/dist/broker.js +55 -0
- package/dist/client.d.ts +22 -0
- package/dist/client.js +36 -0
- package/dist/cluster.d.ts +27 -0
- package/dist/cluster.js +70 -0
- package/dist/cluster.test.d.ts +1 -0
- package/{src/cluster.test.ts → dist/cluster.test.js} +87 -113
- package/dist/codecs/gzip.d.ts +2 -0
- package/dist/codecs/gzip.js +8 -0
- package/dist/codecs/index.d.ts +2 -0
- package/dist/codecs/index.js +17 -0
- package/dist/codecs/none.d.ts +2 -0
- package/dist/codecs/none.js +7 -0
- package/dist/codecs/types.d.ts +5 -0
- package/dist/codecs/types.js +2 -0
- package/dist/connection.d.ts +26 -0
- package/dist/connection.js +175 -0
- package/dist/consumer/consumer-group.d.ts +41 -0
- package/dist/consumer/consumer-group.js +215 -0
- package/dist/consumer/consumer-metadata.d.ts +7 -0
- package/dist/consumer/consumer-metadata.js +14 -0
- package/dist/consumer/consumer.d.ts +44 -0
- package/dist/consumer/consumer.js +225 -0
- package/dist/consumer/fetch-manager.d.ts +33 -0
- package/dist/consumer/fetch-manager.js +140 -0
- package/dist/consumer/fetcher.d.ts +25 -0
- package/dist/consumer/fetcher.js +64 -0
- package/dist/consumer/offset-manager.d.ts +22 -0
- package/dist/consumer/offset-manager.js +66 -0
- package/dist/consumer/processor.d.ts +19 -0
- package/dist/consumer/processor.js +59 -0
- package/dist/distributors/assignments-to-replicas.d.ts +16 -0
- package/{src/distributors/assignments-to-replicas.ts → dist/distributors/assignments-to-replicas.js} +15 -41
- package/dist/distributors/assignments-to-replicas.test.d.ts +1 -0
- package/dist/distributors/assignments-to-replicas.test.js +40 -0
- package/dist/distributors/messages-to-topic-partition-leaders.d.ts +17 -0
- package/dist/distributors/messages-to-topic-partition-leaders.js +15 -0
- package/dist/distributors/messages-to-topic-partition-leaders.test.d.ts +1 -0
- package/dist/distributors/messages-to-topic-partition-leaders.test.js +30 -0
- package/dist/distributors/partitioner.d.ts +7 -0
- package/dist/distributors/partitioner.js +23 -0
- package/dist/index.d.ts +9 -0
- package/dist/index.js +26 -0
- package/dist/metadata.d.ts +24 -0
- package/dist/metadata.js +106 -0
- package/dist/producer/producer.d.ts +24 -0
- package/dist/producer/producer.js +131 -0
- package/{src/types.ts → dist/types.d.ts} +4 -4
- package/dist/types.js +2 -0
- package/{src/utils/api.ts → dist/utils/api.d.ts} +2 -4
- package/dist/utils/api.js +5 -0
- package/dist/utils/crypto.d.ts +8 -0
- package/dist/utils/crypto.js +18 -0
- package/dist/utils/decoder.d.ts +30 -0
- package/{src/utils/decoder.ts → dist/utils/decoder.js} +41 -57
- package/dist/utils/delay.d.ts +1 -0
- package/dist/utils/delay.js +5 -0
- package/dist/utils/encoder.d.ts +28 -0
- package/{src/utils/encoder.ts → dist/utils/encoder.js} +50 -66
- package/dist/utils/error.d.ts +11 -0
- package/dist/utils/error.js +27 -0
- package/dist/utils/logger.d.ts +9 -0
- package/dist/utils/logger.js +32 -0
- package/dist/utils/memo.d.ts +1 -0
- package/{src/utils/memo.ts → dist/utils/memo.js} +7 -3
- package/dist/utils/murmur2.d.ts +3 -0
- package/dist/utils/murmur2.js +40 -0
- package/dist/utils/retrier.d.ts +10 -0
- package/dist/utils/retrier.js +22 -0
- package/dist/utils/tracer.d.ts +5 -0
- package/dist/utils/tracer.js +39 -0
- package/package.json +11 -2
- package/.github/workflows/release.yml +0 -17
- package/.prettierrc +0 -8
- package/certs/ca.crt +0 -29
- package/certs/ca.key +0 -52
- package/certs/ca.srl +0 -1
- package/certs/kafka.crt +0 -29
- package/certs/kafka.csr +0 -26
- package/certs/kafka.key +0 -52
- package/certs/kafka.keystore.jks +0 -0
- package/certs/kafka.truststore.jks +0 -0
- package/docker-compose.yml +0 -104
- package/examples/package-lock.json +0 -31
- package/examples/package.json +0 -14
- package/examples/src/client.ts +0 -9
- package/examples/src/consumer.ts +0 -18
- package/examples/src/create-topic.ts +0 -44
- package/examples/src/producer.ts +0 -24
- package/examples/src/replicator.ts +0 -25
- package/examples/src/utils/delay.ts +0 -1
- package/examples/src/utils/json.ts +0 -1
- package/examples/tsconfig.json +0 -7
- package/log4j.properties +0 -95
- package/scripts/generate-certs.sh +0 -24
- package/src/__snapshots__/request-handler.test.ts.snap +0 -978
- package/src/api/create-topics.ts +0 -78
- package/src/api/delete-topics.ts +0 -42
- package/src/api/fetch.ts +0 -143
- package/src/api/heartbeat.ts +0 -33
- package/src/api/init-producer-id.ts +0 -35
- package/src/api/join-group.ts +0 -67
- package/src/api/leave-group.ts +0 -48
- package/src/api/list-offsets.ts +0 -65
- package/src/api/offset-commit.ts +0 -67
- package/src/api/offset-fetch.ts +0 -74
- package/src/api/sasl-authenticate.ts +0 -21
- package/src/api/sasl-handshake.ts +0 -16
- package/src/api/sync-group.ts +0 -54
- package/src/broker.ts +0 -74
- package/src/client.ts +0 -47
- package/src/cluster.ts +0 -87
- package/src/connection.ts +0 -143
- package/src/consumer/consumer-group.ts +0 -209
- package/src/consumer/consumer-metadata.ts +0 -14
- package/src/consumer/consumer.ts +0 -231
- package/src/consumer/fetch-manager.ts +0 -179
- package/src/consumer/fetcher.ts +0 -57
- package/src/consumer/offset-manager.ts +0 -93
- package/src/consumer/processor.ts +0 -47
- package/src/distributors/assignments-to-replicas.test.ts +0 -43
- package/src/distributors/messages-to-topic-partition-leaders.test.ts +0 -32
- package/src/distributors/messages-to-topic-partition-leaders.ts +0 -19
- package/src/index.ts +0 -4
- package/src/metadata.ts +0 -122
- package/src/producer/producer.ts +0 -132
- package/src/utils/debug.ts +0 -9
- package/src/utils/delay.ts +0 -1
- package/src/utils/error.ts +0 -21
- package/src/utils/retrier.ts +0 -39
- package/src/utils/tracer.ts +0 -31
- package/tsconfig.json +0 -17
|
@@ -1,19 +0,0 @@
|
|
|
1
|
-
type TopicPartitionLeader = { [topicName: string]: { [partitionId: number]: number } };
|
|
2
|
-
type MessagesByNodeTopicPartition<T> = {
|
|
3
|
-
[nodeId: number]: { [topicName: string]: { [partitionId: number]: T[] } };
|
|
4
|
-
};
|
|
5
|
-
|
|
6
|
-
export const distributeMessagesToTopicPartitionLeaders = <T extends { topic: string; partition: number }>(
|
|
7
|
-
messages: T[],
|
|
8
|
-
topicPartitionLeader: TopicPartitionLeader,
|
|
9
|
-
) => {
|
|
10
|
-
const result: MessagesByNodeTopicPartition<T> = {};
|
|
11
|
-
messages.forEach((message) => {
|
|
12
|
-
const leaderId = topicPartitionLeader[message.topic][message.partition];
|
|
13
|
-
result[leaderId] ??= {};
|
|
14
|
-
result[leaderId][message.topic] ??= {};
|
|
15
|
-
result[leaderId][message.topic][message.partition] ??= [];
|
|
16
|
-
result[leaderId][message.topic][message.partition].push(message);
|
|
17
|
-
});
|
|
18
|
-
return result;
|
|
19
|
-
};
|
package/src/index.ts
DELETED
package/src/metadata.ts
DELETED
|
@@ -1,122 +0,0 @@
|
|
|
1
|
-
import { API, API_ERROR } from './api';
|
|
2
|
-
import { Cluster } from './cluster';
|
|
3
|
-
import { delay } from './utils/delay';
|
|
4
|
-
import { KafkaTSApiError } from './utils/error';
|
|
5
|
-
|
|
6
|
-
type MetadataOptions = {
|
|
7
|
-
cluster: Cluster;
|
|
8
|
-
};
|
|
9
|
-
|
|
10
|
-
export class Metadata {
|
|
11
|
-
private topicPartitions: Record<string, number[]> = {};
|
|
12
|
-
private topicNameById: Record<string, string> = {};
|
|
13
|
-
private topicIdByName: Record<string, string> = {};
|
|
14
|
-
private leaderIdByTopicPartition: Record<string, Record<number, number>> = {};
|
|
15
|
-
private isrNodesByTopicPartition: Record<string, Record<number, number[]>> = {};
|
|
16
|
-
|
|
17
|
-
constructor(private options: MetadataOptions) {}
|
|
18
|
-
|
|
19
|
-
public getTopicPartitionLeaderIds() {
|
|
20
|
-
return this.leaderIdByTopicPartition;
|
|
21
|
-
}
|
|
22
|
-
|
|
23
|
-
public getTopicPartitionReplicaIds() {
|
|
24
|
-
return this.isrNodesByTopicPartition;
|
|
25
|
-
}
|
|
26
|
-
|
|
27
|
-
public getTopicPartitions() {
|
|
28
|
-
return this.topicPartitions;
|
|
29
|
-
}
|
|
30
|
-
|
|
31
|
-
public getTopicIdByName(name: string) {
|
|
32
|
-
return this.topicIdByName[name];
|
|
33
|
-
}
|
|
34
|
-
|
|
35
|
-
public getTopicNameById(id: string) {
|
|
36
|
-
return this.topicNameById[id];
|
|
37
|
-
}
|
|
38
|
-
|
|
39
|
-
public async fetchMetadataIfNecessary({
|
|
40
|
-
topics,
|
|
41
|
-
allowTopicAutoCreation,
|
|
42
|
-
}: {
|
|
43
|
-
topics: string[];
|
|
44
|
-
allowTopicAutoCreation: boolean;
|
|
45
|
-
}) {
|
|
46
|
-
const missingTopics = topics.filter((topic) => !this.topicPartitions[topic]);
|
|
47
|
-
if (!missingTopics.length) {
|
|
48
|
-
return;
|
|
49
|
-
}
|
|
50
|
-
|
|
51
|
-
try {
|
|
52
|
-
return await this.fetchMetadata({ topics: missingTopics, allowTopicAutoCreation });
|
|
53
|
-
} catch (error) {
|
|
54
|
-
if (
|
|
55
|
-
error instanceof KafkaTSApiError &&
|
|
56
|
-
error.errorCode === API_ERROR.UNKNOWN_TOPIC_OR_PARTITION &&
|
|
57
|
-
allowTopicAutoCreation
|
|
58
|
-
) {
|
|
59
|
-
// TODO: investigate if we can avoid the delay
|
|
60
|
-
await delay(1000);
|
|
61
|
-
return await this.fetchMetadata({ topics: missingTopics, allowTopicAutoCreation });
|
|
62
|
-
}
|
|
63
|
-
throw error;
|
|
64
|
-
}
|
|
65
|
-
}
|
|
66
|
-
|
|
67
|
-
private async fetchMetadata({
|
|
68
|
-
topics,
|
|
69
|
-
allowTopicAutoCreation,
|
|
70
|
-
}: {
|
|
71
|
-
topics: string[] | null;
|
|
72
|
-
allowTopicAutoCreation: boolean;
|
|
73
|
-
}) {
|
|
74
|
-
const { cluster } = this.options;
|
|
75
|
-
|
|
76
|
-
const response = await cluster.sendRequest(API.METADATA, {
|
|
77
|
-
allowTopicAutoCreation,
|
|
78
|
-
includeTopicAuthorizedOperations: false,
|
|
79
|
-
topics: topics?.map((name) => ({ id: null, name })) ?? null,
|
|
80
|
-
});
|
|
81
|
-
|
|
82
|
-
this.topicPartitions = {
|
|
83
|
-
...this.topicPartitions,
|
|
84
|
-
...Object.fromEntries(
|
|
85
|
-
response.topics.map((topic) => [
|
|
86
|
-
topic.name,
|
|
87
|
-
topic.partitions.map((partition) => partition.partitionIndex),
|
|
88
|
-
]),
|
|
89
|
-
),
|
|
90
|
-
};
|
|
91
|
-
this.topicNameById = {
|
|
92
|
-
...this.topicNameById,
|
|
93
|
-
...Object.fromEntries(response.topics.map((topic) => [topic.topicId, topic.name])),
|
|
94
|
-
};
|
|
95
|
-
this.topicIdByName = {
|
|
96
|
-
...this.topicIdByName,
|
|
97
|
-
...Object.fromEntries(response.topics.map((topic) => [topic.name, topic.topicId])),
|
|
98
|
-
};
|
|
99
|
-
this.leaderIdByTopicPartition = {
|
|
100
|
-
...this.leaderIdByTopicPartition,
|
|
101
|
-
...Object.fromEntries(
|
|
102
|
-
response.topics.map((topic) => [
|
|
103
|
-
topic.name,
|
|
104
|
-
Object.fromEntries(
|
|
105
|
-
topic.partitions.map((partition) => [partition.partitionIndex, partition.leaderId]),
|
|
106
|
-
),
|
|
107
|
-
]),
|
|
108
|
-
),
|
|
109
|
-
};
|
|
110
|
-
this.isrNodesByTopicPartition = {
|
|
111
|
-
...this.isrNodesByTopicPartition,
|
|
112
|
-
...Object.fromEntries(
|
|
113
|
-
response.topics.map((topic) => [
|
|
114
|
-
topic.name,
|
|
115
|
-
Object.fromEntries(
|
|
116
|
-
topic.partitions.map((partition) => [partition.partitionIndex, partition.isrNodes]),
|
|
117
|
-
),
|
|
118
|
-
]),
|
|
119
|
-
),
|
|
120
|
-
};
|
|
121
|
-
}
|
|
122
|
-
}
|
package/src/producer/producer.ts
DELETED
|
@@ -1,132 +0,0 @@
|
|
|
1
|
-
import { API, API_ERROR } from '../api';
|
|
2
|
-
import { Cluster } from '../cluster';
|
|
3
|
-
import { distributeMessagesToTopicPartitionLeaders } from '../distributors/messages-to-topic-partition-leaders';
|
|
4
|
-
import { Metadata } from '../metadata';
|
|
5
|
-
import { Message } from '../types';
|
|
6
|
-
import { delay } from '../utils/delay';
|
|
7
|
-
import { KafkaTSApiError } from '../utils/error';
|
|
8
|
-
import { memo } from '../utils/memo';
|
|
9
|
-
|
|
10
|
-
export type ProducerOptions = {
|
|
11
|
-
allowTopicAutoCreation?: boolean;
|
|
12
|
-
};
|
|
13
|
-
|
|
14
|
-
export class Producer {
|
|
15
|
-
private options: Required<ProducerOptions>;
|
|
16
|
-
private metadata: Metadata;
|
|
17
|
-
private producerId = 0n;
|
|
18
|
-
private producerEpoch = 0;
|
|
19
|
-
private sequences: Record<string, Record<number, number>> = {};
|
|
20
|
-
|
|
21
|
-
constructor(
|
|
22
|
-
private cluster: Cluster,
|
|
23
|
-
options: ProducerOptions,
|
|
24
|
-
) {
|
|
25
|
-
this.options = {
|
|
26
|
-
...options,
|
|
27
|
-
allowTopicAutoCreation: options.allowTopicAutoCreation ?? false,
|
|
28
|
-
};
|
|
29
|
-
this.metadata = new Metadata({ cluster });
|
|
30
|
-
}
|
|
31
|
-
|
|
32
|
-
public async send(messages: Message[]) {
|
|
33
|
-
await this.ensureConnected();
|
|
34
|
-
|
|
35
|
-
const { allowTopicAutoCreation } = this.options;
|
|
36
|
-
const defaultTimestamp = BigInt(Date.now());
|
|
37
|
-
|
|
38
|
-
const topics = Array.from(new Set(messages.map((message) => message.topic)));
|
|
39
|
-
await this.metadata.fetchMetadataIfNecessary({ topics, allowTopicAutoCreation });
|
|
40
|
-
|
|
41
|
-
const nodeTopicPartitionMessages = distributeMessagesToTopicPartitionLeaders(
|
|
42
|
-
messages,
|
|
43
|
-
this.metadata.getTopicPartitionLeaderIds(),
|
|
44
|
-
);
|
|
45
|
-
|
|
46
|
-
await Promise.all(
|
|
47
|
-
Object.entries(nodeTopicPartitionMessages).map(async ([nodeId, topicPartitionMessages]) => {
|
|
48
|
-
await this.cluster.sendRequestToNode(parseInt(nodeId))(API.PRODUCE, {
|
|
49
|
-
transactionalId: null,
|
|
50
|
-
acks: 1,
|
|
51
|
-
timeoutMs: 5000,
|
|
52
|
-
topicData: Object.entries(topicPartitionMessages).map(([topic, partitionMessages]) => ({
|
|
53
|
-
name: topic,
|
|
54
|
-
partitionData: Object.entries(partitionMessages).map(([partition, messages]) => {
|
|
55
|
-
let baseTimestamp: bigint | undefined;
|
|
56
|
-
let maxTimestamp: bigint | undefined;
|
|
57
|
-
|
|
58
|
-
messages.forEach(({ timestamp = defaultTimestamp }) => {
|
|
59
|
-
if (!baseTimestamp || timestamp < baseTimestamp) {
|
|
60
|
-
baseTimestamp = timestamp;
|
|
61
|
-
}
|
|
62
|
-
if (!maxTimestamp || timestamp > maxTimestamp) {
|
|
63
|
-
maxTimestamp = timestamp;
|
|
64
|
-
}
|
|
65
|
-
});
|
|
66
|
-
|
|
67
|
-
const baseSequence = this.nextSequence(topic, parseInt(partition), messages.length);
|
|
68
|
-
return {
|
|
69
|
-
index: parseInt(partition),
|
|
70
|
-
baseOffset: 0n,
|
|
71
|
-
partitionLeaderEpoch: -1,
|
|
72
|
-
attributes: 0,
|
|
73
|
-
lastOffsetDelta: messages.length - 1,
|
|
74
|
-
baseTimestamp: baseTimestamp ?? 0n,
|
|
75
|
-
maxTimestamp: maxTimestamp ?? 0n,
|
|
76
|
-
producerId: this.producerId,
|
|
77
|
-
producerEpoch: 0,
|
|
78
|
-
baseSequence,
|
|
79
|
-
records: messages.map((message, index) => ({
|
|
80
|
-
attributes: 0,
|
|
81
|
-
timestampDelta: (message.timestamp ?? defaultTimestamp) - (baseTimestamp ?? 0n),
|
|
82
|
-
offsetDelta: index,
|
|
83
|
-
key: message.key,
|
|
84
|
-
value: message.value,
|
|
85
|
-
headers: Object.entries(message.headers ?? {}).map(([key, value]) => ({
|
|
86
|
-
key,
|
|
87
|
-
value,
|
|
88
|
-
})),
|
|
89
|
-
})),
|
|
90
|
-
};
|
|
91
|
-
}),
|
|
92
|
-
})),
|
|
93
|
-
});
|
|
94
|
-
}),
|
|
95
|
-
);
|
|
96
|
-
}
|
|
97
|
-
|
|
98
|
-
public async close() {
|
|
99
|
-
await this.cluster.disconnect();
|
|
100
|
-
}
|
|
101
|
-
|
|
102
|
-
private ensureConnected = memo(async () => {
|
|
103
|
-
await this.cluster.connect();
|
|
104
|
-
await this.initProducerId();
|
|
105
|
-
});
|
|
106
|
-
|
|
107
|
-
private async initProducerId(): Promise<void> {
|
|
108
|
-
try {
|
|
109
|
-
const result = await this.cluster.sendRequest(API.INIT_PRODUCER_ID, {
|
|
110
|
-
transactionalId: null,
|
|
111
|
-
transactionTimeoutMs: 0,
|
|
112
|
-
producerId: this.producerId,
|
|
113
|
-
producerEpoch: this.producerEpoch,
|
|
114
|
-
});
|
|
115
|
-
this.producerId = result.producerId;
|
|
116
|
-
this.producerEpoch = result.producerEpoch;
|
|
117
|
-
this.sequences = {};
|
|
118
|
-
} catch (error) {
|
|
119
|
-
if ((error as KafkaTSApiError).errorCode === API_ERROR.COORDINATOR_LOAD_IN_PROGRESS) {
|
|
120
|
-
await delay(100);
|
|
121
|
-
return this.initProducerId();
|
|
122
|
-
}
|
|
123
|
-
throw error;
|
|
124
|
-
}
|
|
125
|
-
}
|
|
126
|
-
|
|
127
|
-
private nextSequence(topic: string, partition: number, messagesCount: number) {
|
|
128
|
-
this.sequences[topic] ??= {};
|
|
129
|
-
this.sequences[topic][partition] ??= 0;
|
|
130
|
-
return (this.sequences[topic][partition] += messagesCount || 1);
|
|
131
|
-
}
|
|
132
|
-
}
|
package/src/utils/debug.ts
DELETED
|
@@ -1,9 +0,0 @@
|
|
|
1
|
-
export const serializer = (_: string, value: unknown) => (typeof value === 'bigint' ? value.toString() : value);
|
|
2
|
-
|
|
3
|
-
export const createDebugger = (module: string) => (func: string, message: string, data?: unknown) => {
|
|
4
|
-
if (!process.env.DEBUG?.includes('kafka-ts')) return;
|
|
5
|
-
console.debug(
|
|
6
|
-
`[${module}] ${func}: ${message}`,
|
|
7
|
-
data && `(${data instanceof Error ? data : JSON.stringify(data, serializer, 4)})`,
|
|
8
|
-
);
|
|
9
|
-
};
|
package/src/utils/delay.ts
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export const delay = (delayMs: number) => new Promise<void>((resolve) => setTimeout(resolve, delayMs));
|
package/src/utils/error.ts
DELETED
|
@@ -1,21 +0,0 @@
|
|
|
1
|
-
import { API_ERROR } from '../api';
|
|
2
|
-
|
|
3
|
-
export class KafkaTSError extends Error {
|
|
4
|
-
constructor(message: string) {
|
|
5
|
-
super(message);
|
|
6
|
-
this.name = this.constructor.name;
|
|
7
|
-
}
|
|
8
|
-
}
|
|
9
|
-
|
|
10
|
-
export class KafkaTSApiError<T = any> extends KafkaTSError {
|
|
11
|
-
constructor(
|
|
12
|
-
public errorCode: number,
|
|
13
|
-
public errorMessage: string | null,
|
|
14
|
-
public response: T,
|
|
15
|
-
) {
|
|
16
|
-
const [errorName] = Object.entries(API_ERROR).find(([, value]) => value === errorCode) ?? ['UNKNOWN'];
|
|
17
|
-
super(`${errorName}${errorMessage ? `: ${errorMessage}` : ''}`);
|
|
18
|
-
}
|
|
19
|
-
}
|
|
20
|
-
|
|
21
|
-
export class ConnectionError extends KafkaTSError {}
|
package/src/utils/retrier.ts
DELETED
|
@@ -1,39 +0,0 @@
|
|
|
1
|
-
import { delay } from './delay';
|
|
2
|
-
|
|
3
|
-
export type Retrier = (func: () => unknown) => Promise<void>;
|
|
4
|
-
|
|
5
|
-
export const createExponentialBackoffRetrier =
|
|
6
|
-
(options: {
|
|
7
|
-
onFailure?: (error: unknown) => Promise<void>;
|
|
8
|
-
maxRetries?: number;
|
|
9
|
-
initialDelayMs?: number;
|
|
10
|
-
maxDelayMs?: number;
|
|
11
|
-
multiplier?: number;
|
|
12
|
-
retry?: number;
|
|
13
|
-
}): Retrier =>
|
|
14
|
-
async (func) => {
|
|
15
|
-
try {
|
|
16
|
-
await func();
|
|
17
|
-
} catch (error) {
|
|
18
|
-
const {
|
|
19
|
-
retry = 0,
|
|
20
|
-
maxRetries = 3,
|
|
21
|
-
onFailure = (error) => {
|
|
22
|
-
throw error;
|
|
23
|
-
},
|
|
24
|
-
initialDelayMs = 100,
|
|
25
|
-
maxDelayMs = 3000,
|
|
26
|
-
multiplier = 2,
|
|
27
|
-
} = options;
|
|
28
|
-
|
|
29
|
-
const isMaxRetriesExceeded = retry > maxRetries;
|
|
30
|
-
if (isMaxRetriesExceeded) return onFailure(error);
|
|
31
|
-
|
|
32
|
-
const delayMs = Math.min(maxDelayMs, initialDelayMs * multiplier ** retry);
|
|
33
|
-
await delay(delayMs);
|
|
34
|
-
|
|
35
|
-
return createExponentialBackoffRetrier({ ...options, retry: retry + 1 })(func);
|
|
36
|
-
}
|
|
37
|
-
};
|
|
38
|
-
|
|
39
|
-
export const defaultRetrier = createExponentialBackoffRetrier({});
|
package/src/utils/tracer.ts
DELETED
|
@@ -1,31 +0,0 @@
|
|
|
1
|
-
import { serializer } from './debug';
|
|
2
|
-
|
|
3
|
-
export const createTracer =
|
|
4
|
-
(module: string, attributes?: Record<string, unknown>) =>
|
|
5
|
-
(fn?: (...args: any[]) => Record<string, unknown> | undefined) =>
|
|
6
|
-
(target: any, propertyKey: string, descriptor: PropertyDescriptor) => {
|
|
7
|
-
if (!process.env.DEBUG?.includes('kafka-ts')) return;
|
|
8
|
-
|
|
9
|
-
const original = descriptor.value;
|
|
10
|
-
descriptor.value = function (...args: any[]) {
|
|
11
|
-
const startTime = Date.now();
|
|
12
|
-
const metadata = fn?.(...args);
|
|
13
|
-
|
|
14
|
-
const onEnd = <T>(result: T): T => {
|
|
15
|
-
console.log(
|
|
16
|
-
`[${module}.${propertyKey}] +${Date.now() - startTime}ms ${JSON.stringify({ ...attributes, ...metadata, result }, serializer)}`,
|
|
17
|
-
);
|
|
18
|
-
return result;
|
|
19
|
-
};
|
|
20
|
-
|
|
21
|
-
const result = original.apply(this, args);
|
|
22
|
-
if (result instanceof Promise) {
|
|
23
|
-
return result.then(onEnd);
|
|
24
|
-
} else {
|
|
25
|
-
onEnd(result);
|
|
26
|
-
return result;
|
|
27
|
-
}
|
|
28
|
-
};
|
|
29
|
-
};
|
|
30
|
-
|
|
31
|
-
export const trace = createTracer('GLOBAL');
|
package/tsconfig.json
DELETED
|
@@ -1,17 +0,0 @@
|
|
|
1
|
-
{
|
|
2
|
-
"compilerOptions": {
|
|
3
|
-
"lib": ["es2023"],
|
|
4
|
-
"target": "es2022",
|
|
5
|
-
"module": "node16",
|
|
6
|
-
"strict": true,
|
|
7
|
-
"forceConsistentCasingInFileNames": true,
|
|
8
|
-
"esModuleInterop": true,
|
|
9
|
-
"skipLibCheck": true,
|
|
10
|
-
"moduleResolution": "node16",
|
|
11
|
-
"outDir": "dist",
|
|
12
|
-
"declaration": true,
|
|
13
|
-
"emitDecoratorMetadata": true,
|
|
14
|
-
"experimentalDecorators": true
|
|
15
|
-
},
|
|
16
|
-
"include": ["src/**/*"]
|
|
17
|
-
}
|