kazoo-ruby 0.2.0 → 0.3.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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 87213b930132989503c56e226e6755b8c2f51559
4
- data.tar.gz: 5c62c5a979ad421634272a4839b746777ed63cc6
3
+ metadata.gz: 129a9f807dc2c4a376d8941c64f25c652427fac1
4
+ data.tar.gz: 1f3ea8b05527feaef6b5b6fce8d7ff8eff19f987
5
5
  SHA512:
6
- metadata.gz: d3a2b95c9e360fdf62c98a68ef752b220e35ddd4d9f8e05081a4eb95176a6e08d753125c47354a98ad171490458d3596199adf8eaea0edfa4768203c244302ab
7
- data.tar.gz: e5af8de385e6946a53aa4a276c2708fb772d611cbf6afb99135c8af4c8f3a61969a52baf9c9fca8ea1f75b70c8c602689ec00024b163b748702b4e7411f47dbf
6
+ metadata.gz: eb6a831e906561296e5c8cb07116a470f4a612ad16b4d92d21d7b64bc3b58d01abf05f10486a4f8d2983b9afd4c1f340fc763bbdd3849dcd935f05675a3702d0
7
+ data.tar.gz: 560c455ec3ae69a0d2cfcb7f955fec90e4a26eaef79f636632fa40784745537368347ada6f028074a30585760a29bcaf14d3b80d1fce20503846d318820e4f6c
data/lib/kazoo/cli.rb CHANGED
@@ -1,155 +1,20 @@
1
1
  require 'kazoo'
2
2
  require 'thor'
3
3
 
4
+ require 'kazoo/cli/common'
5
+ require 'kazoo/cli/cluster'
6
+ require 'kazoo/cli/consumers'
7
+ require 'kazoo/cli/topics'
8
+
4
9
  module Kazoo
5
10
  class CLI < Thor
