codeclimate-poseidon 0.0.8
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/.gitignore +21 -0
- data/.rspec +2 -0
- data/.travis.yml +14 -0
- data/.yardopts +8 -0
- data/CHANGES.md +31 -0
- data/Gemfile +13 -0
- data/LICENSE.txt +22 -0
- data/README.md +72 -0
- data/Rakefile +20 -0
- data/TODO.md +27 -0
- data/examples/consumer.rb +18 -0
- data/examples/producer.rb +9 -0
- data/lib/poseidon.rb +120 -0
- data/lib/poseidon/broker_pool.rb +86 -0
- data/lib/poseidon/cluster_metadata.rb +94 -0
- data/lib/poseidon/compressed_value.rb +23 -0
- data/lib/poseidon/compression.rb +30 -0
- data/lib/poseidon/compression/gzip_codec.rb +23 -0
- data/lib/poseidon/compression/snappy_codec.rb +29 -0
- data/lib/poseidon/connection.rb +169 -0
- data/lib/poseidon/fetched_message.rb +37 -0
- data/lib/poseidon/message.rb +151 -0
- data/lib/poseidon/message_conductor.rb +86 -0
- data/lib/poseidon/message_set.rb +80 -0
- data/lib/poseidon/message_to_send.rb +33 -0
- data/lib/poseidon/messages_for_broker.rb +56 -0
- data/lib/poseidon/messages_to_send.rb +47 -0
- data/lib/poseidon/messages_to_send_batch.rb +27 -0
- data/lib/poseidon/partition_consumer.rb +225 -0
- data/lib/poseidon/producer.rb +199 -0
- data/lib/poseidon/producer_compression_config.rb +37 -0
- data/lib/poseidon/protocol.rb +122 -0
- data/lib/poseidon/protocol/protocol_struct.rb +256 -0
- data/lib/poseidon/protocol/request_buffer.rb +77 -0
- data/lib/poseidon/protocol/response_buffer.rb +72 -0
- data/lib/poseidon/sync_producer.rb +161 -0
- data/lib/poseidon/topic_metadata.rb +89 -0
- data/lib/poseidon/version.rb +4 -0
- data/log/.gitkeep +0 -0
- data/poseidon.gemspec +27 -0
- data/spec/integration/multiple_brokers/consumer_spec.rb +45 -0
- data/spec/integration/multiple_brokers/metadata_failures_spec.rb +144 -0
- data/spec/integration/multiple_brokers/rebalance_spec.rb +69 -0
- data/spec/integration/multiple_brokers/round_robin_spec.rb +41 -0
- data/spec/integration/multiple_brokers/spec_helper.rb +60 -0
- data/spec/integration/simple/compression_spec.rb +23 -0
- data/spec/integration/simple/connection_spec.rb +35 -0
- data/spec/integration/simple/multiple_brokers_spec.rb +10 -0
- data/spec/integration/simple/simple_producer_and_consumer_spec.rb +121 -0
- data/spec/integration/simple/spec_helper.rb +16 -0
- data/spec/integration/simple/truncated_messages_spec.rb +46 -0
- data/spec/integration/simple/unavailable_broker_spec.rb +72 -0
- data/spec/spec_helper.rb +32 -0
- data/spec/test_cluster.rb +211 -0
- data/spec/unit/broker_pool_spec.rb +98 -0
- data/spec/unit/cluster_metadata_spec.rb +46 -0
- data/spec/unit/compression/gzip_codec_spec.rb +34 -0
- data/spec/unit/compression/snappy_codec_spec.rb +49 -0
- data/spec/unit/compression_spec.rb +17 -0
- data/spec/unit/connection_spec.rb +4 -0
- data/spec/unit/fetched_message_spec.rb +11 -0
- data/spec/unit/message_conductor_spec.rb +164 -0
- data/spec/unit/message_set_spec.rb +42 -0
- data/spec/unit/message_spec.rb +129 -0
- data/spec/unit/message_to_send_spec.rb +10 -0
- data/spec/unit/messages_for_broker_spec.rb +54 -0
- data/spec/unit/messages_to_send_batch_spec.rb +25 -0
- data/spec/unit/messages_to_send_spec.rb +63 -0
- data/spec/unit/partition_consumer_spec.rb +142 -0
- data/spec/unit/producer_compression_config_spec.rb +42 -0
- data/spec/unit/producer_spec.rb +51 -0
- data/spec/unit/protocol/request_buffer_spec.rb +16 -0
- data/spec/unit/protocol_spec.rb +54 -0
- data/spec/unit/sync_producer_spec.rb +156 -0
- data/spec/unit/topic_metadata_spec.rb +43 -0
- metadata +225 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: 0d4c27c567e99772b9a024ffe551b68dd81185bf
|
4
|
+
data.tar.gz: b384e7627ec29faadbc7582a69312050ffe693bf
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: aab82245bd26818cad1a361bfefa20619c39e4f882af4204c5f0f4e0f2b17535e86829595cbb9ae1ed63d9fa1bc8fb63b9e604124e336d74dcbc5579f55d0fe3
|
7
|
+
data.tar.gz: 1ab14df98fc583eb6d48df2986421dc9ec33fbf39a17bfbc64ccc0172dffa2a7a07cb6a4eac3e0880a6298634f365f62a33c5ddfaea696d09f4684d8d77025ae
|
data/.gitignore
ADDED
data/.rspec
ADDED
data/.travis.yml
ADDED
data/.yardopts
ADDED
data/CHANGES.md
ADDED
@@ -0,0 +1,31 @@
|
|
1
|
+
# 0.0.5
|
2
|
+
|
3
|
+
* Add support for negative offsets. [GH-24]
|
4
|
+
* Fix serious bug where we would send messages to the wrong partition. [GH-36] (Thanks @sclasen and @jorgeortiz85 for tracking this down.)
|
5
|
+
* Better error message when we can't connect to a broker. [GH-42]
|
6
|
+
* Handle broker rebalances. [GH-43]
|
7
|
+
* PartitionConsumer: Block for messages by default. [GH-48]
|
8
|
+
* Add a logger to help debug issues. [GH-51]
|
9
|
+
* Add snappy support. [GH-57]
|
10
|
+
* Allow `:none` value for `:compression_codec` option. [GH-72]
|
11
|
+
* Allow request buffer to accept mixed encodings. [GH-74]
|
12
|
+
|
13
|
+
# 0.0.4
|
14
|
+
|
15
|
+
* Don't truncate UTF8 Messages [GH-18]
|
16
|
+
* Gracefully handle truncated fetch reponses [GH-19]
|
17
|
+
|
18
|
+
# 0.0.3
|
19
|
+
|
20
|
+
* Better distribute messages across partitions.
|
21
|
+
* Handle broken connections better.
|
22
|
+
* Gracefully handle attempts to send an empty set of messages.
|
23
|
+
|
24
|
+
# 0.0.2
|
25
|
+
|
26
|
+
* Added ability to create a partitioner consumer for a topic+partition using topic metadata.
|
27
|
+
* Added PartitionConsumer#offset to return offset of the last fetch
|
28
|
+
|
29
|
+
# 0.0.1
|
30
|
+
|
31
|
+
* Initial release
|
data/Gemfile
ADDED
@@ -0,0 +1,13 @@
|
|
1
|
+
source 'https://rubygems.org'
|
2
|
+
|
3
|
+
gem 'rake'
|
4
|
+
|
5
|
+
# Specify your gem's dependencies in poseidon.gemspec
|
6
|
+
gemspec
|
7
|
+
|
8
|
+
gem 'coveralls', require: false
|
9
|
+
|
10
|
+
group :development do
|
11
|
+
gem 'github-markup', :platform => :ruby
|
12
|
+
gem 'redcarpet', :platform => :ruby
|
13
|
+
end
|
data/LICENSE.txt
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
Copyright (c) 2013 Bob Potter
|
2
|
+
|
3
|
+
MIT License
|
4
|
+
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
6
|
+
a copy of this software and associated documentation files (the
|
7
|
+
"Software"), to deal in the Software without restriction, including
|
8
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
9
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
10
|
+
permit persons to whom the Software is furnished to do so, subject to
|
11
|
+
the following conditions:
|
12
|
+
|
13
|
+
The above copyright notice and this permission notice shall be
|
14
|
+
included in all copies or substantial portions of the Software.
|
15
|
+
|
16
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
17
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
18
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
19
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
20
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
21
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
22
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,72 @@
|
|
1
|
+
# Poseidon [![Build Status](https://travis-ci.org/bpot/poseidon.png?branch=master)](https://travis-ci.org/bpot/poseidon) [![Code Climate](https://codeclimate.com/github/bpot/poseidon.png)](https://codeclimate.com/github/bpot/poseidon)
|
2
|
+
|
3
|
+
Poseidon is a Kafka client. Poseidon only supports the 0.8 API and above.
|
4
|
+
|
5
|
+
**Until 1.0.0 this should be considered ALPHA software and not neccessarily production ready.**
|
6
|
+
|
7
|
+
## Usage
|
8
|
+
|
9
|
+
### API Documentation
|
10
|
+
|
11
|
+
* [Latest release](http://rubydoc.info/gems/poseidon)
|
12
|
+
* [Github master](http://rubydoc.info/github/bpot/poseidon)
|
13
|
+
|
14
|
+
### Installing a Kafka broker locally
|
15
|
+
|
16
|
+
Follow the [instructions](http://kafka.apache.org/documentation.html#quickstart) on the Kafka wiki to build Kafka 0.8 and get a test broker up and running.
|
17
|
+
|
18
|
+
### Sending messages to Kafka
|
19
|
+
|
20
|
+
```ruby
|
21
|
+
require 'poseidon'
|
22
|
+
|
23
|
+
producer = Poseidon::Producer.new(["localhost:9092"], "my_test_producer")
|
24
|
+
|
25
|
+
messages = []
|
26
|
+
messages << Poseidon::MessageToSend.new("topic1", "value1")
|
27
|
+
messages << Poseidon::MessageToSend.new("topic2", "value2")
|
28
|
+
producer.send_messages(messages)
|
29
|
+
```
|
30
|
+
|
31
|
+
More detailed [Poseidon::Producer](http://rubydoc.info/github/bpot/poseidon/Poseidon/Producer) documentation.
|
32
|
+
|
33
|
+
### Fetching messages from Kafka
|
34
|
+
|
35
|
+
```ruby
|
36
|
+
require 'poseidon'
|
37
|
+
|
38
|
+
consumer = Poseidon::PartitionConsumer.new("my_test_consumer", "localhost", 9092,
|
39
|
+
"topic1", 0, :earliest_offset)
|
40
|
+
|
41
|
+
loop do
|
42
|
+
messages = consumer.fetch
|
43
|
+
messages.each do |m|
|
44
|
+
puts m.value
|
45
|
+
end
|
46
|
+
end
|
47
|
+
```
|
48
|
+
|
49
|
+
More detailed [Poseidon::PartitionConsumer](http://rubydoc.info/github/bpot/poseidon/Poseidon/PartitionConsumer) documentation.
|
50
|
+
|
51
|
+
### Using snappy compression
|
52
|
+
|
53
|
+
To use snappy compression in your producers or consumers, install the [snappy](http://rubygems.org/gems/snappy) gem or simply add `gem 'snappy'` to your project's Gemfile.
|
54
|
+
|
55
|
+
## Semantic Versioning
|
56
|
+
|
57
|
+
This gem follows [SemVer](http://semver.org). In particular, the public API should not be considered stable and anything may change without warning until Version 1.0.0. Additionally, for the purposes of the versioning the public API is everything documented in the [public API docs](http://rubydoc.info/github/bpot/poseidon).
|
58
|
+
|
59
|
+
## Requirements
|
60
|
+
|
61
|
+
* Ruby 1.9.3 or higher (1.9.2 and below not supported!!!)
|
62
|
+
* Kafka 0.8 or higher
|
63
|
+
|
64
|
+
## Integration Tests
|
65
|
+
|
66
|
+
In order to run integration tests you must specify a `KAFKA_PATH` environment variable which points to a built Kafka installation. To build Kafka locally follow the [instructions](http://kafka.apache.org/documentation.html#quickstart) provided by the project.
|
67
|
+
|
68
|
+
# cd ~/src/poseidon/
|
69
|
+
# bundle
|
70
|
+
# KAFKA_PATH=~/src/kafka bundle exec rake spec:all # run all unit and integration specs
|
71
|
+
|
72
|
+
The poseidon test suite will take care of spinning up and down the broker(s) needed for the integration tests.
|
data/Rakefile
ADDED
@@ -0,0 +1,20 @@
|
|
1
|
+
require 'bundler/gem_tasks'
|
2
|
+
require 'rspec/core/rake_task'
|
3
|
+
|
4
|
+
RSpec::Core::RakeTask.new("spec:unit") do |t|
|
5
|
+
t.pattern = 'spec/unit/**/*_spec.rb'
|
6
|
+
end
|
7
|
+
|
8
|
+
RSpec::Core::RakeTask.new('spec:integration:simple') do |t|
|
9
|
+
t.pattern = 'spec/integration/simple/*_spec.rb'
|
10
|
+
t.rspec_opts = ["--fail-fast", "-f d"]
|
11
|
+
end
|
12
|
+
|
13
|
+
RSpec::Core::RakeTask.new('spec:integration:multiple_brokers') do |t|
|
14
|
+
t.pattern = 'spec/integration/multiple_brokers/*_spec.rb'
|
15
|
+
t.rspec_opts = ["--fail-fast", "-f d"]
|
16
|
+
end
|
17
|
+
|
18
|
+
task :spec => 'spec:unit'
|
19
|
+
task 'spec:all' => ['spec:unit', 'spec:integration:simple', 'spec:integration:multiple_brokers']
|
20
|
+
task :default => 'spec:unit'
|
data/TODO.md
ADDED
@@ -0,0 +1,27 @@
|
|
1
|
+
### 0.0.1
|
2
|
+
* Ensure that protocol errors are being handled correctly and not bubbling up
|
3
|
+
* More integration tests, replication, leader changes, etc. Investigate interesting cases in kafka's tests
|
4
|
+
* End-to-end integration specs
|
5
|
+
- In specs that test broker failure, verify that messages were actually sent/not sent with a consumer.
|
6
|
+
|
7
|
+
* AsyncProducer
|
8
|
+
- Implement a bounded queue, sending thread, etc
|
9
|
+
* Cleanup: extract protocol struct delegation to a module.
|
10
|
+
* When failing to send messages in sync producer, return messages that failed to send?
|
11
|
+
|
12
|
+
### 0.0.2
|
13
|
+
|
14
|
+
* New Consumer/Consumer Enhancements
|
15
|
+
- Automatically partition work among consumers (zookeeper, redis, pluggable?)
|
16
|
+
- Handle case where the offset we're trying to read from no longer exists
|
17
|
+
|
18
|
+
* Snappy Compression
|
19
|
+
- snappy: c-ext, would like to avoid
|
20
|
+
- snappy_ffi: ffi interface, but needs to be updated (pre c-api)
|
21
|
+
and has no specs, docs. Also linked to a c-ext version, two gems, etc..
|
22
|
+
- new snappy ffi library with specs, docs, etc. Shave that Yak!
|
23
|
+
|
24
|
+
* Benchmark/Profiling. KGIO?
|
25
|
+
|
26
|
+
### 0.0.3 -- Targets Kafka 0.8.1
|
27
|
+
- Offset API
|
@@ -0,0 +1,18 @@
|
|
1
|
+
$:.unshift File.expand_path(File.dirname(__FILE__) + '/../lib')
|
2
|
+
require 'poseidon'
|
3
|
+
|
4
|
+
producer = Poseidon::PartitionConsumer.new("example_consumer", "localhost", 9092,
|
5
|
+
"example", 0, :earliest_offset)
|
6
|
+
|
7
|
+
loop do
|
8
|
+
begin
|
9
|
+
messages = producer.fetch
|
10
|
+
messages.each do |m|
|
11
|
+
puts "Received message: #{m.value}"
|
12
|
+
end
|
13
|
+
rescue Poseidon::Errors::UnknownTopicOrPartition
|
14
|
+
puts "Topic does not exist yet"
|
15
|
+
end
|
16
|
+
|
17
|
+
sleep 1
|
18
|
+
end
|
@@ -0,0 +1,9 @@
|
|
1
|
+
$:.unshift File.expand_path(File.dirname(__FILE__) + '/../lib')
|
2
|
+
require 'poseidon'
|
3
|
+
|
4
|
+
producer = Poseidon::Producer.new(["localhost:9092"], "example_producer")
|
5
|
+
|
6
|
+
loop do
|
7
|
+
producer.send_messages([Poseidon::MessageToSend.new("example", Time.now.to_s)])
|
8
|
+
sleep 1
|
9
|
+
end
|
data/lib/poseidon.rb
ADDED
@@ -0,0 +1,120 @@
|
|
1
|
+
# Stdlib requires
|
2
|
+
require 'socket'
|
3
|
+
require 'zlib'
|
4
|
+
require 'thread'
|
5
|
+
require 'set'
|
6
|
+
require 'logger'
|
7
|
+
require 'stringio'
|
8
|
+
|
9
|
+
# Top level Poseidon namespace
|
10
|
+
#
|
11
|
+
# @api public
|
12
|
+
module Poseidon
|
13
|
+
# Posiedon exception namespace
|
14
|
+
module Errors
|
15
|
+
# @api private
|
16
|
+
class ProtocolError < StandardError; end
|
17
|
+
|
18
|
+
# Protocol Exceptions
|
19
|
+
#
|
20
|
+
# These are defined by the Poseidon wire format,
|
21
|
+
# they should be caught before being raised to users.
|
22
|
+
#
|
23
|
+
# @api private
|
24
|
+
class UnknownError < ProtocolError; end
|
25
|
+
# @api private
|
26
|
+
class OffsetOutOfRange < ProtocolError; end
|
27
|
+
# @api private
|
28
|
+
class InvalidMessage < ProtocolError; end
|
29
|
+
# @api private
|
30
|
+
class UnknownTopicOrPartition < ProtocolError; end
|
31
|
+
# @api private
|
32
|
+
class InvalidMessageSize < ProtocolError; end
|
33
|
+
# @api private
|
34
|
+
class LeaderNotAvailable < ProtocolError; end
|
35
|
+
# @api private
|
36
|
+
class NotLeaderForPartition < ProtocolError; end
|
37
|
+
# @api private
|
38
|
+
class RequestTimedOut < ProtocolError; end
|
39
|
+
# @api private
|
40
|
+
class BrokerNotAvailable < ProtocolError; end
|
41
|
+
# @api private
|
42
|
+
class ReplicaNotAvailable < ProtocolError; end
|
43
|
+
# @api private
|
44
|
+
class MessageSizeTooLarge < ProtocolError; end
|
45
|
+
# @api private
|
46
|
+
class UnrecognizedProtocolError < ProtocolError; end
|
47
|
+
|
48
|
+
# @api private
|
49
|
+
NO_ERROR_CODE = 0
|
50
|
+
# @api private
|
51
|
+
ERROR_CODES = {
|
52
|
+
-1 => UnknownError,
|
53
|
+
1 => OffsetOutOfRange,
|
54
|
+
2 => InvalidMessage,
|
55
|
+
3 => UnknownTopicOrPartition,
|
56
|
+
4 => InvalidMessageSize,
|
57
|
+
5 => LeaderNotAvailable,
|
58
|
+
6 => NotLeaderForPartition,
|
59
|
+
7 => RequestTimedOut,
|
60
|
+
8 => BrokerNotAvailable,
|
61
|
+
9 => ReplicaNotAvailable,
|
62
|
+
10 => MessageSizeTooLarge
|
63
|
+
}
|
64
|
+
|
65
|
+
# Raised when a custom partitioner tries to send
|
66
|
+
# a message to a partition that doesn't exist.
|
67
|
+
class InvalidPartitionError < StandardError; end
|
68
|
+
|
69
|
+
# Raised when we are unable to fetch metadata from
|
70
|
+
# any of the brokers.
|
71
|
+
class UnableToFetchMetadata < StandardError; end
|
72
|
+
|
73
|
+
# Raised when a messages checksum doesn't match
|
74
|
+
class ChecksumError < StandardError; end
|
75
|
+
|
76
|
+
# Raised when you try to send messages to a producer
|
77
|
+
# object that has been #shutdown
|
78
|
+
class ProducerShutdownError < StandardError; end
|
79
|
+
end
|
80
|
+
|
81
|
+
def self.logger
|
82
|
+
@logger ||= null_logger
|
83
|
+
end
|
84
|
+
|
85
|
+
def self.logger=(logger)
|
86
|
+
@logger = logger
|
87
|
+
end
|
88
|
+
|
89
|
+
private
|
90
|
+
def self.null_logger
|
91
|
+
devnull = RUBY_PLATFORM =~ /w32/ ? 'nul' : '/dev/null'
|
92
|
+
l = Logger.new(devnull)
|
93
|
+
l.level = Logger::INFO
|
94
|
+
l
|
95
|
+
end
|
96
|
+
end
|
97
|
+
|
98
|
+
# Public API
|
99
|
+
require "poseidon/message_to_send"
|
100
|
+
require "poseidon/producer"
|
101
|
+
require "poseidon/fetched_message"
|
102
|
+
require "poseidon/partition_consumer"
|
103
|
+
|
104
|
+
# Poseidon!
|
105
|
+
require "poseidon/message"
|
106
|
+
require "poseidon/message_set"
|
107
|
+
require "poseidon/topic_metadata"
|
108
|
+
require "poseidon/protocol"
|
109
|
+
|
110
|
+
require "poseidon/broker_pool"
|
111
|
+
require "poseidon/cluster_metadata"
|
112
|
+
require "poseidon/compression"
|
113
|
+
require "poseidon/connection"
|
114
|
+
require "poseidon/message_conductor"
|
115
|
+
require "poseidon/messages_for_broker"
|
116
|
+
require "poseidon/messages_to_send"
|
117
|
+
require "poseidon/messages_to_send_batch"
|
118
|
+
require "poseidon/producer_compression_config"
|
119
|
+
require "poseidon/sync_producer"
|
120
|
+
require "poseidon/version"
|
@@ -0,0 +1,86 @@
|
|
1
|
+
module Poseidon
|
2
|
+
# BrokerPool allows you to send api calls to the a brokers Connection.
|
3
|
+
#
|
4
|
+
# @api private
|
5
|
+
class BrokerPool
|
6
|
+
class UnknownBroker < StandardError; end
|
7
|
+
|
8
|
+
# @yieldparam [BrokerPool]
|
9
|
+
def self.open(client_id, seed_brokers, socket_timeout_ms, &block)
|
10
|
+
broker_pool = new(client_id, seed_brokers, socket_timeout_ms)
|
11
|
+
|
12
|
+
yield broker_pool
|
13
|
+
ensure
|
14
|
+
broker_pool.close
|
15
|
+
end
|
16
|
+
|
17
|
+
# @param [String] client_id
|
18
|
+
def initialize(client_id, seed_brokers, socket_timeout_ms)
|
19
|
+
@connections = {}
|
20
|
+
@brokers = {}
|
21
|
+
@client_id = client_id
|
22
|
+
@seed_brokers = seed_brokers
|
23
|
+
@socket_timeout_ms = socket_timeout_ms
|
24
|
+
end
|
25
|
+
|
26
|
+
def fetch_metadata(topics)
|
27
|
+
@seed_brokers.each do |broker|
|
28
|
+
if metadata = fetch_metadata_from_broker(broker, topics)
|
29
|
+
Poseidon.logger.debug { "Fetched metadata from #{broker}:\n" + metadata.to_s }
|
30
|
+
return metadata
|
31
|
+
end
|
32
|
+
end
|
33
|
+
raise Errors::UnableToFetchMetadata
|
34
|
+
end
|
35
|
+
|
36
|
+
# Update the brokers we know about
|
37
|
+
#
|
38
|
+
# TODO break connection when a brokers info changes?
|
39
|
+
#
|
40
|
+
# @param [Hash<Integer,Hash>] brokers
|
41
|
+
# Hash of broker_id => { :host => host, :port => port }
|
42
|
+
def update_known_brokers(brokers)
|
43
|
+
@brokers.update(brokers)
|
44
|
+
nil
|
45
|
+
end
|
46
|
+
|
47
|
+
# Executes an api call on the connection
|
48
|
+
#
|
49
|
+
# @param [Integer] broker_id id of the broker we want to execute it on
|
50
|
+
# @param [Symbol] api_call
|
51
|
+
# the api call we want to execute (:produce,:fetch,etc)
|
52
|
+
def execute_api_call(broker_id, api_call, *args)
|
53
|
+
connection(broker_id).send(api_call, *args)
|
54
|
+
end
|
55
|
+
|
56
|
+
# Closes all open connections to brokers
|
57
|
+
def close
|
58
|
+
@brokers.values(&:close)
|
59
|
+
@brokers = {}
|
60
|
+
end
|
61
|
+
|
62
|
+
alias_method :shutdown, :close
|
63
|
+
|
64
|
+
private
|
65
|
+
def fetch_metadata_from_broker(broker, topics)
|
66
|
+
host, port = broker.split(":")
|
67
|
+
Connection.open(host, port, @client_id, @socket_timeout_ms) do |connection|
|
68
|
+
connection.topic_metadata(topics)
|
69
|
+
end
|
70
|
+
rescue Connection::ConnectionFailedError
|
71
|
+
return nil
|
72
|
+
end
|
73
|
+
|
74
|
+
def connection(broker_id)
|
75
|
+
@connections[broker_id] ||= new_connection(broker_id)
|
76
|
+
end
|
77
|
+
|
78
|
+
def new_connection(broker_id)
|
79
|
+
info = @brokers[broker_id]
|
80
|
+
if info.nil?
|
81
|
+
raise UnknownBroker
|
82
|
+
end
|
83
|
+
Connection.new(info[:host], info[:port], @client_id, @socket_timeout_ms)
|
84
|
+
end
|
85
|
+
end
|
86
|
+
end
|