kazoo-ruby 0.0.1 → 0.1.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 +4 -4
- data/README.md +41 -12
- data/kazoo-ruby.gemspec +2 -2
- data/lib/kazoo.rb +9 -0
- data/lib/kazoo/broker.rb +4 -0
- data/lib/kazoo/cli.rb +3 -4
- data/lib/kazoo/cluster.rb +27 -9
- data/lib/kazoo/consumergroup.rb +215 -0
- data/lib/kazoo/partition.rb +17 -1
- data/lib/kazoo/topic.rb +14 -0
- data/lib/kazoo/version.rb +1 -1
- data/test/broker_test.rb +12 -0
- data/test/partition_test.rb +16 -1
- data/test/topic_test.rb +13 -0
- metadata +5 -4
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 8459c642f0d085f68811488f9d6ab92f186fd296
|
4
|
+
data.tar.gz: 2f187078b0e87d345e71277195750ebecbd3b5b4
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: e22aa111a85057bd295d80485371c46c84b1306d89160e04e2d2a21b985c407da14c59c4936d49239232f53e0309fb59fd9ca71f8affcc6cab8dd3f428ab55b7
|
7
|
+
data.tar.gz: 570508f6fe5f8d10bb8081b06c43f44b5f20da4e28d57801fcc5c6204f97a1f4557ac7234fd67bc72c7173111d145a42f6a5eabc5479267ccf9eb27095706fac
|
data/README.md
CHANGED
@@ -1,31 +1,60 @@
|
|
1
1
|
# Kazoo
|
2
2
|
|
3
|
-
|
3
|
+
Ruby library to access and manipulate Kafka metadata in Zookeeper
|
4
4
|
|
5
|
-
##
|
5
|
+
## Usage
|
6
6
|
|
7
|
-
|
7
|
+
First, make kazoo available by adding it to your Gemfile
|
8
8
|
|
9
|
-
```ruby
|
10
|
-
gem 'kazoo'
|
9
|
+
``` ruby
|
10
|
+
gem 'kazoo-ruby', require: 'kazoo'
|
11
11
|
```
|
12
12
|
|
13
|
-
|
13
|
+
Now, you can interact with the cluster metadata as follows:
|
14
14
|
|
15
|
-
|
15
|
+
``` ruby
|
16
|
+
# Connect to the Zookeeper cluster that backs your Kafka cluster
|
17
|
+
cluster = Kazoo::Cluster.new('zookeeper1:2181,zookeeper2:2181/chroot')
|
16
18
|
|
17
|
-
|
19
|
+
# List the brokers that form the Kafka cluster
|
20
|
+
cluster.brokers.each do |id, broker|
|
21
|
+
puts "Broker #{broker.id}: #{broker.addr}"
|
22
|
+
end
|
18
23
|
|
19
|
-
|
24
|
+
# Inspect topic/partition metadata
|
25
|
+
cluster.topics.each do |name, topic|
|
26
|
+
puts "#{name}: #{topic.partitions.length} partitions"
|
27
|
+
end
|
20
28
|
|
21
|
-
|
29
|
+
# List consumers
|
30
|
+
cluster.consumergroups.each do |name, group|
|
31
|
+
puts "Consumer #{name}: #{group.instances.length} running instances"
|
32
|
+
end
|
33
|
+
```
|
22
34
|
|
23
|
-
|
35
|
+
## Binary
|
36
|
+
|
37
|
+
This gem also comes with a simple `kazoo` binary to inspect your kafka cluster:
|
38
|
+
|
39
|
+
```
|
40
|
+
# Describe the brokers that compose the cluster
|
41
|
+
$ kazoo cluster --zookeeper zk1:2181,zk2:2181,zk3:2181/chroot
|
42
|
+
|
43
|
+
# List all topics or partitions in the cluster
|
44
|
+
$ kazoo topics --zookeeper zk1:2181,zk2:2181,zk3:2181/chroot
|
45
|
+
$ kazoo partitions --topic=access_log --zookeeper zk1:2181,zk2:2181,zk3:2181/chroot
|
46
|
+
|
47
|
+
```
|
24
48
|
|
25
49
|
## Contributing
|
26
50
|
|
27
|
-
1. Fork it ( https://github.com/
|
51
|
+
1. Fork it ( https://github.com/wvanbergen/kazoo/fork )
|
28
52
|
2. Create your feature branch (`git checkout -b my-new-feature`)
|
29
53
|
3. Commit your changes (`git commit -am 'Add some feature'`)
|
30
54
|
4. Push to the branch (`git push origin my-new-feature`)
|
31
55
|
5. Create a new Pull Request
|
56
|
+
|
57
|
+
## See also
|
58
|
+
|
59
|
+
- [kafka-consumer](https://github.com/wvanbergen/kafka-consumer): a high-level
|
60
|
+
Kafka consumer library that coordinates running instances using Zookeeper.
|
data/kazoo-ruby.gemspec
CHANGED
@@ -8,8 +8,8 @@ Gem::Specification.new do |spec|
|
|
8
8
|
spec.version = Kazoo::VERSION
|
9
9
|
spec.authors = ["Willem van Bergen"]
|
10
10
|
spec.email = ["willem@vanbergen.org"]
|
11
|
-
spec.summary = %q{Library to access Kafka metadata in Zookeeper}
|
12
|
-
spec.description = %q{Library to access Kafka metadata in Zookeeper}
|
11
|
+
spec.summary = %q{Library to access and manipulate Kafka metadata in Zookeeper}
|
12
|
+
spec.description = %q{Library to access and manipulate Kafka metadata in Zookeeper}
|
13
13
|
spec.homepage = "https://github.com/wvanbergen/kazoo"
|
14
14
|
spec.license = "MIT"
|
15
15
|
|
data/lib/kazoo.rb
CHANGED
@@ -1,12 +1,21 @@
|
|
1
1
|
require 'zookeeper'
|
2
2
|
require 'json'
|
3
3
|
require 'thread'
|
4
|
+
require 'socket'
|
5
|
+
require 'securerandom'
|
4
6
|
|
5
7
|
module Kazoo
|
8
|
+
Error = Class.new(StandardError)
|
9
|
+
|
10
|
+
NoClusterRegistered = Class.new(Kazoo::Error)
|
11
|
+
ConsumerInstanceRegistrationFailed = Class.new(Kazoo::Error)
|
12
|
+
PartitionAlreadyClaimed = Class.new(Kazoo::Error)
|
13
|
+
ReleasePartitionFailure = Class.new(Kazoo::Error)
|
6
14
|
end
|
7
15
|
|
8
16
|
require 'kazoo/cluster'
|
9
17
|
require 'kazoo/broker'
|
10
18
|
require 'kazoo/topic'
|
11
19
|
require 'kazoo/partition'
|
20
|
+
require 'kazoo/consumergroup'
|
12
21
|
require 'kazoo/version'
|
data/lib/kazoo/broker.rb
CHANGED
@@ -61,6 +61,10 @@ module Kazoo
|
|
61
61
|
[self.cluster, self.id].hash
|
62
62
|
end
|
63
63
|
|
64
|
+
def inspect
|
65
|
+
"#<Kazoo::Broker id=#{id} addr=#{addr}>"
|
66
|
+
end
|
67
|
+
|
64
68
|
def self.from_json(cluster, id, json)
|
65
69
|
new(cluster, id.to_i, json.fetch('host'), json.fetch('port'), jmx_port: json.fetch('jmx_port', nil))
|
66
70
|
end
|
data/lib/kazoo/cli.rb
CHANGED
@@ -3,8 +3,7 @@ require 'thor'
|
|
3
3
|
|
4
4
|
module Kazoo
|
5
5
|
class CLI < Thor
|
6
|
-
class_option :zookeeper, :type => :string, :default => ENV['
|
7
|
-
class_option :chroot, :type => :string, :default => ""
|
6
|
+
class_option :zookeeper, :type => :string, :default => ENV['ZOOKEEPER']
|
8
7
|
|
9
8
|
desc "cluster", "Describes the Kafka cluster as registered in Zookeeper"
|
10
9
|
def cluster
|
@@ -57,7 +56,7 @@ module Kazoo
|
|
57
56
|
|
58
57
|
def validate_class_options!
|
59
58
|
if options[:zookeeper].nil? || options[:zookeeper] == ''
|
60
|
-
raise Thor::InvocationError, "Please supply --zookeeper argument, or set the
|
59
|
+
raise Thor::InvocationError, "Please supply --zookeeper argument, or set the ZOOKEEPER environment variable"
|
61
60
|
end
|
62
61
|
end
|
63
62
|
|
@@ -73,7 +72,7 @@ module Kazoo
|
|
73
72
|
end
|
74
73
|
|
75
74
|
def kafka_cluster
|
76
|
-
@kafka_cluster ||= Kazoo::Cluster.new(options[:zookeeper]
|
75
|
+
@kafka_cluster ||= Kazoo::Cluster.new(options[:zookeeper])
|
77
76
|
end
|
78
77
|
end
|
79
78
|
end
|
data/lib/kazoo/cluster.rb
CHANGED
@@ -1,10 +1,10 @@
|
|
1
1
|
module Kazoo
|
2
2
|
class Cluster
|
3
3
|
|
4
|
-
attr_reader :zookeeper
|
4
|
+
attr_reader :zookeeper
|
5
5
|
|
6
|
-
def initialize(zookeeper
|
7
|
-
@zookeeper
|
6
|
+
def initialize(zookeeper)
|
7
|
+
@zookeeper = zookeeper
|
8
8
|
@zk_mutex, @brokers_mutex, @topics_mutex = Mutex.new, Mutex.new, Mutex.new
|
9
9
|
end
|
10
10
|
|
@@ -17,11 +17,18 @@ module Kazoo
|
|
17
17
|
def brokers
|
18
18
|
@brokers_mutex.synchronize do
|
19
19
|
@brokers ||= begin
|
20
|
-
brokers = zk.get_children(path:
|
20
|
+
brokers = zk.get_children(path: "/brokers/ids")
|
21
|
+
|
22
|
+
if brokers.fetch(:rc) != Zookeeper::Constants::ZOK
|
23
|
+
raise NoClusterRegistered, "No Kafka cluster registered on this Zookeeper location."
|
24
|
+
end
|
25
|
+
|
21
26
|
result, threads, mutex = {}, ThreadGroup.new, Mutex.new
|
22
27
|
brokers.fetch(:children).map do |id|
|
23
28
|
t = Thread.new do
|
24
|
-
broker_info = zk.get(path:
|
29
|
+
broker_info = zk.get(path: "/brokers/ids/#{id}")
|
30
|
+
raise Kazoo::Error, "Failed to retrieve broker info. Error code: #{broker_info.fetch(:rc)}" unless broker_info.fetch(:rc) == Zookeeper::Constants::ZOK
|
31
|
+
|
25
32
|
broker = Kazoo::Broker.from_json(self, id, JSON.parse(broker_info.fetch(:data)))
|
26
33
|
mutex.synchronize { result[id.to_i] = broker }
|
27
34
|
end
|
@@ -33,14 +40,25 @@ module Kazoo
|
|
33
40
|
end
|
34
41
|
end
|
35
42
|
|
43
|
+
def consumergroups
|
44
|
+
@consumergroups ||= begin
|
45
|
+
consumers = zk.get_children(path: "/consumers")
|
46
|
+
consumers.fetch(:children).map { |name| Kazoo::Consumergroup.new(self, name) }
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
36
50
|
def topics
|
37
51
|
@topics_mutex.synchronize do
|
38
52
|
@topics ||= begin
|
39
|
-
topics = zk.get_children(path:
|
53
|
+
topics = zk.get_children(path: "/brokers/topics")
|
54
|
+
raise Kazoo::Error, "Failed to list topics. Error code: #{topics.fetch(:rc)}" unless topics.fetch(:rc) == Zookeeper::Constants::ZOK
|
55
|
+
|
40
56
|
result, threads, mutex = {}, ThreadGroup.new, Mutex.new
|
41
57
|
topics.fetch(:children).each do |name|
|
42
58
|
t = Thread.new do
|
43
|
-
topic_info = zk.get(path:
|
59
|
+
topic_info = zk.get(path: "/brokers/topics/#{name}")
|
60
|
+
raise Kazoo::Error, "Failed to get topic info. Error code: #{topic_info.fetch(:rc)}" unless topic_info.fetch(:rc) == Zookeeper::Constants::ZOK
|
61
|
+
|
44
62
|
topic = Kazoo::Topic.from_json(self, name, JSON.parse(topic_info.fetch(:data)))
|
45
63
|
mutex.synchronize { result[name] = topic }
|
46
64
|
end
|
@@ -64,8 +82,8 @@ module Kazoo
|
|
64
82
|
partitions.any?(&:under_replicated?)
|
65
83
|
end
|
66
84
|
|
67
|
-
def
|
68
|
-
|
85
|
+
def close
|
86
|
+
zk.close
|
69
87
|
end
|
70
88
|
end
|
71
89
|
end
|
@@ -0,0 +1,215 @@
|
|
1
|
+
module Kazoo
|
2
|
+
class Consumergroup
|
3
|
+
attr_reader :cluster, :name
|
4
|
+
|
5
|
+
def initialize(cluster, name)
|
6
|
+
@cluster, @name = cluster, name
|
7
|
+
end
|
8
|
+
|
9
|
+
def create
|
10
|
+
cluster.zk.create(path: "/consumers/#{name}")
|
11
|
+
cluster.zk.create(path: "/consumers/#{name}/ids")
|
12
|
+
cluster.zk.create(path: "/consumers/#{name}/owners")
|
13
|
+
cluster.zk.create(path: "/consumers/#{name}/offsets")
|
14
|
+
end
|
15
|
+
|
16
|
+
def exists?
|
17
|
+
stat = cluster.zk.stat(path: "/consumers/#{name}")
|
18
|
+
stat.fetch(:stat).exists?
|
19
|
+
end
|
20
|
+
|
21
|
+
|
22
|
+
def instantiate(id: nil)
|
23
|
+
Instance.new(self, id: id)
|
24
|
+
end
|
25
|
+
|
26
|
+
def instances
|
27
|
+
instances = cluster.zk.get_children(path: "/consumers/#{name}/ids")
|
28
|
+
instances.fetch(:children).map { |id| Instance.new(self, id: id) }
|
29
|
+
end
|
30
|
+
|
31
|
+
def watch_instances(&block)
|
32
|
+
cb = Zookeeper::Callbacks::WatcherCallback.create(&block)
|
33
|
+
result = cluster.zk.get_children(path: "/consumers/#{name}/ids", watcher: cb)
|
34
|
+
|
35
|
+
if result.fetch(:rc) != Zookeeper::Constants::ZOK
|
36
|
+
raise Kazoo::Error, "Failed to watch instances. Error code: #{result.fetch(:rc)}"
|
37
|
+
end
|
38
|
+
|
39
|
+
instances = result.fetch(:children).map { |id| Instance.new(self, id: id) }
|
40
|
+
[instances, cb]
|
41
|
+
end
|
42
|
+
|
43
|
+
|
44
|
+
def watch_partition_claim(partition, &block)
|
45
|
+
cb = Zookeeper::Callbacks::WatcherCallback.create(&block)
|
46
|
+
|
47
|
+
result = cluster.zk.get(path: "/consumers/#{name}/owners/#{partition.topic.name}/#{partition.id}", watcher: cb)
|
48
|
+
|
49
|
+
case result.fetch(:rc)
|
50
|
+
when Zookeeper::Constants::ZNONODE # Nobody is claiming this partition yet
|
51
|
+
[nil, nil]
|
52
|
+
when Zookeeper::Constants::ZOK
|
53
|
+
[Kazoo::Consumergroup::Instance.new(self, id: result.fetch(:data)), cb]
|
54
|
+
else
|
55
|
+
raise Kazoo::Error, "Failed set watch for partition claim of #{partition.topic.name}/#{partition.id}. Error code: #{result.fetch(:rc)}"
|
56
|
+
end
|
57
|
+
end
|
58
|
+
|
59
|
+
def retrieve_offset(partition)
|
60
|
+
result = cluster.zk.get(path: "/consumers/#{name}/offsets/#{partition.topic.name}/#{partition.id}")
|
61
|
+
case result.fetch(:rc)
|
62
|
+
when Zookeeper::Constants::ZOK;
|
63
|
+
result.fetch(:data).to_i
|
64
|
+
when Zookeeper::Constants::ZNONODE;
|
65
|
+
nil
|
66
|
+
else
|
67
|
+
raise Kazoo::Error, "Failed to retrieve offset for partition #{partition.topic.name}/#{partition.id}. Error code: #{result.fetch(:rc)}"
|
68
|
+
end
|
69
|
+
end
|
70
|
+
|
71
|
+
def commit_offset(partition, offset)
|
72
|
+
result = cluster.zk.set(path: "/consumers/#{name}/offsets/#{partition.topic.name}/#{partition.id}", data: (offset + 1).to_s)
|
73
|
+
if result.fetch(:rc) == Zookeeper::Constants::ZNONODE
|
74
|
+
result = cluster.zk.create(path: "/consumers/#{name}/offsets/#{partition.topic.name}")
|
75
|
+
case result.fetch(:rc)
|
76
|
+
when Zookeeper::Constants::ZOK, Zookeeper::Constants::ZNODEEXISTS
|
77
|
+
else
|
78
|
+
raise Kazoo::Error, "Failed to commit offset #{offset} for partition #{partition.topic.name}/#{partition.id}. Error code: #{result.fetch(:rc)}"
|
79
|
+
end
|
80
|
+
|
81
|
+
result = cluster.zk.create(path: "/consumers/#{name}/offsets/#{partition.topic.name}/#{partition.id}", data: (offset + 1).to_s)
|
82
|
+
end
|
83
|
+
|
84
|
+
if result.fetch(:rc) != Zookeeper::Constants::ZOK
|
85
|
+
raise Kazoo::Error, "Failed to commit offset #{offset} for partition #{partition.topic.name}/#{partition.id}. Error code: #{result.fetch(:rc)}"
|
86
|
+
end
|
87
|
+
end
|
88
|
+
|
89
|
+
def reset_offsets
|
90
|
+
result = cluster.zk.get_children(path: "/consumers/#{name}/offsets")
|
91
|
+
raise Kazoo::Error unless result.fetch(:rc) == Zookeeper::Constants::ZOK
|
92
|
+
|
93
|
+
result.fetch(:children).each do |topic|
|
94
|
+
result = cluster.zk.get_children(path: "/consumers/#{name}/offsets/#{topic}")
|
95
|
+
raise Kazoo::Error unless result.fetch(:rc) == Zookeeper::Constants::ZOK
|
96
|
+
|
97
|
+
result.fetch(:children).each do |partition|
|
98
|
+
cluster.zk.delete(path: "/consumers/#{name}/offsets/#{topic}/#{partition}")
|
99
|
+
raise Kazoo::Error unless result.fetch(:rc) == Zookeeper::Constants::ZOK
|
100
|
+
end
|
101
|
+
|
102
|
+
cluster.zk.delete(path: "/consumers/#{name}/offsets/#{topic}")
|
103
|
+
raise Kazoo::Error unless result.fetch(:rc) == Zookeeper::Constants::ZOK
|
104
|
+
end
|
105
|
+
end
|
106
|
+
|
107
|
+
def inspect
|
108
|
+
"#<Kazoo::Consumergroup name=#{name}>"
|
109
|
+
end
|
110
|
+
|
111
|
+
def eql?(other)
|
112
|
+
other.kind_of?(Kazoo::Consumergroup) && cluster == other.cluster && name == other.name
|
113
|
+
end
|
114
|
+
|
115
|
+
alias_method :==, :eql?
|
116
|
+
|
117
|
+
def hash
|
118
|
+
[cluster, name].hash
|
119
|
+
end
|
120
|
+
|
121
|
+
class Instance
|
122
|
+
|
123
|
+
def self.generate_id
|
124
|
+
"#{Socket.gethostname}:#{SecureRandom.uuid}"
|
125
|
+
end
|
126
|
+
|
127
|
+
attr_reader :group, :id
|
128
|
+
|
129
|
+
def initialize(group, id: nil)
|
130
|
+
@group = group
|
131
|
+
@id = id || self.class.generate_id
|
132
|
+
end
|
133
|
+
|
134
|
+
def registered?
|
135
|
+
stat = cluster.zk.stat(path: "/consumers/#{group.name}/ids/#{id}")
|
136
|
+
stat.fetch(:stat).exists?
|
137
|
+
end
|
138
|
+
|
139
|
+
def register(subscription)
|
140
|
+
result = cluster.zk.create(
|
141
|
+
path: "/consumers/#{group.name}/ids/#{id}",
|
142
|
+
ephemeral: true,
|
143
|
+
data: JSON.generate({
|
144
|
+
version: 1,
|
145
|
+
timestamp: Time.now.to_i,
|
146
|
+
pattern: "static",
|
147
|
+
subscription: Hash[*subscription.flat_map { |topic| [topic.name, 1] } ]
|
148
|
+
})
|
149
|
+
)
|
150
|
+
|
151
|
+
if result.fetch(:rc) != Zookeeper::Constants::ZOK
|
152
|
+
raise Kazoo::ConsumerInstanceRegistrationFailed, "Failed to register instance #{id} for consumer group #{group.name}! Error code: #{result.fetch(:rc)}"
|
153
|
+
end
|
154
|
+
|
155
|
+
subscription.each do |topic|
|
156
|
+
stat = cluster.zk.stat(path: "/consumers/#{group.name}/owners/#{topic.name}")
|
157
|
+
unless stat.fetch(:stat).exists?
|
158
|
+
result = cluster.zk.create(path: "/consumers/#{group.name}/owners/#{topic.name}")
|
159
|
+
if result.fetch(:rc) != Zookeeper::Constants::ZOK
|
160
|
+
raise Kazoo::ConsumerInstanceRegistrationFailed, "Failed to register subscription of #{topic.name} for consumer group #{group.name}! Error code: #{result.fetch(:rc)}"
|
161
|
+
end
|
162
|
+
end
|
163
|
+
end
|
164
|
+
end
|
165
|
+
|
166
|
+
def deregister
|
167
|
+
cluster.zk.delete(path: "/consumers/#{group.name}/ids/#{id}")
|
168
|
+
end
|
169
|
+
|
170
|
+
def claim_partition(partition)
|
171
|
+
result = cluster.zk.create(
|
172
|
+
path: "/consumers/#{group.name}/owners/#{partition.topic.name}/#{partition.id}",
|
173
|
+
ephemeral: true,
|
174
|
+
data: id,
|
175
|
+
)
|
176
|
+
|
177
|
+
case result.fetch(:rc)
|
178
|
+
when Zookeeper::Constants::ZOK
|
179
|
+
return true
|
180
|
+
when Zookeeper::Constants::ZNODEEXISTS
|
181
|
+
raise Kazoo::PartitionAlreadyClaimed, "Partition #{partition.topic.name}/#{partition.id} is already claimed!"
|
182
|
+
else
|
183
|
+
raise Kazoo::Error, "Failed to claim partition #{partition.topic.name}/#{partition.id}. Error code: #{result.fetch(:rc)}"
|
184
|
+
end
|
185
|
+
end
|
186
|
+
|
187
|
+
def release_partition(partition)
|
188
|
+
result = cluster.zk.delete(path: "/consumers/#{group.name}/owners/#{partition.topic.name}/#{partition.id}")
|
189
|
+
if result.fetch(:rc) != Zookeeper::Constants::ZOK
|
190
|
+
raise Kazoo::Error, "Failed to release partition #{partition.topic.name}/#{partition.id}. Error code: #{result.fetch(:rc)}"
|
191
|
+
end
|
192
|
+
end
|
193
|
+
|
194
|
+
def inspect
|
195
|
+
"#<Kazoo::Consumergroup::Instance group=#{group.name} id=#{id}>"
|
196
|
+
end
|
197
|
+
|
198
|
+
def hash
|
199
|
+
[group, id].hash
|
200
|
+
end
|
201
|
+
|
202
|
+
def eql?(other)
|
203
|
+
other.kind_of?(Kazoo::Consumergroup::Instance) && group == other.group && id == other.id
|
204
|
+
end
|
205
|
+
|
206
|
+
alias_method :==, :eql?
|
207
|
+
|
208
|
+
private
|
209
|
+
|
210
|
+
def cluster
|
211
|
+
group.cluster
|
212
|
+
end
|
213
|
+
end
|
214
|
+
end
|
215
|
+
end
|
data/lib/kazoo/partition.rb
CHANGED
@@ -33,10 +33,26 @@ module Kazoo
|
|
33
33
|
isr.length < replication_factor
|
34
34
|
end
|
35
35
|
|
36
|
+
def inspect
|
37
|
+
"#<Kazoo::Partition #{topic.name}/#{id}>"
|
38
|
+
end
|
39
|
+
|
40
|
+
def eql?(other)
|
41
|
+
other.kind_of?(Kazoo::Partition) && topic == other.topic && id == other.id
|
42
|
+
end
|
43
|
+
|
44
|
+
alias_method :==, :eql?
|
45
|
+
|
46
|
+
def hash
|
47
|
+
[topic, id].hash
|
48
|
+
end
|
49
|
+
|
36
50
|
protected
|
37
51
|
|
38
52
|
def refresh_state
|
39
|
-
state_json = cluster.zk.get(path:
|
53
|
+
state_json = cluster.zk.get(path: "/brokers/topics/#{topic.name}/partitions/#{id}/state")
|
54
|
+
raise Kazoo::Error, "Failed to get partition state. Error code: #{state_json.fetch(:rc)}" unless state_json.fetch(:rc) == Zookeeper::Constants::ZOK
|
55
|
+
|
40
56
|
set_state(JSON.parse(state_json.fetch(:data)))
|
41
57
|
end
|
42
58
|
|
data/lib/kazoo/topic.rb
CHANGED
@@ -28,5 +28,19 @@ module Kazoo
|
|
28
28
|
def under_replicated?
|
29
29
|
partitions.any?(:under_replicated?)
|
30
30
|
end
|
31
|
+
|
32
|
+
def inspect
|
33
|
+
"#<Kazoo::Topic #{name}>"
|
34
|
+
end
|
35
|
+
|
36
|
+
def eql?(other)
|
37
|
+
other.kind_of?(Kazoo::Topic) && cluster == other.cluster && name == other.name
|
38
|
+
end
|
39
|
+
|
40
|
+
alias_method :==, :eql?
|
41
|
+
|
42
|
+
def hash
|
43
|
+
[cluster, name].hash
|
44
|
+
end
|
31
45
|
end
|
32
46
|
end
|
data/lib/kazoo/version.rb
CHANGED
data/test/broker_test.rb
CHANGED
@@ -42,4 +42,16 @@ class BrokerTest < Minitest::Test
|
|
42
42
|
assert_equal 2, @cluster.brokers[2].led_partitions.length
|
43
43
|
assert_equal 1, @cluster.brokers[3].led_partitions.length
|
44
44
|
end
|
45
|
+
|
46
|
+
def test_inspect
|
47
|
+
assert_equal "#<Kazoo::Broker id=1 addr=example.com:9091>", @cluster.brokers[1].inspect
|
48
|
+
end
|
49
|
+
|
50
|
+
def test_equality
|
51
|
+
b1 = @cluster.brokers[1]
|
52
|
+
b2 = Kazoo::Broker.new(@cluster, 1, 'example.com', 9091)
|
53
|
+
|
54
|
+
assert_equal b1, b2
|
55
|
+
assert_equal b1.hash, b2.hash
|
56
|
+
end
|
45
57
|
end
|
data/test/partition_test.rb
CHANGED
@@ -17,9 +17,24 @@ class PartitionTest < Minitest::Test
|
|
17
17
|
partition.unstub(:isr)
|
18
18
|
|
19
19
|
json_payload = '{"controller_epoch":157,"leader":1,"version":1,"leader_epoch":8,"isr":[3,2,1]}'
|
20
|
-
@cluster.zk.expects(:get).with(path: "/brokers/topics/test.1/partitions/0/state").returns(data: json_payload)
|
20
|
+
@cluster.zk.expects(:get).with(path: "/brokers/topics/test.1/partitions/0/state").returns(data: json_payload, rc: 0)
|
21
21
|
|
22
22
|
assert_equal 1, partition.leader.id
|
23
23
|
assert_equal [3,2,1], partition.isr.map(&:id)
|
24
24
|
end
|
25
|
+
|
26
|
+
def test_inspect
|
27
|
+
assert_equal "#<Kazoo::Partition test.1/0>", @cluster.topics['test.1'].partition(0).inspect
|
28
|
+
end
|
29
|
+
|
30
|
+
def test_equality
|
31
|
+
topic = @cluster.topics['test.1']
|
32
|
+
p1 = topic.partition(0)
|
33
|
+
p2 = Kazoo::Partition.new(topic, 0)
|
34
|
+
|
35
|
+
assert_equal p1, p2
|
36
|
+
assert p1 != Kazoo::Partition.new(topic, 1)
|
37
|
+
assert p1 != Kazoo::Partition.new(@cluster.topics['test.4'], 0)
|
38
|
+
assert_equal p1.hash, p2.hash
|
39
|
+
end
|
25
40
|
end
|
data/test/topic_test.rb
CHANGED
@@ -37,4 +37,17 @@ class TopicTest < Minitest::Test
|
|
37
37
|
assert @cluster.topics['test.1'].partitions[0].under_replicated?
|
38
38
|
assert @cluster.topics['test.1'].under_replicated?
|
39
39
|
end
|
40
|
+
|
41
|
+
def test_inspect
|
42
|
+
assert_equal "#<Kazoo::Topic test.1>", @cluster.topics['test.1'].inspect
|
43
|
+
end
|
44
|
+
|
45
|
+
def test_equality
|
46
|
+
t1 = @cluster.topics['test.1']
|
47
|
+
t2 = Kazoo::Topic.new(@cluster, 'test.1')
|
48
|
+
|
49
|
+
assert_equal t1, t2
|
50
|
+
assert t1 != Kazoo::Topic.new(@cluster, 'test.2')
|
51
|
+
assert_equal t1.hash, t2.hash
|
52
|
+
end
|
40
53
|
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: kazoo-ruby
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0
|
4
|
+
version: 0.1.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Willem van Bergen
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2015-08-
|
11
|
+
date: 2015-08-13 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: thor
|
@@ -94,7 +94,7 @@ dependencies:
|
|
94
94
|
- - ~>
|
95
95
|
- !ruby/object:Gem::Version
|
96
96
|
version: '5'
|
97
|
-
description: Library to access Kafka metadata in Zookeeper
|
97
|
+
description: Library to access and manipulate Kafka metadata in Zookeeper
|
98
98
|
email:
|
99
99
|
- willem@vanbergen.org
|
100
100
|
executables:
|
@@ -114,6 +114,7 @@ files:
|
|
114
114
|
- lib/kazoo/broker.rb
|
115
115
|
- lib/kazoo/cli.rb
|
116
116
|
- lib/kazoo/cluster.rb
|
117
|
+
- lib/kazoo/consumergroup.rb
|
117
118
|
- lib/kazoo/partition.rb
|
118
119
|
- lib/kazoo/topic.rb
|
119
120
|
- lib/kazoo/version.rb
|
@@ -145,7 +146,7 @@ rubyforge_project:
|
|
145
146
|
rubygems_version: 2.0.14
|
146
147
|
signing_key:
|
147
148
|
specification_version: 4
|
148
|
-
summary: Library to access Kafka metadata in Zookeeper
|
149
|
+
summary: Library to access and manipulate Kafka metadata in Zookeeper
|
149
150
|
test_files:
|
150
151
|
- test/broker_test.rb
|
151
152
|
- test/cluster_test.rb
|