6
- class_option :zookeeper, type: :string, default: ENV['ZOOKEEPER']
7
-
8
- desc "cluster", "Describes the Kafka cluster as registered in Zookeeper"
9
- def cluster
10
- validate_class_options!
11
-
12
- kafka_cluster.brokers.values.sort_by(&:id).each do |broker|
13
- $stdout.puts "#{broker.id}:\t#{broker.addr}\t(hosts #{broker.replicated_partitions.length} partitions, leads #{broker.led_partitions.length})"
14
- end
15
- end
16
-
17
- desc "topics", "Lists all topics in the cluster"
18
- def topics
19
- validate_class_options!
20
-
21
- kafka_cluster.topics.values.sort_by(&:name).each do |topic|
22
- $stdout.puts topic.name
23
- end
24
- end
25
-
26
- desc "create_topic", "Creates a new topic"
27
- option :name, type: :string, required: true
28
- option :partitions, type: :numeric, required: true
29
- option :replication_factor, type: :numeric, required: true
30
- def create_topic
31
- validate_class_options!
32
-
33
- kafka_cluster.create_topic(options[:name], partitions: options[:partitions], replication_factor: options[:replication_factor])
34
- end
35
-
36
- desc "delete_topic", "Removes a topic"
37
- option :name, type: :string, required: true
38
- def delete_topic
39
- validate_class_options!
40
-
41
- kafka_cluster.topics.fetch(options[:name]).destroy
42
- end
43
-
44
- option :topic, type: :string
45
- desc "partitions", "Lists partitions"
46
- def partitions
47
- validate_class_options!
48
-
49
- topics = kafka_cluster.topics.values
50
- topics.select! { |t| t.name == options[:topic] } if options[:topic]
51
- topics.sort_by!(&:name)
52
-
53
- topics.each do |topic|
54
- topic.partitions.each do |partition|
55
- $stdout.puts "#{partition.topic.name}/#{partition.id}\tReplicas: #{partition.replicas.map(&:id).join(",")}"
56
- end
57
- end
58
- end
59
-
60
- option :replicas, type: :numeric, default: 1
61
- desc "critical <broker>", "Determine whether a broker is critical"
62
- def critical(broker_name)
63
- validate_class_options!
64
-
65
- if broker(broker_name).critical?(replicas: options[:replicas])
66
- raise Thor::Error, "WARNING: broker #{broker_name} is critical and cannot be stopped safely!"
67
- else
68
- $stdout.puts "Broker #{broker_name} is non-critical and can be stopped safely."
69
- end
70
- end
71
-
72
-
73
- desc "consumergroups", "Lists the consumergroups registered for this Kafka cluster"
74
- def consumergroups
75
- validate_class_options!
76
-
77
- kafka_cluster.consumergroups.each do |group|
78
- instances = group.instances
79
- if instances.length == 0
80
- puts "- #{group.name}: inactive"
81
- else
82
- puts "- #{group.name}: #{instances.length} running instances"
83
- end
84
- end
85
- end
86
-
87
- desc "consumergroup", "Prints information about a consumer group"
88
- option :name, type: :string, required: true
89
- def consumergroup
90
- validate_class_options!
91
-
92
- cg = kafka_cluster.consumergroup(options[:name])
93
- raise Kazoo::Error, "Consumergroup #{options[:name]} is not registered in Zookeeper" unless cg.exists?
94
-
95
- puts "Consumer group: #{cg.name}\n"
96
-
97
- if cg.active?
98
- puts "Running instances:"
99
- cg.instances.each do |instance|
100
- puts "- #{instance.id}"
101
- end
102
- else
103
- puts "This consumer group is inactive."
104
- end
105
- end
106
-
107
- desc "delete_consumergroup", "Removes a consumer group from Zookeeper"
108
- option :name, type: :string, required: true
109
- def delete_consumergroup
110
- validate_class_options!
111
-
112
- cg = kafka_cluster.consumergroup(options[:name])
113
- raise Kazoo::Error, "Consumergroup #{options[:name]} is not registered in Zookeeper" unless cg.exists?
114
- raise Kazoo::Error, "Cannot remove consumergroup #{cg.name} because it's still active" if cg.active?
115
-
116
- cg.destroy
117
- end
118
-
119
- desc "reset_consumergroup", "Resets all the offsets stored for a consumergroup"
120
- option :name, type: :string, required: true
121
- def reset_consumergroup
122
- validate_class_options!
123
-
124
- cg = kafka_cluster.consumergroup(options[:name])
125
- raise Kazoo::Error, "Consumergroup #{options[:name]} is not registered in Zookeeper" unless cg.exists?
126
- raise Kazoo::Error, "Cannot remove consumergroup #{cg.name} because it's still active" if cg.active?
127
-
128
- cg.reset_all_offsets
129
- end
130
-
131
-
132
- private
133
-
134
- def validate_class_options!
135
- if options[:zookeeper].nil? || options[:zookeeper] == ''
136
- raise Thor::InvocationError, "Please supply --zookeeper argument, or set the ZOOKEEPER environment variable"
137
- end
138
- end
139
-
140
- def broker(name_or_id)
141
- broker = if name_or_id =~ /\A\d+\z/
142
- kafka_cluster.brokers[name_or_id.to_i]
143
- else
144
- kafka_cluster.brokers.values.detect { |b| b.addr == name_or_id } || cluster.brokers.values.detect { |b| b.host == name_or_id }
145
- end
11
+ desc "cluster SUBCOMMAND ...ARGS", "Inspect the Kafka cluster"
12
+ subcommand "cluster", Kazoo::CLI::Cluster
146
13
 
147
- raise Thor::InvocationError, "Broker #{name_or_id.inspect} not found!" if broker.nil?
148
- broker
149
- end
14
+ desc "topics SUBCOMMAND ...ARGS", "Manage consumer groups"
15
+ subcommand "topics", Kazoo::CLI::Topics
150
16
 
