stapfen 2.1.1 → 2.2.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: 19bdf4344cf49d95cee8597de1902b9a814a1b90
4
- data.tar.gz: 06ad77a4f72ea1cce8269e92a19ce2cf6872474b
3
+ metadata.gz: 01629a450316fa2089bd559e2ec2df8bb3b79fe7
4
+ data.tar.gz: 84ad17b10f341ca81c599e5aadd7d13fce04cb42
5
5
  SHA512:
6
- metadata.gz: 09b0dfd450a6e4387250b0d0c4b49734891ea5f07db900b7cdb33412b731352b5cd0a192663b898e383030c2938710f29238716b0b793d181adbed35157155aa
7
- data.tar.gz: 79104895c26a380204fe1cddbe0304e255e87d522ada0c1c38fe7dad16457b10d9bec4bdb82cd44b55f21bd21ecc09cba1ec8b8abc2287cf2a23663f23ed10b3
6
+ metadata.gz: 24f9f0557fa24b518b7b957010c4de14db38c04ad4dd81d7f900ece3e783e577f37d2f8fe3226e9896f2409ed1cb92e7e760b078344308d887049e8cef64a890
7
+ data.tar.gz: 82ecce67fb2b23c3cb73d47a356de210ef5ebc6f72a03a3fa1108cc1e87e95e47826000965a8c96884fcb5ff2e6db6777acea7dc5dbebf6507a423e40e7dc14a
data/.gitignore CHANGED
@@ -16,3 +16,4 @@ test/tmp
16
16
  test/version_tmp
17
17
  tmp
18
18
  .rvmrc
19
+ activemq-all-5.8.0.jar
data/Gemfile CHANGED
@@ -8,7 +8,8 @@ gem 'stomp', '>= 1.2.14'
8
8
 
9
9
  group :development do
10
10
  gem 'rake'
11
- gem 'rspec', '~> 2.11'
11
+ gem 'rspec'
12
+ gem 'rspec-its'
12
13
  gem 'pry'
13
14
  gem 'debugger', :platform => :mri
14
15
  gem 'debugger-pry', :platform => :mri
data/README.md CHANGED
@@ -77,8 +77,8 @@ care when accessing other shared resources.
77
77
 
78
78
  The consume block accepts the usual subscriptions headers, as well as two
79
79
  additional headers `:dead_letter_queue` and `:max_redeliveries`. If either of
80
- the latter two is present, the honsumer will unreceive any messages for which
81
- the block returns `false`; after `:max\_redeliveries`, it will send the message
80
+ the latter two is present, the consumer will unreceive any messages for which
81
+ the block returns `false`; after `:max_redeliveries`, it will send the message
82
82
  to `:dead_letter_queue`. `consume` blocks without these headers will fail
83
83
  silently rather than unreceive.
84
84
 
@@ -97,3 +97,10 @@ Or install it yourself as:
97
97
 
98
98
  $ gem install stapfen
99
99
 
