|
1 | 1 | from __future__ import absolute_import |
2 | 2 |
|
3 | 3 | import collections |
| 4 | +import itertools |
4 | 5 | import logging |
5 | 6 |
|
6 | 7 | from kafka.vendor import six |
@@ -34,31 +35,35 @@ class RangePartitionAssignor(AbstractPartitionAssignor): |
34 | 35 | @classmethod |
35 | 36 | def assign(cls, cluster, group_subscriptions): |
36 | 37 | consumers_per_topic = collections.defaultdict(list) |
37 | | - for member, subscription in six.iteritems(group_subscriptions): |
| 38 | + for member_id, subscription in six.iteritems(group_subscriptions): |
38 | 39 | for topic in subscription.topics: |
39 | | - consumers_per_topic[topic].append(member) |
| 40 | + consumers_per_topic[topic].append((subscription.group_instance_id, member_id)) |
40 | 41 |
|
41 | 42 | # construct {member_id: {topic: [partition, ...]}} |
42 | 43 | assignment = collections.defaultdict(dict) |
43 | 44 |
|
| 45 | + for topic in consumers_per_topic: |
| 46 | + # group by static members (True) v dynamic members (False) |
| 47 | + grouped = {k: list(g) for k, g in itertools.groupby(consumers_per_topic[topic], key=lambda ids: ids[0] is not None)} |
| 48 | + consumers_per_topic[topic] = sorted(grouped.get(True, [])) + sorted(grouped.get(False, [])) # sorted static members first, then sorted dynamic |
| 49 | + |
44 | 50 | for topic, consumers_for_topic in six.iteritems(consumers_per_topic): |
45 | 51 | partitions = cluster.partitions_for_topic(topic) |
46 | 52 | if partitions is None: |
47 | 53 | log.warning('No partition metadata for topic %s', topic) |
48 | 54 | continue |
49 | 55 | partitions = sorted(partitions) |
50 | | - consumers_for_topic.sort() |
51 | 56 |
|
52 | 57 | partitions_per_consumer = len(partitions) // len(consumers_for_topic) |
53 | 58 | consumers_with_extra = len(partitions) % len(consumers_for_topic) |
54 | 59 |
|
55 | | - for i, member in enumerate(consumers_for_topic): |
| 60 | + for i, (_group_instance_id, member_id) in enumerate(consumers_for_topic): |
56 | 61 | start = partitions_per_consumer * i |
57 | 62 | start += min(i, consumers_with_extra) |
58 | 63 | length = partitions_per_consumer |
59 | 64 | if not i + 1 > consumers_with_extra: |
60 | 65 | length += 1 |
61 | | - assignment[member][topic] = partitions[start:start+length] |
| 66 | + assignment[member_id][topic] = partitions[start:start+length] |
62 | 67 |
|
63 | 68 | protocol_assignment = {} |
64 | 69 | for member_id in group_subscriptions: |
|
0 commit comments