151
- def kafka_cluster
152
- @kafka_cluster ||= Kazoo::Cluster.new(options[:zookeeper])
153
- end
17
+ desc "consumers SUBCOMMAND ...ARGS", "Manage consumer groups"
18
+ subcommand "consumers", Kazoo::CLI::Consumers
154
19
  end
155
20
  end
@@ -0,0 +1,28 @@
1
+ module Kazoo
2
+ class CLI < Thor
3
+ class Cluster < Thor
4
+ include Kazoo::CLI::Common
5
+
6
+ desc "brokers", "Describes the brokers in the cluster as registered in Zookeeper"
7
+ def brokers
8
+ validate_class_options!
9
+
10
+ kafka_cluster.brokers.values.sort_by(&:id).each do |broker|
11
+ $stdout.puts "#{broker.id}:\t#{broker.addr}\t(hosts #{broker.replicated_partitions.length} partitions, leads #{broker.led_partitions.length})"
12
+ end
13
+ end
14
+
15
+ option :replicas, type: :numeric, default: 1
16
+ desc "critical BROKER", "Determine whether a broker is critical"
17
+ def critical(broker_name)
18
+ validate_class_options!
19
+
20
+ if broker(broker_name).critical?(replicas: options[:replicas])
21
+ raise Thor::Error, "WARNING: broker #{broker_name} is critical and cannot be stopped safely!"
22
+ else
23
+ $stdout.puts "Broker #{broker_name} is non-critical and can be stopped safely."
24
+ end
25
+ end
26
+ end
27
+ end
28
+ end
@@ -0,0 +1,32 @@
1
+ module Kazoo
2
+ class CLI < Thor
3
+ module Common
4
+ def self.included(base)
5
+ base.class_option :zookeeper, type: :string, default: ENV['ZOOKEEPER']
6
+ end
7
+
8
+ private
9
+
10
+ def validate_class_options!
11
+ if options[:zookeeper].nil? || options[:zookeeper] == ''
12
+ raise Thor::InvocationError, "Please supply --zookeeper argument, or set the ZOOKEEPER environment variable"
13
+ end
14
+ end
15
+
16
+ def broker(name_or_id)
17
+ broker = if name_or_id =~ /\A\d+\z/
18
+ kafka_cluster.brokers[name_or_id.to_i]
19
+ else
20
+ kafka_cluster.brokers.values.detect { |b| b.addr == name_or_id } || kafka_cluster.brokers.values.detect { |b| b.host == name_or_id }
21
+ end
22
+
23
+ raise Thor::InvocationError, "Broker #{name_or_id.inspect} not found!" if broker.nil?
24
+ broker
25
+ end
26
+
27
+ def kafka_cluster
28
+ @kafka_cluster ||= Kazoo::Cluster.new(options[:zookeeper])
29
+ end
30
+ end
31
+ end
32
+ end
@@ -0,0 +1,94 @@
1
+ module Kazoo
2
+ class CLI < Thor
3
+ class Consumers < Thor
4
+ include Kazoo::CLI::Common
5
+
6
+ desc "list", "Lists the consumergroups registered for this Kafka cluster"
7
+ def list
8
+ validate_class_options!
9
+
10
+ kafka_cluster.consumergroups.sort_by(&:name).each do |group|
11
+ instances = group.instances
12
+ if instances.length == 0
13
+ puts "- #{group.name}: inactive"
14
+ else
15
+ puts "- #{group.name}: #{instances.length} running instances"
16
+ end
17
+ end
18
+ end
19
+
20
+ desc "show NAME", "Prints information about a consumer group"
21
+ def show(name)
22
+ validate_class_options!
23
+
24
+ cg = kafka_cluster.consumergroup(name)
25
+ raise Kazoo::Error, "Consumergroup #{cg.name} is not registered in Zookeeper" unless cg.exists?
26
+
27
+ topics = cg.topics.sort_by(&:name)
28
+
29
+ puts "Consumer name: #{cg.name}"
30
+ puts "Created on: #{cg.created_at}"
31
+ puts "Topics (#{topics.length}): #{topics.map(&:name).join(', ')}"
32
+
33
+ instances = cg.instances
34
+ if instances.length > 0
35
+
36
+ puts
37
+ puts "Running instances (#{instances.length}):"
38
+ instances.each do |instance|
39
+ puts "- #{instance.id}\t(created on #{instance.created_at})"
40
+ end
41
+
42
+ partition_claims = cg.partition_claims
43
+ if partition_claims.length > 0
44
+ partitions = partition_claims.keys.sort_by { |p| [p.topic.name, p.id] }
45
+
46
+ puts
47
+ puts "Partition claims (#{partition_claims.length}):"
48
+ partitions.each do |partition|
49
+ instance = partition_claims[partition]
50
+ puts "- #{partition.key}: #{instance.id}"
51
+ end
52
+ else
53
+ puts
54
+ puts "WARNING: this consumer group is active but hasn't claimed any partitions"
55
+ end
56
+
57
+ unclaimed_partitions = (cg.partitions - partition_claims.keys).sort_by { |p| [p.topic.name, p.id] }
58
+
59
+ if unclaimed_partitions.length > 0
60
+ puts
61
+ puts "WARNING: this consumergroup has #{unclaimed_partitions.length} unclaimed partitions:"
62
+ unclaimed_partitions.each do |partition|
63
+ puts "- #{partition.key}"
64
+ end
65
+ end
66
+ else
67
+ puts "This consumer group is inactive."
68
+ end
69
+ end
70
+
71
+ desc "delete NAME", "Removes a consumer group from Zookeeper"
72
+ def delete(name)
73
+ validate_class_options!
74
+
75
+ cg = kafka_cluster.consumergroup(name)
76
+ raise Kazoo::Error, "Consumergroup #{cg.name} is not registered in Zookeeper" unless cg.exists?
77
+ raise Kazoo::Error, "Cannot remove consumergroup #{cg.name} because it's still active" if cg.active?
78
+
79
+ cg.destroy
80
+ end
81
+
82
+ desc "reset [NAME]", "Resets all the offsets stored for a consumergroup"
83
+ def reset(name)
84
+ validate_class_options!
85
+
86
+ cg = kafka_cluster.consumergroup(name)
87
+ raise Kazoo::Error, "Consumergroup #{cg.name} is not registered in Zookeeper" unless cg.exists?
88
+ raise Kazoo::Error, "Cannot remove consumergroup #{cg.name} because it's still active" if cg.active?
89
+
90
+ cg.reset_all_offsets
91
+ end
92
+ end
93
+ end
94
+ end
@@ -0,0 +1,43 @@
1
+ module Kazoo
2
+ class CLI < Thor
3
+ class Topics < Thor
4
+ include Kazoo::CLI::Common
5
+
6
+ desc "list", "Lists all topics in the cluster"
7
+ def list
8
+ validate_class_options!
9
+
10
+ kafka_cluster.topics.values.sort_by(&:name).each do |topic|
11
+ $stdout.puts topic.name
12
+ end
13
+ end
14
+
15
+ desc "create TOPIC", "Creates a new topic"
16
+ option :partitions, type: :numeric, required: true
17
+ option :replication_factor, type: :numeric, required: true
18
+ def create(name)
19
+ validate_class_options!
20
+
21
+ kafka_cluster.create_topic(name, partitions: options[:partitions], replication_factor: options[:replication_factor])
22
+ end
23
+
24
+ desc "delete TOPIC", "Removes a topic"
25
+ def delete(name)
26
+ validate_class_options!
27
+
28
+ kafka_cluster.topics.fetch(name).destroy
29
+ end
30
+
31
+ option :topic, type: :string
32
+ desc "partitions TOPIC", "Lists partitions for a topic"
33
+ def partitions(topic)
34
+ validate_class_options!
35
+
36
+ topic = kafka_cluster.topics.fetch(topic)
37
+ topic.partitions.each do |partition|
38
+ puts "#{partition.key}\tReplicas: #{partition.replicas.map(&:id).join(",")}\tISR: #{partition.isr.map(&:id).join(",")}"
39
+ end
40
+ end
41
+ end
42
+ end
43
+ end
@@ -20,6 +20,13 @@ module Kazoo
20
20
  stat.fetch(:stat).exists?
