stapfen 1.4.3 → 1.5.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.
data/Gemfile CHANGED
@@ -3,10 +3,14 @@ source 'https://rubygems.org'
3
3
  # Specify your gem's dependencies in stapfen.gemspec
4
4
  gemspec
5
5
 
6
+ gem 'jruby-jms', :platform => :jruby
7
+ gem 'stomp', '>= 1.2.14'
6
8
 
7
9
  group :development do
8
10
  gem 'rake'
9
11
  gem 'rspec', '~> 2.11'
10
12
  gem 'guard-rspec'
11
- gem 'debugger'
13
+ gem 'pry'
14
+ gem 'debugger', :platform => :mri
15
+ gem 'debugger-pry', :platform => :mri
12
16
  end
@@ -0,0 +1,35 @@
1
+ module Stapfen
2
+ class Destination
3
+ attr_accessor :name, :type
4
+
5
+ def queue?
6
+ @type == :queue
7
+ end
8
+
9
+ def topic?
10
+ @type == :topic
11
+ end
12
+
13
+ def as_stomp
14
+ if queue?
15
+ return "/queue/#{@name}"
16
+ end
17
+
18
+ if topic?
19
+ return "/topic/#{@name}"
20
+ end
21
+ end
22
+
23
+ # Create a {Stapfen::Destination} from the given string
24
+ #
25
+ # @param [String] name
26
+ # @return [Stapfen::Destination]
27
+ def self.from_string(name)
28
+ destination = self.new
29
+ pieces = name.split('/')
30
+ destination.type = pieces[1].to_sym
31
+ destination.name = pieces[2 .. -1].join('/')
32
+ return destination
33
+ end
34
+ end
35
+ end
@@ -0,0 +1,58 @@
1
+ begin
2
+ require 'stomp'
3
+ rescue LoadError
4
+ # Can't process Stomp
5
+ end
6
+
7
+ begin
8
+ require 'java'
9
+ require 'jms'
10
+ rescue LoadError
11
+ # Can't process JMS
12
+ end
13
+
14
+ module Stapfen
15
+ class Message
16
+ attr_reader :message_id, :body, :original, :destination
17
+
18
+ def initialize(opts={})
19
+ super()
20
+ @body = opts[:body]
21
+ @destination = opts[:destination]
22
+ @message_id = opts[:message_id]
23
+ @original = opts[:original]
24
+ end
25
+
26
+ # Create an instance of {Stapfen::Message} from the passed in
27
+ # {Stomp::Message}
28
+ #
29
+ # @param [Stomp::Message] message A message created by the Stomp gem
30
+ # @return [Stapfen::Message] A Stapfen wrapper object
31
+ def self.from_stomp(message)
32
+ unless message.kind_of? Stomp::Message
33
+ raise Stapfen::InvalidMessageError, message.inspect
34
+ end
35
+
36
+ return self.new(:body => message.body,
37
+ :destination => message.headers['destination'],
38
+ :message_id => message.headers['message-id'],
39
+ :original => message)
40
+ end
41
+
42
+ # Create an instance of {Stapfen::Message} from the passed in
43
+ # +ActiveMQBytesMessage+ which a JMS consumer should receive
44
+ #
45
+ # @param [ActiveMQBytesMessage] message
46
+ # @return [Stapfen::Message] A Stapfen wrapper object
47
+ def self.from_jms(message)
48
+ unless message.kind_of? Java::JavaxJms::Message
49
+ raise Stapfen::InvalidMessageError, message.inspect
50
+ end
51
+
52
+ return self.new(:body => message.data,
53
+ :destination => message.jms_destination.getQualifiedName,
54
+ :message_id => message.jms_message_id,
55
+ :original => message)
56
+ end
57
+ end
58
+ end
@@ -1,3 +1,3 @@
1
1
  module Stapfen
2
- VERSION = '1.4.3'
2
+ VERSION = '1.5.0'
3
3
  end
@@ -1,15 +1,22 @@
1
1
  require 'stomp'
2
2
  require 'stapfen/logger'
3
+ require 'stapfen/destination'
4
+ require 'stapfen/message'
3
5
 
4
6
  module Stapfen
5
7
  class Worker
6
8
  include Stapfen::Logger
7
9
 
10
+ # Class variables!
8
11
  @@signals_handled = false
9
12
  @@workers = []
10
13
 
14
+ # Class instance variables!
15
+ @use_stomp = true
16
+
11
17
  class << self