100
+ ## Running Specs
101
+
102
+ Download this from jar from Maven Central
103
+ * [activemq-all-5.8.0.jar](http://search.maven.org/#artifactdetails%7Corg.apache.activemq%7Cactivemq-all%7C5.8.0%7Cjar)
104
+ * Put it in gem root
105
+ * ```rake spec```
106
+
@@ -0,0 +1,76 @@
1
+ begin
2
+ require 'hermann'
3
+ require 'hermann/consumer'
4
+ rescue LoadError => e
5
+ if RUBY_PLATFORM == 'java'
6
+ raise
7
+ end
8
+ end
9
+
10
+ require 'stapfen/destination'
11
+
12
+ module Stapfen
13
+ module Client
14
+ class Kafka
15
+ attr_reader :connection, :producer
16
+
17
+ # Initialize a Kafka client object
18
+ #
19
+ # @params [Hash] configuration object
20
+ # @option configuration [String] :topic The kafka topic
21
+ # @option configuration [String] :groupId The kafka groupId
22
+ # @option configuration [String] :zookeepers List of zookeepers
23
+ #
24
+ # @raises [ConfigurationError] if required configs are not present
25
+ def initialize(configuration)
26
+ super()
27
+ @config = configuration
28
+ @topic = @config[:topic]
29
+ @groupId = @config[:groupId]
30
+ @zookeepers = @config[:zookeepers]
31
+ raise ConfigurationError unless @topic && @groupId && @zookeepers
32
+ @connection = Hermann::Consumer.new(@topic, @groupId, @zookeepers)
33
+ end
34
+
35
+ # This method is not implemenented
36
+ def connect(*args)
37
+ # No-op
38
+ end
39
+
40
+ # Cannot unreceive
41
+ def can_unreceive?
42
+ false
43
+ end
44
+
45
+ # Closes the consumer threads created by kafka.
46
+ #
47
+ # @return [Boolean] True/false depending on whether we actually closed
48
+ # the connection
49
+ def close
50
+ return false unless @connection
51
+ @connection.shutdown
52
+ @connection = nil
53
+ return true
54
+ end
55
+
56
+ # Subscribes to a destination (i.e. kafka topic) and consumes messages
57
+ #
58
+ # @params [Destination] source of messages to consume
59
+ #
60
+ # @params [Hash] Not used
61
+ #
62
+ # @params [block] block to yield consumed messages
63
+ def subscribe(destination, headers={}, &block)
64
+ destination = Stapfen::Destination.from_string(destination)
65
+ connection.consume(destination.as_kafka, &block)
66
+ end
67
+
68
+ def runloop
69
+ loop do
70
+ sleep 1
71
+ end
72
+ end
73
+
74
+ end
75
+ end
76
+ end
@@ -40,6 +40,10 @@ module Stapfen
40
40
  end
41
41
  end
42
42
 
43
+ def as_kafka
44
+ return name
45
+ end
46
+
43
47
  # Create a {Stapfen::Destination} from the given string
44
48
  #
45
49
  # @param [String] name
@@ -1,14 +1,13 @@
1
-
2
1
  module Stapfen
3
2
  class Message
4
3
  attr_reader :message_id, :body, :original, :destination
5
4
 
6
5
  def initialize(opts={})
7
6
  super()
8
- @body = opts[:body]
7
+ @body = opts[:body]
9
8
  @destination = opts[:destination]
10
- @message_id = opts[:message_id]
11
- @original = opts[:original]
9
+ @message_id = opts[:message_id]
10
+ @original = opts[:original]
12
11
  end
13
12
 
14
13
  # Create an instance of {Stapfen::Message} from the passed in
@@ -42,5 +41,18 @@ module Stapfen
42
41
  :message_id => message.jms_message_id,
43
42
  :original => message)
44
43
  end
44
+
45
+ # Create an instance of {Stapfen::Message} from the passed in
46
+ # +String+ which a Kafka consumer should receive
47
+ #
48
+ # @param [String] message
49
+ # @return [Stapfen::Message] A Stapfen wrapper object
50
+ def self.from_kafka(message)
51
+ unless message.kind_of? String
52
+ raise Stapfen::InvalidMessageError, message.inspect
53
+ end
54
+
55
+ return self.new(:body => message)
56
+ end
45
57
  end
46
58
  end
@@ -1,3 +1,3 @@
1
1
  module Stapfen
2
- VERSION = '2.1.1'
2
+ VERSION = '2.2.0'
3
3
  end
@@ -47,12 +47,12 @@ module Stapfen
47
47
  raise
48
48
  end
49
49
 
50
- @use_stomp = true
50
+ @protocol = 'stomp'
51
51
  return true
52
52
  end
53
53
 
54
54
  def self.stomp?
55
- @use_stomp.nil? || @use_stomp
55
+ @protocol.nil? || @protocol == 'stomp'
56
56
  end
57
57
 
58
58
  # Force the worker to use JMS as the messaging protocol.
@@ -73,12 +73,38 @@ module Stapfen
73
73
  raise
74
74
  end
75
75
 