21
21
  end
22
22
 
23
+ def created_at
24
+ result = cluster.zk.stat(path: "/consumers/#{name}")
25
+ raise Kazoo::Error, "Failed to get consumer details. Error code: #{result.fetch(:rc)}" if result.fetch(:rc) != Zookeeper::Constants::ZOK
26
+
27
+ Time.at(result.fetch(:stat).mtime / 1000.0)
28
+ end
29
+
23
30
 
24
31
  def instantiate(id: nil)
25
32
  Instance.new(self, id: id)
@@ -69,31 +76,88 @@ module Kazoo
69
76
  end
70
77
  end
71
78
 
79
+ def topics
80
+ topic_result = cluster.zk.get_children(path: "/consumers/#{name}/owners")
81
+ case topic_result.fetch(:rc)
82
+ when Zookeeper::Constants::ZOK
83
+ topic_result.fetch(:children).map { |topic_name| cluster.topic(topic_name) }
84
+ when Zookeeper::Constants::ZNONODE
85
+ []
86
+ else
87
+ raise Kazoo::Error, "Failed to get subscribed topics. Result code: #{topic_result.fetch(:rc)}"
88
+ end
89
+ end
90
+
91
+ def partitions
92
+ partitions, threads, mutex = [], [], Mutex.new
93
+ topics.each do |topic|
94
+ threads << Thread.new do
95
+ topic_partitions = topic.partitions
96
+ mutex.synchronize { partitions.concat(topic_partitions) }
97
+ end
98
+ end
99
+
100
+ threads.each(&:join)
101
+ return partitions
102
+ end
103
+
104
+ def unclaimed_partitions
105
+ partitions - partition_claims.keys
106
+ end
107
+
108
+ def partition_claims
109
+ topic_result = cluster.zk.get_children(path: "/consumers/#{name}/owners")
110
+ case topic_result.fetch(:rc)
111
+ when Zookeeper::Constants::ZOK; # continue
112
+ when Zookeeper::Constants::ZNONODE; return {}
113
+ else raise Kazoo::Error, "Failed to get partition claims. Result code: #{topic_result.fetch(:rc)}"
114
+ end
115
+
116
+ partition_claims, threads, mutex = {}, [], Mutex.new
117
+ topic_result.fetch(:children).each do |topic_name|
118
+ threads << Thread.new do
119
+ topic = cluster.topic(topic_name)
120
+
121
+ partition_result = cluster.zk.get_children(path: "/consumers/#{name}/owners/#{topic.name}")
122
+ raise Kazoo::Error, "Failed to get partition claims. Result code: #{partition_result.fetch(:rc)}" if partition_result.fetch(:rc) != Zookeeper::Constants::ZOK
123
+
124
+ partition_threads = []
125
+ partition_result.fetch(:children).each do |partition_id|
126
+ partition_threads << Thread.new do
127
+ partition = topic.partition(partition_id.to_i)
128
+
129
+ claim_result =cluster.zk.get(path: "/consumers/#{name}/owners/#{topic.name}/#{partition.id}")
130
+ raise Kazoo::Error, "Failed to get partition claims. Result code: #{claim_result.fetch(:rc)}" if claim_result.fetch(:rc) != Zookeeper::Constants::ZOK
131
+
132
+ mutex.synchronize { partition_claims[partition] = instantiate(id: claim_result.fetch(:data)) }
133
+ end
134
+ end
135
+ partition_threads.each(&:join)
136
+ end
137
+ end
138
+
139
+ threads.each(&:join)
140
+ return partition_claims
141
+ end
142
+
72
143
  def retrieve_offset(partition)