12
18
  attr_accessor :configuration, :consumers, :logger, :destructor
19
+
13
20
  end
14
21
 
15
22
  # Instantiate a new +Worker+ instance and run it
@@ -33,6 +40,51 @@ module Stapfen
33
40
  @configuration = block
34
41
  end
35
42
 
43
+ # Force the worker to use STOMP as the messaging protocol (default)
44
+ #
45
+ # @return [Boolean]
46
+ def self.use_stomp!
47
+ begin
48
+ require 'stomp'
49
+ rescue LoadError
50
+ puts "You need the `stomp` gem to be installed to use stomp!"
51
+ raise
52
+ end
53
+
54
+ @use_stomp = true
55
+ return true
56
+ end
57
+
58
+ def self.stomp?
59
+ @use_stomp
60
+ end
61
+
62
+ # Force the worker to use JMS as the messaging protocol.
63
+ #
64
+ # *Note:* Only works under JRuby
65
+ #
66
+ # @return [Boolean]
67
+ def self.use_jms!
68
+ unless RUBY_PLATFORM == 'java'
69
+ raise Stapfen::ConfigurationError, "You cannot use JMS unless you're running under JRuby!"
70
+ end
71
+
72
+ begin
73
+ require 'java'
74
+ require 'jms'
75
+ rescue LoadError
76
+ puts "You need the `jms` gem to be installed to use JMS!"
77
+ raise
78
+ end
79
+
80
+ @use_stomp = false
81
+ return true
82
+ end
83
+
84
+ def self.jms?
85
+ !(@use_stomp)
86
+ end
87
+
36
88
  # Optional method, should be passed a block which will yield a {{Logger}}
37
89
  # instance for the Stapfen worker to use
38
90
  def self.log
@@ -105,6 +157,53 @@ module Stapfen
105
157
  attr_accessor :client
106
158
 
107
159
  def run
160
+ if self.class.stomp?
161
+ run_stomp
162
+ elsif self.class.jms?
163
+ run_jms
164
+ end
165
+ end
166
+
167
+ def run_jms
168
+ JMS::Connection.start(self.class.configuration.call) do |connection|
169
+ @client = connection
170
+ debug("Running with #{@client} inside of Thread:#{Thread.current.inspect}")
171
+
172
+ self.class.consumers.each do |name, headers, block|
173
+ destination = Stapfen::Destination.from_string(name)
174
+ type = 'queue'
175
+ options = {}
176
+
177
+ if destination.queue?
178
+ options[:queue_name] = destination.name
179
+ end
180
+
181
+ if destination.topic?
182
+ type = 'topic'
183
+ options[:topic_name] = destination.name
184
+ end
185
+
186
+ method_name = "handle_#{type}_#{name}".to_sym
187
+ self.class.send(:define_method, method_name, &block)
188
+
189
+ connection.on_message(options) do |m|
190
+ message = Stapfen::Message.from_jms(m)
191
+ self.send(method_name, message)
192
+ end
193
+ end
194
+
195
+ begin
196
+ loop do
197
+ sleep 1
198
+ end
199
+ debug("Exiting the JMS runloop for #{self}")
200
+ rescue Interrupt
201
+ exit_cleanly
202
+ end
203
+ end
204
+ end
205
+
206
+ def run_stomp
108
207
  @client = Stomp::Client.new(self.class.configuration.call)
109
208
  debug("Running with #{@client} inside of Thread:#{Thread.current.inspect}")
110
209
 
data/lib/stapfen.rb CHANGED
@@ -6,4 +6,6 @@ module Stapfen
6
6
  end
7
7
  class ConsumeError < StandardError
8
8
  end
9
+ class InvalidMessageError < StandardError
10
+ end
9
11
  end