76
- @use_stomp = false
76
+ @protocol = 'jms'
77
77
  return true
78
78
  end
79
79
 
80
80
  def self.jms?
81
- !(stomp?)
81
+ @protocol == 'jms'
82
+ end
83
+
84
+ # Force the worker to use Kafka as the messaging protocol.
85
+ #
86
+ # *Note:* Only works under JRuby
87
+ #
88
+ # @return [Boolean]
89
+ def self.use_kafka!
90
+ unless RUBY_PLATFORM == 'java'
91
+ raise Stapfen::ConfigurationError, "You cannot use Kafka unless you're running under JRuby!"
92
+ end
93
+
94
+ begin
95
+ require 'java'
96
+ require 'hermann'
97
+ rescue LoadError
98
+ puts "You need the `hermann` gem to be installed to use Kafka!"
99
+ raise
100
+ end
101
+
102
+ @protocol = 'kafka'
103
+ return true
104
+ end
105
+
106
+ def self.kafka?
107
+ @protocol == 'kafka'
82
108
  end
83
109
 
84
110
  # Optional method, should be passed a block which will yield a {{Logger}}
@@ -164,6 +190,9 @@ module Stapfen
164
190
  elsif self.class.jms?
165
191
  require 'stapfen/client/jms'
166
192
  @client = Stapfen::Client::JMS.new(self.class.configuration.call)
193
+ elsif self.class.kafka?
194
+ require 'stapfen/client/kafka'
195
+ @client = Stapfen::Client::Kafka.new(self.class.configuration.call)
167
196
  end
168
197
 
169
198
  debug("Running with #{@client} inside of Thread:#{Thread.current.inspect}")
@@ -192,6 +221,10 @@ module Stapfen
192
221
  message = Stapfen::Message.from_jms(m)
193
222
  end
194
223
 
224
+ if self.class.kafka?
225
+ message = Stapfen::Message.from_kafka(m)
226
+ end
227
+
195
228
  success = self.send(method_name, message)
196
229
 
197
230
  unless success
data/lib/stapfen.rb CHANGED
@@ -11,7 +11,6 @@ rescue LoadError
11
11
  # Can't process JMS
12
12
  end
13
13
 
14
-
15
14
  require 'stapfen/version'
16
15
  require 'stapfen/client'
17
16
  require 'stapfen/worker'
@@ -12,7 +12,7 @@ if RUBY_PLATFORM == 'java'
12
12
  describe '#can_unreceive?' do
13
13
  subject { client.can_unreceive? }
14
14
 
15
- it { should be_true }
15
+ it { should be true }
16
16
  end
17
17
 
18
18
  describe '#unreceive' do
@@ -158,11 +158,11 @@ if RUBY_PLATFORM == 'java'
158
158
  client.stub(:connection).and_return(double('JMS::Connection'))
159
159
  end
160
160
 
161
- it { should be_false }
161
+ it { should be false }
162
162
  end
163
163
 
164
164
  context 'without a connection' do
165
- it { should be_true }
165
+ it { should be true }
166
166
  end
167
167
  end
168
168
 
@@ -177,7 +177,7 @@ if RUBY_PLATFORM == 'java'
177
177
  context 'without an existing session' do
178
178
  it 'should close the client' do
179
179
  connection.should_receive(:close)
180
- expect(result).to be_true
180
+ expect(result).to be true
181
181
  end
182
182
  end
183
183
 
@@ -191,7 +191,7 @@ if RUBY_PLATFORM == 'java'
191
191
  it 'should close the client and session' do
192
192
  session.should_receive(:close)
193
193
  connection.should_receive(:close)
194
- expect(result).to be_true
194
+ expect(result).to be true
195
195
  end
196
196
  end
197
197
  end