73
144
  result = cluster.zk.get(path: "/consumers/#{name}/offsets/#{partition.topic.name}/#{partition.id}")
74
145
  case result.fetch(:rc)
75
- when Zookeeper::Constants::ZOK;
76
- result.fetch(:data).to_i
77
- when Zookeeper::Constants::ZNONODE;
78
- nil
79
- else
80
- raise Kazoo::Error, "Failed to retrieve offset for partition #{partition.topic.name}/#{partition.id}. Error code: #{result.fetch(:rc)}"
146
+ when Zookeeper::Constants::ZOK; result.fetch(:data).to_i
147
+ when Zookeeper::Constants::ZNONODE; nil
148
+ else raise Kazoo::Error, "Failed to retrieve offset for partition #{partition.topic.name}/#{partition.id}. Error code: #{result.fetch(:rc)}"
81
149
  end
82
150
  end
83
151
 
84
152
  def retrieve_all_offsets
85
- offsets, threads, mutex = {}, [], Mutex.new
86
-
87
153
  topic_result = cluster.zk.get_children(path: "/consumers/#{name}/offsets")
88
154
  case topic_result.fetch(:rc)
89
- when Zookeeper::Constants::ZOK;
90
- # continue
91
- when Zookeeper::Constants::ZNONODE;
92
- return offsets
93
- else
94
- raise Kazoo::Error, "Failed to retrieve offset for partition #{partition.topic.name}/#{partition.id}. Error code: #{topic_result.fetch(:rc)}"
155
+ when Zookeeper::Constants::ZOK; # continue
156
+ when Zookeeper::Constants::ZNONODE; return {}
157
+ else raise Kazoo::Error, "Failed to retrieve offset for partition #{partition.topic.name}/#{partition.id}. Error code: #{topic_result.fetch(:rc)}"
95
158
  end