@@ -0,0 +1,45 @@
1
+ require 'spec_helper'
2
+ require 'stapfen/destination'
3
+
4
+ describe Stapfen::Destination do
5
+ it { should respond_to :name }
6
+ it { should respond_to :type }
7
+
8
+ describe '#as_stomp' do
9
+ let(:name) { 'rspec/dlq' }
10
+
11
+ subject(:destination) do
12
+ d = described_class.new
13
+ d.type = :queue
14
+ d.name = name
15
+ d.as_stomp
16
+ end
17
+
18
+ it { should be_instance_of String }
19
+ it { should eql "/queue/#{name}" }
20
+ end
21
+
22
+ context 'class methods' do
23
+ describe '#from_string' do
24
+ subject(:destination) { described_class.from_string(name) }
25
+
26
+ context 'a simple queue' do
27
+ let(:name) { '/queue/rspec' }
28
+ its(:name) { should eql 'rspec' }
29
+ its(:type) { should eql :queue }
30
+ end
31
+
32
+ context 'a queue with slashes' do
33
+ let(:name) { '/queue/rspec/dlq' }
34
+ its(:name) { should eql 'rspec/dlq' }
35
+ its(:type) { should eql :queue }
36
+ end
37
+
38
+ context 'a complex topic' do
39
+ let(:name) { '/topic/rspec/dlq' }
40
+ its(:name) { should eql 'rspec/dlq' }
41
+ its(:type) { should eql :topic }
42
+ end
43
+ end
44
+ end
45
+ end
@@ -0,0 +1,96 @@
1
+ require 'spec_helper'
2
+ require 'stapfen/message'
3
+
4
+ if RUBY_PLATFORM == 'java'
5
+ require 'java'
6
+ require File.expand_path('./activemq-all-5.8.0.jar')
7
+ end
8
+
9
+ describe Stapfen::Message do
10
+ context 'accessors' do
11
+ it { should respond_to :message_id }
12
+ it { should respond_to :body }
13
+ it { should respond_to :original }
14
+ it { should respond_to :destination }
15
+ end
16
+
17
+ describe '#initialize' do
18
+ it 'should accept :body' do
19
+ body = 'hello'
20
+ m = described_class.new(:body => body)
21
+ expect(m.body).to eql(body)
22
+ end
23
+ end
24
+
25
+ context 'class methods' do
26
+ let(:body) { 'hello stapfen' }
27
+ let(:destination) { '/queue/rspec' }
28
+ let(:message_id) { rand.to_s }
29
+
30
+ describe '#from_stomp' do
31
+ subject(:result) { described_class.from_stomp(message) }
32
+
33
+ context 'when passed something other than a Stomp::Message' do
34
+ let(:message) { 'hello' }
35
+
36
+ it 'should raise an error' do
37
+ expect { result }.to raise_error(Stapfen::InvalidMessageError)
38
+ end
39
+ end
40
+
41
+ context 'when passed a Stomp::Message' do
42
+ let(:message) do
43
+ m = Stomp::Message.new('') # empty frame
44
+ m.body = body
45
+ headers = {'destination' => destination,
46
+ 'message-id' => message_id}
47
+ m.headers = headers
48
+ m
49
+ end
50
+
51
+ it 'should create an instance' do
52
+ expect(result).to be_instance_of Stapfen::Message
53
+ end
54
+
55
+ its(:body) { should eql body }
56
+ its(:destination) { should eql destination }
57
+ its(:message_id) { should eql message_id }
58
+ its(:original) { should be message }
59
+ end
60
+ end
61
+
62
+ describe '#from_jms', :java => true do
63
+ subject(:result) { described_class.from_jms(message) }
64
+
65
+ context 'when passed something other than a JMS message' do
66
+ let(:message) { 'hello' }
67
+
68
+ it 'should raise an error' do
69
+ expect { result }.to raise_error(Stapfen::InvalidMessageError)
70
+ end
71
+ end
72
+
73
+ context 'when passed an ActiveMQBytesMessage' do
74
+ let(:destination) { 'queue://rspec' }
75
+
76
+ let(:message) do
77
+ m = Java::OrgApacheActivemqCommand::ActiveMQBytesMessage.new
78
+ m.stub(:jms_destination => double('ActiveMQDestination mock', :getQualifiedName => destination))
79
+ m.stub(:jms_message_id => message_id)
80
+ m.stub(:data => body)
81
+ m
82
+ end
83
+
84
+ it 'should create an instance' do
85
+ expect(result).to be_instance_of Stapfen::Message
86
+ end
87
+
88
+ its(:body) { should eql body }
89
+ its(:destination) { should eql destination }
90
+ its(:message_id) { should eql message_id }
91
+ its(:original) { should be message }
92
+
93
+ end
94
+ end
95
+ end
96
+ end
data/spec/spec_helper.rb CHANGED
@@ -1,4 +1,18 @@
1
1
  $LOAD_PATH.unshift(File.expand_path(File.dirname(__FILE__) + '../lib'))
2
2
 
3
3
  require 'stapfen'