@@ -0,0 +1,54 @@
1
+ require 'spec_helper'
2
+
3
+ require 'stapfen/client/kafka'
4
+
5
+ describe Stapfen::Client::Kafka, :java => true do
6
+ let(:config) { { :topic => 'test', :groupId => 'groupId', :zookeepers => 'foo' } }
7
+ let(:consumer) { double('Hermann::Consumer') }
8
+
9
+ subject(:client) { described_class.new(config) }
10
+
11
+ before do
12
+ allow(Hermann::Consumer).to receive(:new) { consumer }
13
+ end
14
+
15
+ it { should respond_to :connect }
16
+
17
+ describe '#can_unreceive?' do
18
+ subject { client.can_unreceive? }
19
+ it { should be false }
20
+ end
21
+
22
+ describe '#close' do
23
+ subject(:result) { client.close }
24
+
25
+ context 'with a connection' do
26
+ it 'should close the client' do
27
+ allow(consumer).to receive(:shutdown)
28
+ expect(result).to be true
29
+ end
30
+ end
31
+ context 'without a connection' do
32
+ it 'returns false' do
33
+ expect(Hermann::Consumer).to receive(:new) { nil }
34
+ expect(consumer).to_not receive(:shutdown)
35
+ expect(result).to be false
36
+ end
37
+ end
38
+ end
39
+
40
+ describe '#subscribe' do
41
+ let(:topic) { 'topic' }
42
+ let(:destination) { double('Destination') }
43
+ let(:msg) { 'foo' }
44
+ it 'yields to the block and passes in consumed message' do
45
+ allow(destination).to receive(:as_kafka) { topic }
46
+ allow(Stapfen::Destination).to receive(:from_string) { destination }
47
+ allow(consumer).to receive(:consume).with(topic).and_yield(msg)
48
+
49
+ expect{ |b|
50
+ client.subscribe(destination, nil, &b)
51
+ }.to yield_with_args(msg)
52
+ end
53
+ end
54
+ end
@@ -5,6 +5,19 @@ describe Stapfen::Destination do
5
5
  it { should respond_to :name }
6
6
  it { should respond_to :type }
7
7
 
8
+ describe '#as_kafka' do
9
+ let(:name) { 'topic' }
10
+ subject(:destination) do
11
+ d = described_class.new
12
+ d.type = :topic
13
+ d.name = name
14
+ d.as_kafka
15
+ end
16
+
17
+ it { should be_instance_of String }
18
+ it { should eql "topic" }
19
+ end
20
+
8
21
  describe '#as_jms' do
9
22
  let(:name) { 'rspec/dlq' }
10
23
  subject(:destination) do
data/spec/logger_spec.rb CHANGED
@@ -21,7 +21,7 @@ describe Stapfen::Logger do
21
21
  end
22
22
 
23
23
  it 'should discard info messages' do
24
- expect(logger.info('rspec')).to be_false
24
+ expect(logger.info('rspec')).to be false
25
25
  end
26
26
  end
27
27
 
@@ -34,8 +34,7 @@ describe Stapfen::Logger do
34
34
 
35
35
  it 'should pass info messages along' do
36
36
  plogger.should_receive(:info)
37
-
38
- expect(logger.info('rspec')).to be_true
37
+ expect(logger.info('rspec')).to be true
39
38
  end
40
39
  end
41
40
  end
data/spec/spec_helper.rb CHANGED
@@ -1,7 +1,7 @@
1
1
  $LOAD_PATH.unshift(File.expand_path(File.dirname(__FILE__) + '../lib'))
2
2
 
3
3
  require 'stapfen'
4
-
4
+ require 'rspec/its'
5
5
 
6
6
  is_java = (RUBY_PLATFORM == 'java')
7
7
 
@@ -12,6 +12,9 @@ end
12
12
 
13
13
 
14
14
  RSpec.configure do |c|
15
+ c.color = true
16
+ c.order = "random"
17
+
15
18
  unless is_java
16
19
  c.filter_run_excluding :java => true
17
20
  end
data/spec/worker_spec.rb CHANGED
@@ -17,7 +17,7 @@ describe Stapfen::Worker do
17
17
  subject(:result) { worker.use_stomp! }
18
18
 
19
19
  it 'should update the instance variable' do
20
- expect(result).to be_true
20
+ expect(result).to be true
21
21
  expect(worker).to be_stomp