96
159
 
160
+ offsets, threads, mutex = {}, [], Mutex.new
97
161
  topic_result.fetch(:children).each do |topic_name|
98
162
  threads << Thread.new do
99
163
  Thread.abort_on_exception = true
@@ -200,6 +264,14 @@ module Kazoo
200
264
  end
201
265
  end
202
266
 
267
+ def created_at
268
+ result = cluster.zk.stat(path: "/consumers/#{group.name}/ids/#{id}")
269
+ raise Kazoo::Error, "Failed to get instance details. Error code: #{result.fetch(:rc)}" if result.fetch(:rc) != Zookeeper::Constants::ZOK
270
+
271
+ Time.at(result.fetch(:stat).mtime / 1000.0)
272
+ end
273
+
274
+
203
275
  def deregister
204
276
  cluster.zk.delete(path: "/consumers/#{group.name}/ids/#{id}")
205
277
  end
@@ -50,6 +50,10 @@ module Kazoo
50
50
  "#<Kazoo::Partition #{topic.name}/#{id}>"
51
51
  end
52
52
 
53
+ def key
54
+ "#{topic.name}/#{id}"
55
+ end
56
+
53
57
  def eql?(other)
54
58
  other.kind_of?(Kazoo::Partition) && topic == other.topic && id == other.id
55
59
  end
data/lib/kazoo/topic.rb CHANGED
@@ -4,11 +4,10 @@ module Kazoo
4
4
  BLACKLISTED_TOPIC_NAMES = %r{\A\.\.?\z}
5
5
 
6
6
  attr_reader :cluster, :name
7
- attr_accessor :partitions
7
+ attr_writer :partitions
8
8
 
9
9
  def initialize(cluster, name)
