kazoo-ruby 0.2.0 → 0.3.0

Sign up to get free protection for your applications and to get access to all the features.
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