22
22
  expect(worker).not_to be_jms
23
23
  end
@@ -32,7 +32,7 @@ describe Stapfen::Worker do
32
32
  end
33
33
 
34
34
  it 'should update the instance variable' do
35
- expect(result).to be_true
35
+ expect(result).to be true
36
36
  expect(worker).to be_jms
37
37
  expect(worker).not_to be_stomp
38
38
  end
@@ -55,6 +55,7 @@ describe Stapfen::Worker do
55
55
  end
56
56
 
57
57
  describe '#configure' do
58
+ let(:config) { {:valid => true} }
58
59
  it 'should error when not passed a block' do
59
60
  expect {
60
61
  worker.configure
@@ -62,21 +63,26 @@ describe Stapfen::Worker do
62
63
  end
63
64
 
64
65
  it 'should save the return value from the block' do
65
- config = {:valid => true}
66
-
67
66
  worker.configure do
68
67
  config
69
68
  end
70
-
71
69
  expect(worker.configuration.call).to eql(config)
72
70
  end
73
71
  end
74
72
 
75
- describe '#exit_cleanly' do
73
+ describe '#exit_cleanly', :java => true do
76
74
  subject(:result) { worker.exit_cleanly }
77
75
 
76
+ before do
77
+ allow(Java::JavaLang::System).to receive(:exit).with(0)
78
+ end
79
+
80
+ after do
81
+ worker.class_variable_set(:@@workers, [])
82
+ end
83
+
78
84
  context 'with no worker classes' do
79
- it { should be_false }
85
+ it { should be false }
80
86
  end
81
87
 
82
88
  context 'with a single worker class' do
@@ -88,12 +94,12 @@ describe Stapfen::Worker do
88
94
 
89
95
  it "should execute the worker's #exit_cleanly method" do
90
96
  w.should_receive(:exit_cleanly)
91
- expect(result).to be_true
97
+ expect(result).to be true
92
98
  end
93
99
 
94
100
  it "should return false if the worker's #exit_cleanly method" do
95
101
  w.should_receive(:exit_cleanly).and_raise(StandardError)
96
- expect(result).to be_false
102
+ expect(result).to be false
97
103
  end
98
104
  end
99
105
 
@@ -101,14 +107,14 @@ describe Stapfen::Worker do
101
107
  let(:w1) { double('Fake Worker 1') }
102
108
  let(:w2) { double('Fake Worker 2') }
103
109
 
104
- before :each do
110
+ before do
105
111
  worker.class_variable_set(:@@workers, [w1, w2])
106
112
  end
107
113
 
108
114
  it 'should invoke both #exit_cleanly methods' do
109
- w1.should_receive(:exit_cleanly)
110
- w2.should_receive(:exit_cleanly)
111
- expect(result).to be_true
115
+ expect(w1).to receive(:exit_cleanly)
116
+ expect(w2).to receive(:exit_cleanly)
117
+ expect(worker.exit_cleanly).to be true
112
118
  end
113
119
  end
114
120
  end
@@ -125,6 +131,10 @@ describe Stapfen::Worker do
125
131
  context 'with just a queue name' do
126
132
  let(:name) { 'jms.queue.lol' }
127
133
 
134
+ before do
135
+ worker.instance_variable_set(:@consumers, [])
136
+ end
137
+
128
138
  it 'should add an entry for the queue name' do
129
139
  worker.consume(name) do |msg|
130
140
  nil
@@ -163,6 +173,16 @@ describe Stapfen::Worker do
163
173
  client.stub(:subscribe) do |name, headers, &block|
164
174
  block.call(message)
165
175
  end
176
+
177
+ config = {:valid => true}
178
+
179
+ worker.configure do
180
+ config
181
+ end
182
+ end
183
+
184
+ after do
185
+ worker.class_variable_set(:@@workers, [])
166
186
  end
167
187
 
168
188
  context 'with just a queue name' do
@@ -189,6 +209,7 @@ describe Stapfen::Worker do
189
209
  { :dead_letter_queue => '/queue/foo',
190
210
  :max_redeliveries => 3 }
191
211
  end
212
+
192
213
  let(:raw_headers) { unrec_headers.merge(:other_header => 'foo!') }
193
214
  context 'on a failed message' do
194
215
  it 'should unreceive' do
data/stapfen.gemspec CHANGED
@@ -3,17 +3,22 @@ lib = File.expand_path('../lib', __FILE__)
3
3
  $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
4
  require 'stapfen/version'
5
5
 
6
- Gem::Specification.new do |gem|
7
- gem.name = "stapfen"
8
- gem.version = Stapfen::VERSION
9
- gem.authors = ["R. Tyler Croy"]
10
- gem.email = ["rtyler.croy@lookout.com"]
11
- gem.description = "A simple gem for writing good basic STOMP workers"
12
- gem.summary = "A simple gem for writing good basic STOMP workers"
13
- gem.homepage = ""
6
+ Gem::Specification.new do |s|
7
+ s.name = "stapfen"
8
+ s.version = Stapfen::VERSION
9
+ s.authors = ["R. Tyler Croy"]
10
+ s.email = ["rtyler.croy@lookout.com"]
11
+ s.description = "A simple gem for writing good basic STOMP workers"
12
+ s.summary = "A simple gem for writing good basic STOMP workers"
13
+ s.homepage = ""
14
14
 
15
- gem.files = `git ls-files`.split($/)
16
- gem.executables = gem.files.grep(%r{^bin/}).map{ |f| File.basename(f) }
17
- gem.test_files = gem.files.grep(%r{^(test|spec|features)/})
18
- gem.require_paths = ["lib"]
15
+ s.files = `git ls-files`.split($/)
16
+ s.executables = s.files.grep(%r{^bin/}).map{ |f| File.basename(f) }
17
+ s.test_files = s.files.grep(%r{^(test|spec|features)/})
18
+ s.require_paths = ["lib"]
19
+
20
+ if RUBY_PLATFORM == "java"
21
+ s.add_dependency 'hermann', "~> 0.20.0"
22
+ s.platform = 'java'
23
+ end
19
24
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: stapfen
3
3
  version: !ruby/object:Gem::Version
4
- version: 2.1.1
4
+ version: 2.2.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - R. Tyler Croy
@@ -9,7 +9,7 @@ autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
11
 
12
- date: 2014-01-28 00:00:00 Z
12
+ date: 2014-11-03 00:00:00 Z
13
13
  dependencies: []
14
14
 
15
15
  description: A simple gem for writing good basic STOMP workers
@@ -32,6 +32,7 @@ files:
32
32
  - lib/stapfen.rb
33
33
  - lib/stapfen/client.rb
34
34
  - lib/stapfen/client/jms.rb
35
+ - lib/stapfen/client/kafka.rb
35
36
  - lib/stapfen/client/stomp.rb
36
37
  - lib/stapfen/destination.rb
37
38
  - lib/stapfen/logger.rb
@@ -39,6 +40,7 @@ files:
39
40
  - lib/stapfen/version.rb
40
41
  - lib/stapfen/worker.rb
41
42
  - spec/client/jms_spec.rb
43
+ - spec/client/kafka_spec.rb
42
44
  - spec/client/stomp_spec.rb
43
45
  - spec/client_spec.rb
44
46
  - spec/destination_spec.rb
@@ -69,12 +71,13 @@ required_rubygems_version: !ruby/object:Gem::Requirement
69
71
  requirements: []
70
72
 
71
73
  rubyforge_project:
72
- rubygems_version: 2.2.1
74
+ rubygems_version: 2.4.1
73
75
  signing_key:
74
76
  specification_version: 4
75
77
  summary: A simple gem for writing good basic STOMP workers
76
78
  test_files:
77
79
  - spec/client/jms_spec.rb
80
+ - spec/client/kafka_spec.rb
78
81
  - spec/client/stomp_spec.rb
79
82
  - spec/client_spec.rb
80
83
  - spec/destination_spec.rb