@platformatic/kafka 1.18.0 → 1.20.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.
@@ -364,18 +364,22 @@ export class Admin extends Base {
364
364
  };
365
365
  for (const member of raw.members) {
366
366
  const reader = Reader.from(member.memberMetadata);
367
- const memberMetadata = {
368
- version: reader.readInt16(),
369
- topics: reader.readArray(r => r.readString(false), false, false),
370
- metadata: reader.readBytes(false)
371
- };
372
- reader.reset(member.memberAssignment);
373
- reader.skip(2); // Ignore Version information
374
- const memberAssignments = reader.readMap(r => {
375
- const topic = r.readString(false);
376
- return [topic, { topic, partitions: reader.readArray(r => r.readInt32(), false, false) }];
377
- }, false, false);
378
- reader.readBytes(); // Ignore the user data
367
+ let memberMetadata;
368
+ let memberAssignments;
369
+ if (reader.remaining > 0) {
370
+ memberMetadata = {
371
+ version: reader.readInt16(),
372
+ topics: reader.readArray(r => r.readString(false), false, false),
373
+ metadata: reader.readBytes(false)
374
+ };
375
+ reader.reset(member.memberAssignment);
376
+ reader.skip(2); // Ignore Version information
377
+ memberAssignments = reader.readMap(r => {
378
+ const topic = r.readString(false);
379
+ return [topic, { topic, partitions: reader.readArray(r => r.readInt32(), false, false) }];
380
+ }, false, false);
381
+ reader.readBytes(); // Ignore the user data
382
+ }
379
383
  group.members.set(member.memberId, {
380
384
  id: member.memberId,
381
385
  groupInstanceId: member.groupInstanceId,
@@ -1,7 +1,7 @@
1
1
  import { type AlterClientQuotasRequestEntry } from '../../apis/admin/alter-client-quotas-v1.ts';
2
- import { type DescribeClientQuotasRequestComponent } from '../../apis/admin/describe-client-quotas-v0.ts';
3
- import { type DescribeLogDirsResponse, type DescribeLogDirsResponseResult, type DescribeLogDirsRequestTopic } from '../../apis/admin/describe-log-dirs-v4.ts';
4
2
  import { type CreateTopicsRequestTopicConfig } from '../../apis/admin/create-topics-v7.ts';
3
+ import { type DescribeClientQuotasRequestComponent } from '../../apis/admin/describe-client-quotas-v0.ts';
4
+ import { type DescribeLogDirsRequestTopic, type DescribeLogDirsResponse, type DescribeLogDirsResponseResult } from '../../apis/admin/describe-log-dirs-v4.ts';
5
5
  import { type ConsumerGroupState } from '../../apis/enumerations.ts';
6
6
  import { type NullableString } from '../../protocol/definitions.ts';
7
7
  import { type BaseOptions } from '../base/types.ts';
@@ -22,8 +22,8 @@ export interface GroupMember {
22
22
  groupInstanceId: NullableString;
23
23
  clientId: string;
24
24
  clientHost: string;
25
- metadata: Omit<ExtendedGroupProtocolSubscription, 'memberId'>;
26
- assignments: Map<string, GroupAssignment>;
25
+ metadata?: Omit<ExtendedGroupProtocolSubscription, 'memberId'>;
26
+ assignments?: Map<string, GroupAssignment>;
27
27
  }
28
28
  export interface GroupBase {
29
29
  id: string;
@@ -271,7 +271,7 @@ export class Consumer extends Base {
271
271
  // Now gather the last committed offsets from each stream
272
272
  const committeds = new Map();
273
273
  for (const stream of this.#streams) {
274
- for (const [topic, offset] of stream.committedOffsets) {
274
+ for (const [topic, offset] of stream.offsetsCommitted) {
275
275
  committeds.set(topic, offset);
276
276
  }
277
277
  }
@@ -448,13 +448,17 @@ export class Consumer extends Base {
448
448
  });
449
449
  }
450
450
  #listOffsets(withTimestamps, options, callback) {
451
- this[kMetadata]({ topics: options.topics }, (error, metadata) => {
451
+ let topics = options.topics;
452
+ if (!topics || topics.length === 0) {
453
+ topics = this.topics.current;
454
+ }
455
+ this[kMetadata]({ topics }, (error, metadata) => {
452
456
  if (error) {
453
457
  callback(error, undefined);
454
458
  return;
455
459
  }
456
460
  const requests = new Map();
457
- for (const name of options.topics) {
461
+ for (const name of topics) {
458
462
  const topic = metadata.topics.get(name);
459
463
  const toInclude = new Set(options.partitions?.[name] ?? []);
460
464
  const hasPartitionsFilter = toInclude.size > 0;
@@ -11,6 +11,9 @@ export declare class MessagesStream<Key, Value, HeaderKey, HeaderValue> extends
11
11
  #private;
12
12
  [kInstance]: number;
13
13
  constructor(consumer: Consumer<Key, Value, HeaderKey, HeaderValue>, options: ConsumeOptions<Key, Value, HeaderKey, HeaderValue>);
14
+ get offsetsToFetch(): Map<string, bigint>;
15
+ get offsetsToCommit(): Map<string, CommitOptionsPartition>;
16
+ get offsetsCommitted(): Map<string, bigint>;
14
17
  get committedOffsets(): Map<string, bigint>;
15
18
  close(callback: CallbackWithPromise<void>): void;
16
19
  close(): Promise<void>;
@@ -20,6 +23,7 @@ export declare class MessagesStream<Key, Value, HeaderKey, HeaderValue> extends
20
23
  pause(): this;
21
24
  addListener(event: 'autocommit', listener: (err: Error, offsets: CommitOptionsPartition[]) => void): this;
22
25
  addListener(event: 'fetch', listener: () => void): this;
26
+ addListener(event: 'offsets', listener: () => void): this;
23
27
  addListener(event: 'data', listener: (message: Message<Key, Value, HeaderKey, HeaderValue>) => void): this;
24
28
  addListener(event: 'close', listener: () => void): this;
25
29
  addListener(event: 'end', listener: () => void): this;
@@ -29,6 +33,7 @@ export declare class MessagesStream<Key, Value, HeaderKey, HeaderValue> extends
29
33
  addListener(event: 'resume', listener: () => void): this;
30
34
  on(event: 'autocommit', listener: (err: Error, offsets: CommitOptionsPartition[]) => void): this;
31
35
  on(event: 'fetch', listener: () => void): this;
36
+ on(event: 'offsets', listener: () => void): this;
32
37
  on(event: 'data', listener: (message: Message<Key, Value, HeaderKey, HeaderValue>) => void): this;
33
38
  on(event: 'close', listener: () => void): this;
34
39
  on(event: 'end', listener: () => void): this;
@@ -38,6 +43,7 @@ export declare class MessagesStream<Key, Value, HeaderKey, HeaderValue> extends
38
43
  on(event: 'resume', listener: () => void): this;
39
44
  once(event: 'autocommit', listener: (err: Error, offsets: CommitOptionsPartition[]) => void): this;
40
45
  once(event: 'fetch', listener: () => void): this;
46
+ once(event: 'offsets', listener: () => void): this;
41
47
  once(event: 'data', listener: (message: Message<Key, Value, HeaderKey, HeaderValue>) => void): this;
42
48
  once(event: 'close', listener: () => void): this;
43
49
  once(event: 'end', listener: () => void): this;
@@ -47,6 +53,7 @@ export declare class MessagesStream<Key, Value, HeaderKey, HeaderValue> extends
47
53
  once(event: 'resume', listener: () => void): this;
48
54
  prependListener(event: 'autocommit', listener: (err: Error, offsets: CommitOptionsPartition[]) => void): this;
49
55
  prependListener(event: 'fetch', listener: () => void): this;
56
+ prependListener(event: 'offsets', listener: () => void): this;
50
57
  prependListener(event: 'data', listener: (message: Message<Key, Value, HeaderKey, HeaderValue>) => void): this;
51
58
  prependListener(event: 'close', listener: () => void): this;
52
59
  prependListener(event: 'end', listener: () => void): this;
@@ -56,6 +63,7 @@ export declare class MessagesStream<Key, Value, HeaderKey, HeaderValue> extends
56
63
  prependListener(event: 'resume', listener: () => void): this;
57
64
  prependOnceListener(event: 'autocommit', listener: (err: Error, offsets: CommitOptionsPartition[]) => void): this;
58
65
  prependOnceListener(event: 'fetch', listener: () => void): this;
66
+ prependOnceListener(event: 'offsets', listener: () => void): this;
59
67
  prependOnceListener(event: 'data', listener: (message: Message<Key, Value, HeaderKey, HeaderValue>) => void): this;
60
68
  prependOnceListener(event: 'close', listener: () => void): this;
61
69
  prependOnceListener(event: 'end', listener: () => void): this;
@@ -98,6 +98,7 @@ export class MessagesStream extends Readable {
98
98
  // will have changed so we may have gone from last with no assignments to
99
99
  // having some.
100
100
  this.#consumer.on('consumer:group:join', () => {
101
+ this.#offsetsCommitted.clear();
101
102
  this.#refreshOffsets((error) => {
102
103
  /* c8 ignore next 4 - Hard to test */
103
104
  if (error) {
@@ -112,6 +113,16 @@ export class MessagesStream extends Readable {
112
113
  }
113
114
  notifyCreation('messages-stream', this);
114
115
  }
116
+ get offsetsToFetch() {
117
+ return this.#offsetsToFetch;
118
+ }
119
+ get offsetsToCommit() {
120
+ return this.#offsetsToCommit;
121
+ }
122
+ get offsetsCommitted() {
123
+ return this.#offsetsCommitted;
124
+ }
125
+ // TODO: This is deprecated alias, remove in future major version
115
126
  get committedOffsets() {
116
127
  return this.#offsetsCommitted;
117
128
  }
@@ -525,6 +536,20 @@ export class MessagesStream extends Readable {
525
536
  }
526
537
  }
527
538
  }
539
+ // Rebuild the list of offsetsCommitted (which is used for consumer lag) out of the offsets to fetch
540
+ for (const topic of this.#topics) {
541
+ const assignment = this.#assignmentsForTopic(topic);
542
+ // This consumer has no assignment for the topic, continue
543
+ if (!assignment) {
544
+ continue;
545
+ }
546
+ const partitions = assignment.partitions;
547
+ for (const partition of partitions) {
548
+ const committed = this.#offsetsToFetch.get(`${topic}:${partition}`);
549
+ this.#offsetsCommitted.set(`${topic}:${partition}`, committed - 1n);
550
+ }
551
+ }
552
+ this.emit('offsets');
528
553
  callback(null);
529
554
  }
530
555
  #assignmentsForTopic(topic) {
package/dist/version.js CHANGED
@@ -1,2 +1,2 @@
1
1
  export const name = "@platformatic/kafka";
2
- export const version = "1.18.0";
2
+ export const version = "1.20.0";
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@platformatic/kafka",
3
- "version": "1.18.0",
3
+ "version": "1.20.0",
4
4
  "description": "Modern and performant client for Apache Kafka",
5
5
  "homepage": "https://github.com/platformatic/kafka",
6
6
  "author": "Platformatic Inc. <oss@platformatic.dev> (https://platformatic.dev)",