10
10
  @cluster, @name = cluster, name
11
- @partitions = []
12
11
  end
13
12
 
14
13
  def self.from_json(cluster, name, json)
@@ -20,6 +19,18 @@ module Kazoo
20
19
  return topic
21
20
  end
22
21
 
22
+ def partitions
23
+ @partitions ||= begin
24
+ result = cluster.zk.get(path: "/brokers/topics/#{name}")
25
+ raise Kazoo::Error, "Failed to get list of partitions for #{name}. Result code: #{result.fetch(:rc)}" if result.fetch(:rc) != Zookeeper::Constants::ZOK
26
+
27
+ partition_json = JSON.parse(result.fetch(:data))
28
+ partition_json.fetch('partitions').map do |(id, replicas)|
29
+ partition(id.to_i, replicas: replicas.map { |b| cluster.brokers[b] })
30
+ end
31
+ end
32
+ end
33
+
23
34
  def partition(*args)
24
35
  Kazoo::Partition.new(self, *args)
25
36
  end
data/lib/kazoo/version.rb CHANGED
@@ -1,3 +1,3 @@
1
1
  module Kazoo
2
- VERSION = "0.2.0"
2
+ VERSION = "0.3.0"
3
3
  end
@@ -6,9 +6,13 @@ class FunctionalConsumergroupTest < Minitest::Test
6
6
  @cluster = Kazoo.connect(zookeeper)
7
7
  @cg = Kazoo::Consumergroup.new(@cluster, 'test.kazoo')
8
8
  @cg.create
9
+
10
+ @topic = @cluster.create_topic("test.4", partitions: 4, replication_factor: 1)
9
11
  end
10
12
 
11
13
  def teardown
14
+ @topic.destroy
15
+
12
16
  cg = Kazoo::Consumergroup.new(@cluster, 'test.kazoo')
13
17
  cg.destroy if cg.exists?
14
18
 
@@ -40,6 +44,31 @@ class FunctionalConsumergroupTest < Minitest::Test
40
44
  assert_nil @cg.retrieve_offset(partition)
41
45
  end
42
46
 
47
+ def test_unclaimed_partitions
48
+ partition40 = @topic.partition(0)
49
+ partition41 = @topic.partition(1)
50
+ partition42 = @topic.partition(2)
51
+ partition43 = @topic.partition(3)
52
+
53
+ refute @cg.active?
54
+
55
+ instance1 = @cg.instantiate
56
+ instance1.register([@topic])
57
+ instance2 = @cg.instantiate
58
+ instance2.register([@topic])
59
+
60
+ assert @cg.active?
61
+
62
+ instance1.claim_partition(partition40)
63
+ instance2.claim_partition(partition41)
64
+
65
+ assert_equal 2, @cg.partition_claims.length
66
+ assert_equal [@topic], @cg.topics
67
+ assert_equal @topic.partitions, @cg.partitions
68
+
69
+ assert_equal Set[partition42, partition43], Set.new(@cg.unclaimed_partitions)
70
+ end
71
+
43
72
  def test_retrieve_all_offsets
44
73
  topic1 = Kazoo::Topic.new(@cluster, 'test.1')
45
74
  partition10 = Kazoo::Partition.new(topic1, 0)
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: kazoo-ruby
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.0
4
+ version: 0.3.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Willem van Bergen
@@ -114,6 +114,10 @@ files:
114
114
  - lib/kazoo.rb
115
115
  - lib/kazoo/broker.rb
116
116
  - lib/kazoo/cli.rb
117
+ - lib/kazoo/cli/cluster.rb
118
+ - lib/kazoo/cli/common.rb
119
+ - lib/kazoo/cli/consumers.rb
120
+ - lib/kazoo/cli/topics.rb
117
121
  - lib/kazoo/cluster.rb
118
122
  - lib/kazoo/consumergroup.rb
119
123
  - lib/kazoo/partition.rb