|
| 1 | + |
1 | 2 | from __future__ import absolute_import
|
2 | 3 |
|
3 | 4 | import copy
|
4 | 5 | import logging
|
5 | 6 | import socket
|
6 | 7 | from kafka.client_async import KafkaClient, selectors
|
| 8 | +import kafka.errors as Errors |
7 | 9 | from kafka.errors import (
|
8 | 10 | IncompatibleBrokerVersion, KafkaConfigurationError, KafkaConnectionError,
|
9 | 11 | NodeNotReadyError, NotControllerError)
|
@@ -487,18 +489,53 @@ def describe_consumer_groups(self, group_ids):
|
487 | 489 | .format(version))
|
488 | 490 | return self._send(request)
|
489 | 491 |
|
490 |
| - def list_consumer_groups(self): |
| 492 | + def list_consumer_groups(self, broker_ids=None): |
491 | 493 | """List all consumer groups known to the cluster.
|
492 | 494 |
|
493 |
| - :return: Appropriate version of ListGroupsResponse class |
| 495 | + This returns a list of Consumer Group tuples. The tuples are |
| 496 | + composed of the consumer group name and the consumer group protocol |
| 497 | + type. |
| 498 | +
|
| 499 | + Only consumer groups that store their offsets in Kafka are returned. |
| 500 | + The protocol type will be an empty string for groups created using |
| 501 | + Kafka < 0.9 APIs because, although they store their offsets in Kafka, |
| 502 | + they don't use Kafka for group coordination. For groups created using |
| 503 | + Kafka >= 0.9, the protocol type will typically be "consumer". |
| 504 | +
|
| 505 | + As soon as any error is encountered, it is immediately raised. |
| 506 | +
|
| 507 | + :param broker_ids: A list of broker node_ids to query for consumer |
| 508 | + groups. If set to None, will query all brokers in the cluster. |
| 509 | + Explicitly specifying broker(s) can be useful for determining which |
| 510 | + consumer groups are coordinated by those broker(s). Default: None |
| 511 | + :return list: List of tuples of Consumer Groups. |
| 512 | + :exception GroupCoordinatorNotAvailableError: The coordinator is not |
| 513 | + available, so cannot process requests. |
| 514 | + :exception GroupLoadInProgressError: The coordinator is loading and |
| 515 | + hence can't process requests. |
494 | 516 | """
|
| 517 | + # While we return a list, internally use a set to prevent duplicates |
| 518 | + # because if a group coordinator fails after being queried, and its |
| 519 | + # consumer groups move to new brokers that haven't yet been queried, |
| 520 | + # then the same group could be returned by multiple brokers. |
| 521 | + consumer_groups = set() |
| 522 | + if broker_ids is None: |
| 523 | + broker_ids = [broker.nodeId for broker in self._client.cluster.brokers()] |
495 | 524 | version = self._matching_api_version(ListGroupsRequest)
|
496 |
| - if version <= 1: |
| 525 | + if version <= 2: |
497 | 526 | request = ListGroupsRequest[version]()
|
| 527 | + for broker_id in broker_ids: |
| 528 | + response = self._send_request_to_node(broker_id, request) |
| 529 | + error_type = Errors.for_code(response.error_code) |
| 530 | + if error_type is not Errors.NoError: |
| 531 | + raise error_type( |
| 532 | + "Request '{}' failed with response '{}'." |
| 533 | + .format(request, response)) |
| 534 | + consumer_groups.update(response.groups) |
498 | 535 | else:
|
499 | 536 | raise NotImplementedError(
|
500 | 537 | "Support for ListGroups v{} has not yet been added to KafkaAdmin."
|
501 | 538 | .format(version))
|
502 |
| - return self._send(request) |
| 539 | + return list(consumer_groups) |
503 | 540 |
|
504 | 541 | # delete groups protocol not implemented
|
0 commit comments