hermann 0.16.0 → 0.17.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/Rakefile +15 -2
- data/lib/hermann/consumer.rb +7 -2
- data/lib/hermann/discovery/zookeeper.rb +80 -0
- data/lib/hermann/producer.rb +18 -3
- data/lib/hermann/provider/java_producer.rb +64 -0
- data/lib/hermann/version.rb +1 -1
- data/lib/hermann.rb +18 -0
- data/lib/hermann_jars.rb +15 -0
- metadata +33 -10
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: b08abedfd6c15b1c7c1aa5dfe66315501c212512
|
4
|
+
data.tar.gz: 3bf7306d482a260fd73004e4d8087cd5f3a1f063
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 901a4eecf276229c561186f5be901b6ed87313d35d6878365621ee0302328870f24fe02661620d633f4e55462aaf953a8036c3da88d5d6e6d66c7e71e9e6a9d4
|
7
|
+
data.tar.gz: 300db74c52df5be4f01078b6098c9a0cd528da811c4681e2fb0dde337c7b5b9bfe1cbe645769f9c616adbc9cfe5a841d9413f2d51208518e2dd1a20a4fce57cf
|
data/Rakefile
CHANGED
@@ -12,7 +12,15 @@ Rake::ExtensionTask.new do |t|
|
|
12
12
|
end
|
13
13
|
|
14
14
|
RSpec::Core::RakeTask.new(:spec) do |r|
|
15
|
-
|
15
|
+
options = ['--tag ~type:integration']
|
16
|
+
|
17
|
+
if RUBY_PLATFORM == 'java'
|
18
|
+
options << '--tag ~platform:mri'
|
19
|
+
else
|
20
|
+
options << '--tag ~platform:java'
|
21
|
+
end
|
22
|
+
|
23
|
+
r.rspec_opts = options.join(' ')
|
16
24
|
end
|
17
25
|
|
18
26
|
namespace :spec do
|
@@ -29,5 +37,10 @@ end
|
|
29
37
|
|
30
38
|
task :build => [:compile]
|
31
39
|
task :clean => [:removetmp]
|
32
|
-
|
40
|
+
|
41
|
+
if RUBY_PLATFORM == 'java'
|
42
|
+
task :default => [:clean, :spec]
|
43
|
+
else
|
44
|
+
task :default => [:clean, :build, :spec]
|
45
|
+
end
|
33
46
|
|
data/lib/hermann/consumer.rb
CHANGED
@@ -1,5 +1,8 @@
|
|
1
1
|
require 'hermann'
|
2
|
-
|
2
|
+
|
3
|
+
unless Hermann.jruby?
|
4
|
+
require 'hermann_lib'
|
5
|
+
end
|
3
6
|
|
4
7
|
module Hermann
|
5
8
|
class Consumer
|
@@ -9,7 +12,9 @@ module Hermann
|
|
9
12
|
@topic = topic
|
10
13
|
@brokers = brokers
|
11
14
|
@partition = partition
|
12
|
-
|
15
|
+
unless Hermann.jruby?
|
16
|
+
@internal = Hermann::Lib::Consumer.new(topic, brokers, partition)
|
17
|
+
end
|
13
18
|
end
|
14
19
|
|
15
20
|
def consume(&block)
|
@@ -0,0 +1,80 @@
|
|
1
|
+
require 'hermann'
|
2
|
+
require 'zk'
|
3
|
+
require 'json'
|
4
|
+
|
5
|
+
module Hermann
|
6
|
+
module Discovery
|
7
|
+
class NoBrokersError < StandardError; end
|
8
|
+
|
9
|
+
# Communicates with Zookeeper to discover kafka broker ids
|
10
|
+
#
|
11
|
+
class Zookeeper
|
12
|
+
attr_reader :zookeepers
|
13
|
+
|
14
|
+
BROKERS_PATH = "/brokers/ids".freeze
|
15
|
+
|
16
|
+
def initialize(zookeepers)
|
17
|
+
@zookeepers = zookeepers
|
18
|
+
end
|
19
|
+
|
20
|
+
# Gets comma separated string of brokers
|
21
|
+
#
|
22
|
+
# @param [Fixnum] timeout to connect to zookeeper, "2 times the
|
23
|
+
# tickTime (as set in the server configuration) and a maximum
|
24
|
+
# of 20 times the tickTime2 times the tick time set on server"
|
25
|
+
#
|
26
|
+
# @return [String] comma separated list of brokers
|
27
|
+
def get_brokers(timeout=0)
|
28
|
+
brokers = []
|
29
|
+
ZK.open(zookeepers, {:timeout => timeout}) do |zk|
|
30
|
+
brokers = fetch_brokers(zk)
|
31
|
+
end
|
32
|
+
raise NoBrokersError if brokers.empty?
|
33
|
+
brokers.join(',')
|
34
|
+
end
|
35
|
+
|
36
|
+
private
|
37
|
+
|
38
|
+
# Gets an Array of broker strings
|
39
|
+
#
|
40
|
+
# @param [ZK::Client] zookeeper client
|
41
|
+
#
|
42
|
+
# @return array of broker strings
|
43
|
+
def fetch_brokers(zk)
|
44
|
+
brokers = []
|
45
|
+
zk.children(BROKERS_PATH).each do |id|
|
46
|
+
node = fetch_znode(zk, id)
|
47
|
+
next if node.nil? # whatever error could happen from ZK#get
|
48
|
+
brokers << format_broker_from_znode(node)
|
49
|
+
end
|
50
|
+
brokers.compact
|
51
|
+
end
|
52
|
+
|
53
|
+
# Gets node from zookeeper
|
54
|
+
#
|
55
|
+
# @param [ZK::Client] zookeeper client
|
56
|
+
# @param [Fixnum] kafka broker
|
57
|
+
#
|
58
|
+
# @return [String] node data
|
59
|
+
def fetch_znode(zk, id)
|
60
|
+
zk.get("#{BROKERS_PATH}/#{id}")[0]
|
61
|
+
rescue ZK::Exceptions::NoNode
|
62
|
+
nil
|
63
|
+
end
|
64
|
+
|
65
|
+
# Formats the node data into string
|
66
|
+
#
|
67
|
+
# @param [String] node data
|
68
|
+
#
|
69
|
+
# @return [String] formatted node data or empty string if error
|
70
|
+
def format_broker_from_znode(znode)
|
71
|
+
hash = JSON.parse(znode)
|
72
|
+
host = hash['host']
|
73
|
+
port = hash['port']
|
74
|
+
host && port ? "#{host}:#{port}" : nil
|
75
|
+
rescue JSON::ParserError
|
76
|
+
nil
|
77
|
+
end
|
78
|
+
end
|
79
|
+
end
|
80
|
+
end
|
data/lib/hermann/producer.rb
CHANGED
@@ -1,6 +1,12 @@
|
|
1
1
|
require 'hermann'
|
2
2
|
require 'hermann/result'
|
3
|
-
|
3
|
+
|
4
|
+
|
5
|
+
if RUBY_PLATFORM == "java"
|
6
|
+
require 'hermann/provider/java_producer'
|
7
|
+
else
|
8
|
+
require 'hermann_lib'
|
9
|
+
end
|
4
10
|
|
5
11
|
module Hermann
|
6
12
|
class Producer
|
@@ -9,7 +15,11 @@ module Hermann
|
|
9
15
|
def initialize(topic, brokers)
|
10
16
|
@topic = topic
|
11
17
|
@brokers = brokers
|
12
|
-
|
18
|
+
if RUBY_PLATFORM == "java"
|
19
|
+
@internal = Hermann::Provider::JavaProducer.new(topic, brokers)
|
20
|
+
else
|
21
|
+
@internal = Hermann::Lib::Producer.new(topic, brokers)
|
22
|
+
end
|
13
23
|
# We're tracking children so we can make sure that at Producer exit we
|
14
24
|
# make a reasonable attempt to clean up outstanding result objects
|
15
25
|
@children = []
|
@@ -43,7 +53,12 @@ module Hermann
|
|
43
53
|
if value.kind_of? Array
|
44
54
|
return value.map { |e| self.push(e) }
|
45
55
|
else
|
46
|
-
|
56
|
+
if RUBY_PLATFORM == "java"
|
57
|
+
result = @internal.push_single(value)
|
58
|
+
@children << result
|
59
|
+
else
|
60
|
+
@internal.push_single(value, result)
|
61
|
+
end
|
47
62
|
end
|
48
63
|
|
49
64
|
return result
|
@@ -0,0 +1,64 @@
|
|
1
|
+
require 'hermann'
|
2
|
+
require 'concurrent'
|
3
|
+
require 'json'
|
4
|
+
|
5
|
+
module Hermann
|
6
|
+
module Provider
|
7
|
+
|
8
|
+
# This class simulates the kafka producer class within a java environment.
|
9
|
+
# If the producer throw an exception within the Promise a call to +.value!+
|
10
|
+
# will raise the exception and the rejected flag will be set to true
|
11
|
+
#
|
12
|
+
class JavaProducer
|
13
|
+
attr_accessor :topic, :producer
|
14
|
+
|
15
|
+
def initialize(topic, brokers)
|
16
|
+
@topic = topic
|
17
|
+
properties = create_properties(:brokers => brokers)
|
18
|
+
config = create_config(properties)
|
19
|
+
@producer = JavaApiUtil::Producer.new(config)
|
20
|
+
end
|
21
|
+
|
22
|
+
DEFAULTS = {
|
23
|
+
:string_encoder => 'kafka.serializer.StringEncoder',
|
24
|
+
:partitioner => 'kafka.producer.DefaultPartitioner',
|
25
|
+
:required_acks => "1"
|
26
|
+
}.freeze
|
27
|
+
|
28
|
+
# Push a value onto the Kafka topic passed to this +Producer+
|
29
|
+
#
|
30
|
+
# @param [Object] value A single object to push
|
31
|
+
#
|
32
|
+
# @return +Concurrent::Promise+ Representa a promise to send the
|
33
|
+
# data to the kafka broker. Upon execution the Promise's status
|
34
|
+
# will be set
|
35
|
+
def push_single(msg)
|
36
|
+
Concurrent::Promise.execute {
|
37
|
+
data = ProducerUtil::KeyedMessage.new(@topic, msg)
|
38
|
+
@producer.send(data)
|
39
|
+
}
|
40
|
+
end
|
41
|
+
|
42
|
+
private
|
43
|
+
# @return [ProducerConfig] - packaged config for +Producer+
|
44
|
+
def create_config(properties)
|
45
|
+
ProducerUtil::ProducerConfig.new(properties)
|
46
|
+
end
|
47
|
+
|
48
|
+
# @return [Properties] properties object for creating +ProducerConfig+
|
49
|
+
def create_properties(args={})
|
50
|
+
brokers = args[:brokers]
|
51
|
+
str_encoder = DEFAULTS[:string_encoder]
|
52
|
+
partitioner = DEFAULTS[:partitioner]
|
53
|
+
acks = DEFAULTS[:required_acks]
|
54
|
+
|
55
|
+
properties = JavaUtil::Properties.new
|
56
|
+
properties.put('metadata.broker.list', brokers)
|
57
|
+
properties.put('serializer.class', str_encoder)
|
58
|
+
properties.put('partitioner.class', partitioner)
|
59
|
+
properties.put('request.required.acks', acks)
|
60
|
+
properties
|
61
|
+
end
|
62
|
+
end
|
63
|
+
end
|
64
|
+
end
|
data/lib/hermann/version.rb
CHANGED
data/lib/hermann.rb
CHANGED
@@ -1,2 +1,20 @@
|
|
1
1
|
module Hermann
|
2
|
+
def self.jruby?
|
3
|
+
return RUBY_PLATFORM == "java"
|
4
|
+
end
|
5
|
+
|
6
|
+
if self.jruby?
|
7
|
+
require 'java'
|
8
|
+
require 'hermann_jars'
|
9
|
+
|
10
|
+
module JavaUtil
|
11
|
+
include_package 'java.util'
|
12
|
+
end
|
13
|
+
module ProducerUtil
|
14
|
+
include_package 'kafka.producer'
|
15
|
+
end
|
16
|
+
module JavaApiUtil
|
17
|
+
include_package 'kafka.javaapi.producer'
|
18
|
+
end
|
19
|
+
end
|
2
20
|
end
|
data/lib/hermann_jars.rb
ADDED
@@ -0,0 +1,15 @@
|
|
1
|
+
# this is a generated file, to avoid over-writing it just delete this comment
|
2
|
+
require 'jar_dependencies'
|
3
|
+
|
4
|
+
require_jar( 'org.slf4j', 'slf4j-api', '1.7.2' )
|
5
|
+
require_jar( 'org.scala-lang', 'scala-library', '2.10.1' )
|
6
|
+
require_jar( 'log4j', 'log4j', '1.2.14' )
|
7
|
+
require_jar( 'com.yammer.metrics', 'metrics-core', '2.2.0' )
|
8
|
+
require_jar( 'org.apache.zookeeper', 'zookeeper', '3.3.4' )
|
9
|
+
require_jar( 'net.sf.jopt-simple', 'jopt-simple', '3.2' )
|
10
|
+
require_jar( 'org.apache.kafka', 'kafka_2.10', '0.8.1.1' )
|
11
|
+
require_jar( 'jline', 'jline', '0.9.94' )
|
12
|
+
require_jar( 'com.101tec', 'zkclient', '0.3' )
|
13
|
+
require_jar( 'org.mod4j.org.eclipse.xtext', 'log4j', '1.2.15' )
|
14
|
+
require_jar( 'junit', 'junit', '3.8.1' )
|
15
|
+
require_jar( 'org.xerial.snappy', 'snappy-java', '1.0.5' )
|
metadata
CHANGED
@@ -1,31 +1,51 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: hermann
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.17.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
|
-
- Stan Campbell
|
8
7
|
- R. Tyler Croy
|
8
|
+
- Stan Campbell
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
12
|
|
13
|
-
date: 2014-
|
13
|
+
date: 2014-10-10 00:00:00 Z
|
14
14
|
dependencies:
|
15
15
|
- !ruby/object:Gem::Dependency
|
16
|
-
name:
|
16
|
+
name: concurrent-ruby
|
17
17
|
requirement: &id001 !ruby/object:Gem::Requirement
|
18
18
|
requirements:
|
19
19
|
- - ~>
|
20
20
|
- !ruby/object:Gem::Version
|
21
|
-
version: 0.
|
21
|
+
version: 0.7.0
|
22
22
|
type: :runtime
|
23
23
|
prerelease: false
|
24
24
|
version_requirements: *id001
|
25
|
-
|
25
|
+
- !ruby/object:Gem::Dependency
|
26
|
+
name: zk
|
27
|
+
requirement: &id002 !ruby/object:Gem::Requirement
|
28
|
+
requirements:
|
29
|
+
- - ~>
|
30
|
+
- !ruby/object:Gem::Version
|
31
|
+
version: 1.9.4
|
32
|
+
type: :runtime
|
33
|
+
prerelease: false
|
34
|
+
version_requirements: *id002
|
35
|
+
- !ruby/object:Gem::Dependency
|
36
|
+
name: mini_portile
|
37
|
+
requirement: &id003 !ruby/object:Gem::Requirement
|
38
|
+
requirements:
|
39
|
+
- - ~>
|
40
|
+
- !ruby/object:Gem::Version
|
41
|
+
version: 0.6.0
|
42
|
+
type: :runtime
|
43
|
+
prerelease: false
|
44
|
+
version_requirements: *id003
|
45
|
+
description: Ruby gem for talking to Kafka
|
26
46
|
email:
|
27
|
-
- stan.campbell3@gmail.com
|
28
47
|
- rtyler.croy@lookout.com
|
48
|
+
- stan.campbell3@gmail.com
|
29
49
|
executables: []
|
30
50
|
|
31
51
|
extensions:
|
@@ -40,11 +60,14 @@ files:
|
|
40
60
|
- ext/patches/librdkafka/0006-Update-some-headers-to-include-the-right-headers-to-.patch
|
41
61
|
- lib/hermann.rb
|
42
62
|
- lib/hermann/consumer.rb
|
63
|
+
- lib/hermann/discovery/zookeeper.rb
|
43
64
|
- lib/hermann/errors.rb
|
44
65
|
- lib/hermann/producer.rb
|
66
|
+
- lib/hermann/provider/java_producer.rb
|
45
67
|
- lib/hermann/result.rb
|
46
68
|
- lib/hermann/timeout.rb
|
47
69
|
- lib/hermann/version.rb
|
70
|
+
- lib/hermann_jars.rb
|
48
71
|
homepage: https://github.com/lookout/Hermann
|
49
72
|
licenses:
|
50
73
|
- MIT
|
@@ -58,19 +81,19 @@ require_paths:
|
|
58
81
|
- ext/hermann
|
59
82
|
required_ruby_version: !ruby/object:Gem::Requirement
|
60
83
|
requirements:
|
61
|
-
- &
|
84
|
+
- &id004
|
62
85
|
- ">="
|
63
86
|
- !ruby/object:Gem::Version
|
64
87
|
version: "0"
|
65
88
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
66
89
|
requirements:
|
67
|
-
- *
|
90
|
+
- *id004
|
68
91
|
requirements: []
|
69
92
|
|
70
93
|
rubyforge_project:
|
71
94
|
rubygems_version: 2.4.1
|
72
95
|
signing_key:
|
73
96
|
specification_version: 3
|
74
|
-
summary: A Kafka consumer/producer gem
|
97
|
+
summary: A Kafka consumer/producer gem supporting both MRI and JRuby
|
75
98
|
test_files: []
|
76
99
|
|