4
- require 'debugger'
4
+
5
+
6
+ is_java = (RUBY_PLATFORM == 'java')
7
+
8
+ unless is_java
9
+ require 'debugger'
10
+ require 'debugger/pry'
11
+ end
12
+
13
+
14
+ RSpec.configure do |c|
15
+ unless is_java
16
+ c.filter_run_excluding :java => true
17
+ end
18
+ end
data/spec/worker_spec.rb CHANGED
@@ -13,6 +13,31 @@ describe Stapfen::Worker do
13
13
  it { should respond_to :log }
14
14
  it { should respond_to :shutdown }
15
15
 
16
+ describe '#use_stomp!' do
17
+ subject(:result) { worker.use_stomp! }
18
+
19
+ it 'should update the instance variable' do
20
+ expect(result).to be_true
21
+ expect(worker).to be_stomp
22
+ expect(worker).not_to be_jms
23
+ end
24
+ end
25
+
26
+ describe '#use_jms!', :java => true do
27
+ subject(:result) { worker.use_jms! }
28
+
29
+ after :each do
30
+ # Reset to the default since we've modified the class
31
+ worker.use_stomp!
32
+ end
33
+
34
+ it 'should update the instance variable' do
35
+ expect(result).to be_true
36
+ expect(worker).to be_jms
37
+ expect(worker).not_to be_stomp
38
+ end
39
+ end
40
+
16
41
  describe '#configure' do
17
42
  it 'should error when not passed a block' do
18
43
  expect {
data/stapfen.gemspec CHANGED
@@ -16,7 +16,4 @@ Gem::Specification.new do |gem|
16
16
  gem.executables = gem.files.grep(%r{^bin/}).map{ |f| File.basename(f) }
17
17
  gem.test_files = gem.files.grep(%r{^(test|spec|features)/})
18
18
  gem.require_paths = ["lib"]
19
-
20
-
21
- gem.add_dependency('stomp', '>= 1.2.14') # 1.2.14 fixes Stomp::Client#unreceive behavior
22
19
  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: 1.4.3
4
+ version: 1.5.0
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -9,24 +9,8 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2013-09-26 00:00:00.000000000 Z
13
- dependencies:
14
- - !ruby/object:Gem::Dependency
15
- name: stomp
16
- requirement: !ruby/object:Gem::Requirement
17
- none: false
18
- requirements:
19
- - - ! '>='
20
- - !ruby/object:Gem::Version
21
- version: 1.2.14
22
- type: :runtime
23
- prerelease: false
24
- version_requirements: !ruby/object:Gem::Requirement
25
- none: false
26
- requirements:
27
- - - ! '>='
28
- - !ruby/object:Gem::Version
29
- version: 1.2.14
12
+ date: 2013-09-27 00:00:00.000000000 Z
13
+ dependencies: []
30
14
  description: A simple gem for writing good basic STOMP workers
31
15
  email:
32
16
  - rtyler.croy@lookout.com
@@ -42,10 +26,14 @@ files:
42
26
  - Rakefile
43
27
  - examples/simple.rb
44
28
  - lib/stapfen.rb
29
+ - lib/stapfen/destination.rb
45
30
  - lib/stapfen/logger.rb
31
+ - lib/stapfen/message.rb
46
32
  - lib/stapfen/version.rb
47
33
  - lib/stapfen/worker.rb
34
+ - spec/destination_spec.rb
48
35
  - spec/logger_spec.rb
36
+ - spec/message_spec.rb
49
37
  - spec/spec_helper.rb
50
38
  - spec/worker_spec.rb
51
39
  - stapfen.gemspec
@@ -63,7 +51,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
63
51
  version: '0'
64
52
  segments:
65
53
  - 0
66
- hash: -1405776487740339593
54
+ hash: -1455385429346077259
67
55
  required_rubygems_version: !ruby/object:Gem::Requirement
68
56
  none: false
69
57
  requirements:
@@ -72,7 +60,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
72
60
  version: '0'
73
61
  segments:
74
62
  - 0
75
- hash: -1405776487740339593
63
+ hash: -1455385429346077259
76
64
  requirements: []
77
65
  rubyforge_project:
78
66
  rubygems_version: 1.8.25
@@ -80,6 +68,8 @@ signing_key:
80
68
  specification_version: 3
81
69
  summary: A simple gem for writing good basic STOMP workers
82
70
  test_files:
71
+ - spec/destination_spec.rb
83
72
  - spec/logger_spec.rb
73
+ - spec/message_spec.rb
84
74
  - spec/spec_helper.rb
85
75
  - spec/worker_spec.rb