stapfen 1.5.0 → 2.0.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/CHANGES.md ADDED
@@ -0,0 +1,8 @@
1
+ # Changes to Stapfen
2
+
3
+
4
+ ## 2.0.0
5
+
6
+ * Add support for JMS-backed `Stapfen::Worker` classes
7
+ * Deep copy the configuration passed into `Stomp::Client` to work-around [stomp #80](https://github.com/stompgem/stomp/issues/80)
8
+ * Support per-instance log configuration [#3](https://github.com/lookout/stapfen/issues/3)
data/README.md CHANGED
@@ -1,6 +1,12 @@
1
1
  # Stapfen
2
2
 
3
- Stapfen is a simple gem to make writing stand-alone STOMP workers easier.
3
+
4
+ Stapfen is a simple gem to make writing workers that consume messages via
5
+ [STOMP](http://stomp.github.io/) or
6
+ [JMS](https://en.wikipedia.org/wiki/Java_Message_Service) easier.
7
+
8
+ Stapfen allows you to write one worker class, and use either protocol
9
+ depending on the environment and needs.
4
10
 
5
11
 
6
12
  ## Usage
@@ -10,37 +16,63 @@ Stapfen is a simple gem to make writing stand-alone STOMP workers easier.
10
16
 
11
17
  Consider the following `myworker.rb` file:
12
18
 
13
- class MyWorker < Stapfen::Worker
14
- configure do
15
- {:hosts => [
16
- {
17
- :host => 'localhost',
18
- :port => 61613,
19
- :login => 'guest',
20
- :passcode => 'guest',
21
- :ssl => false
22
- }
23
- ]}
24
- end
25
-
26
- consume 'thequeue', :dead_letter_queue => '/queue/dlq',
27
- :max_redeliveries => 0 do |message|
28
- data = expensive_computation(message.body)
29
- persist(data)
30
- end
31
- end
32
-
33
- MyWorker.run!
34
-
35
-
36
- The value returned from the `configure` block is expected to be a valid
19
+ ```ruby
20
+ class MyWorker < Stapfen::Worker
21
+ use_stomp!
22
+
23
+ configure do
24
+ {
25
+ :hosts => [
26
+ {
27
+ :host => 'localhost',
28
+ :port => 61613,
29
+ :login => 'guest',
30
+ :passcode => 'guest',
31
+ :ssl => false
32
+ }
33
+ ]
34
+ }
35
+ end
36
+
37
+ # [Optional] Set up a logger for each worker instance
38
+ log do
39
+ Logger.new(STDOUT)
40
+ end
41
+
42
+ consume 'thequeue', :dead_letter_queue => '/queue/dlq',
43
+ :max_redeliveries => 0 do |message|
44
+
45
+ data = expensive_computation(message.body)
46
+ # Save my data, or do something worker-specific with it
47
+ persist(data)
48
+
49
+ # Send another message
50
+ client.publish('/topic/computation-acks', "finished with #{message.message_id}")
51
+ end
52
+
53
+ end
54
+
55
+ MyWorker.run!
56
+ ```
57
+
58
+
59
+ When using the STOMP protocol, the value returned from the `configure` block is expected to be a valid
37
60
  `Stomp::Client` [connection
38
61
  hash](https://github.com/stompgem/stomp#hash-login-example-usage-this-is-the-recommended-login-technique).
39
62
 
63
+ In the case of the JMS protocol, the value returned from the `configure` block
64
+ is expected to be a valid [configuration
65
+ hash](https://github.com/reidmorrison/jruby-jms#consumer) for the
66
+ [jruby-jms](https://github.com/reidmorrison/jruby-jms) gem.
67
+
68
+ ---
69
+
40
70
  It is also important to note that the `consume` block will be invoked inside an
41
71
  **instance** of `MyWorker` and will execute inside its own `Thread`, so take
42
72
  care when accessing other shared resources.
43
73
 
74
+ ### STOMP-specific support
75
+
44
76
  The consume block accepts the usual
45
77
  [Stomp::Client](https://github.com/stompgem/stomp) subscription headers, as well
46
78
  as :dead_letter_queue and :max\_redeliveries. If either of the latter two is
@@ -48,6 +80,7 @@ present, the consumer will unreceive any messages for which the block returns
48
80
  false; after :max\_redeliveries, it will send the message to :dead_letter_queue.
49
81
  `consume` blocks without these headers will fail silently rather than unreceive.
50
82
 
83
+
51
84
  ## Installation
52
85
 
53
86
  Add this line to your application's Gemfile:
@@ -0,0 +1,91 @@
1
+ require 'jms'
2
+ require 'stapfen/destination'
3
+
4
+ module Stapfen
5
+ module Client
6
+ class JMS
7
+ attr_reader :connection
8
+
9
+ def initialize(configuration)
10
+ super()
11
+ @config = configuration
12
+ @connection = nil
13
+ end
14
+
15
+ # Connect to the broker via JMS and start the JMS session
16
+ #
17
+ # @return [JMS::Connection]
18
+ def connect(*args)
19
+ @connection = ::JMS::Connection.new(@config)
20
+ @connection.start
21
+ return @connection
22
+ end
23
+
24
+ # Accessor method which will cache the session if we've already created
25
+ # it once
26
+ #
27
+ # @return [JMS::Session] Instantiated +JMS::Session+ for our
28
+ # +connection+
29
+ def session
30
+ @session ||= connection.create_session
31
+ end
32
+
33
+ def publish(destination, body, headers={})
34
+ destination = Stapfen::Destination.from_string(destination)
35
+
36
+ session.producer(destination.jms_opts) do |p|
37
+ # Create the JMS typed Message
38
+ message = session.message(body)
39
+
40
+ message.delivery_mode = ::JMS::DeliveryMode::PERSISTENT if headers.delete(:persistent)
41
+
42
+ # Take the remainder of the headers and push them into the message
43
+ # properties.
44
+ headers.each_pair do |key, value|
45
+ message.setStringProperty(key.to_s, value.to_s)
46
+ end
47
+
48
+ p.send(message)
49
+ end
50
+ end
51
+
52
+ def subscribe(destination, headers={}, &block)
53
+ destination = Stapfen::Destination.from_string(destination)
54
+ connection.on_message(destination.jms_opts) do |m|
55
+ block.call(m)
56
+ end
57
+ end
58
+
59
+ # Close the JMS::Connection and the JMS::Session if it's been created
60
+ # for this client
61
+ #
62
+ # @return [Boolean] True/false depending on whether we actually closed
63
+ # the connection
64
+ def close
65
+ return false unless @connection
66
+ @session.close if @session
67
+ @connection.close
68
+ @connection = nil
69
+ return true
70
+ end
71
+
72
+ # API compatibilty method, doesn't actually indicate that the connection
73
+ # is closed. Will only return true if no connection currently exists
74
+ #
75
+ # @return [Boolean]
76
+ def closed?
77
+ return connection.nil?
78
+ end
79
+
80
+ def runloop
81
+ loop do
82
+ sleep 1
83
+ end
84
+ end
85
+
86
+ def can_unreceive?
87
+ false
88
+ end
89
+ end
90
+ end
91
+ end
@@ -0,0 +1,35 @@
1
+ require 'stomp'
2
+
3
+ module Stapfen
4
+ module Client
5
+ class Stomp < ::Stomp::Client
6
+
7
+ def initialize(config)
8
+ # Perform a deep-copy of the configuration since +Stomp::Client+ will
9
+ # mutate/mess up the configuration +Hash+ passed in here, see:
10
+ # <https://github.com/stompgem/stomp/issues/80>
11
+ super(Marshal.load(Marshal.dump(config)))
12
+ end
13
+
14
+ def connect(*args)
15
+ # No-op, since Stomp::Client will connect on instantiation
16
+ end
17
+
18
+ def can_unreceive?
19
+ true
20
+ end
21
+
22
+ def runloop
23
+ # Performing this join/runningloop to make sure that we don't
24
+ # experience potential deadlocks between signal handlers who might
25
+ # close the connection, and an infinite Client#join call
26
+ #
27
+ # Instead of using client#open? we use #running which will still be
28
+ # true even if the client is currently in an exponential reconnect loop
29
+ while self.running do
30
+ self.join(1)
31
+ end
32
+ end
33
+ end
34
+ end
35
+ end
@@ -0,0 +1,8 @@
1
+
2
+ module Stapfen
3
+ module Client
4
+ #def publish(destination, body)
5
+ # destination = Stapfen::Destination.from_string(destination)
6
+ #end
7
+ end
8
+ end
@@ -20,6 +20,26 @@ module Stapfen
20
20
  end
21
21
  end
22
22
 
23
+ def as_jms
24
+ if queue?
25
+ return "queue://#{@name}"
26
+ end
27
+
28
+ if topic?
29
+ return "topic://#{@name}"
30
+ end
31
+ end
32
+
33
+ def jms_opts
34
+ if queue?
35
+ return {:queue_name => name}
36
+ end
37
+
38
+ if topic?
39
+ return {:topic_name => name}
40
+ end
41
+ end
42
+
23
43
  # Create a {Stapfen::Destination} from the given string
24
44
  #
25
45
  # @param [String] name
@@ -18,7 +18,7 @@ module Stapfen
18
18
 
19
19
  def proxy_log_method(method, arguments)
20
20
  if self.logger
21
- self.logger.send(method, *arguments)
21
+ self.logger.call.send(method, *arguments)
22
22
  return true
23
23
  end
24
24
  return false
@@ -39,7 +39,7 @@ module Stapfen
39
39
 
40
40
  def proxy_log_method(method, arguments)
41
41
  if self.class.logger
42
- self.class.logger.send(method, *arguments)
42
+ self.class.logger.call.send(method, *arguments)
43
43
  return true
44
44
  end
45
45
  return false
@@ -1,15 +1,3 @@
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
1
 
14
2
  module Stapfen
15
3
  class Message
@@ -1,3 +1,3 @@
1
1
  module Stapfen
2
- VERSION = '1.5.0'
2
+ VERSION = '2.0.0'
3
3
  end
@@ -11,12 +11,8 @@ module Stapfen
11
11
  @@signals_handled = false
12
12
  @@workers = []
13
13
 
14
- # Class instance variables!
15
- @use_stomp = true
16
-
17
14
  class << self
18
15
  attr_accessor :configuration, :consumers, :logger, :destructor
19
-
20
16
  end
21
17
 
22
18
  # Instantiate a new +Worker+ instance and run it
@@ -56,7 +52,7 @@ module Stapfen
56
52
  end
57
53
 
58
54
  def self.stomp?
59
- @use_stomp
55
+ @use_stomp.nil? || @use_stomp
60
56
  end
61
57
 
62
58
  # Force the worker to use JMS as the messaging protocol.
@@ -82,13 +78,13 @@ module Stapfen
82
78
  end
83
79
 
84
80
  def self.jms?
85
- !(@use_stomp)
81
+ !(stomp?)
86
82
  end
87
83
 
88
84
  # Optional method, should be passed a block which will yield a {{Logger}}
89
85
  # instance for the Stapfen worker to use
90
- def self.log
91
- @logger = yield
86
+ def self.log(&block)
87
+ @logger = block
92
88
  end
93
89
 
94
90
  # Main message consumption block
@@ -158,55 +154,17 @@ module Stapfen
158
154
 
159
155
  def run
160
156
  if self.class.stomp?
161
- run_stomp
157
+ require 'stapfen/client/stomp'
158
+ @client = Stapfen::Client::Stomp.new(self.class.configuration.call)
162
159
  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
160
+ require 'stapfen/client/jms'
161
+ @client = Stapfen::Client::JMS.new(self.class.configuration.call)
203
162
  end
204
- end
205
163
 
206
- def run_stomp
207
- @client = Stomp::Client.new(self.class.configuration.call)
208
164
  debug("Running with #{@client} inside of Thread:#{Thread.current.inspect}")
209
165
 
166
+ @client.connect
167
+
210
168
  self.class.consumers.each do |name, headers, block|
211
169
  unreceive_headers = {}
212
170
  [:max_redeliveries, :dead_letter_queue].each do |sym|
@@ -219,25 +177,28 @@ module Stapfen
219
177
  method_name = name.gsub(/[.|\-]/, '_').to_sym
220
178
  self.class.send(:define_method, method_name, &block)
221
179
 
222
- client.subscribe(name, headers) do |message|
180
+ client.subscribe(name, headers) do |m|
181
+ message = nil
182
+ if self.class.stomp?
183
+ message = Stapfen::Message.from_stomp(m)
184
+ end
185
+
186
+ if self.class.jms?
187
+ message = Stapfen::Message.from_jms(m)
188
+ end
189
+
223
190
  success = self.send(method_name, message)
224
191
 
225
- if !success && !unreceive_headers.empty?
226
- client.unreceive(message, unreceive_headers)
192
+ unless success
193
+ if client.can_unreceive? && !unreceive_headers.empty?
194
+ client.unreceive(m, unreceive_headers)
195
+ end
227
196
  end
228
197
  end
229
198
  end
230
199
 
231
200
  begin
232
- # Performing this join/runningloop to make sure that we don't
233
- # experience potential deadlocks between signal handlers who might
234
- # close the connection, and an infinite Client#join call
235
- #
236
- # Instead of using client#open? we use #running which will still be
237
- # true even if the client is currently in an exponential reconnect loop
238
- while client.running do
239
- client.join(1)
240
- end
201
+ client.runloop
241
202
  warn("Exiting the runloop for #{self}")
242
203
  rescue Interrupt
243
204
  exit_cleanly
@@ -251,8 +212,10 @@ module Stapfen
251
212
  self.class.destructor.call if self.class.destructor
252
213
 
253
214
  # Only close the client if we have one sitting around
254
- if client && !client.closed?
255
- client.close
215
+ if client
216
+ unless client.closed?
217
+ client.close
218
+ end
256
219
  end
257
220
  end
258
221
  end
data/lib/stapfen.rb CHANGED
@@ -1,4 +1,19 @@
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
+
1
15
  require 'stapfen/version'
16
+ require 'stapfen/client'
2
17
  require 'stapfen/worker'
3
18
 
4
19
  module Stapfen
@@ -0,0 +1,106 @@
1
+ require 'spec_helper'
2
+
3
+ if RUBY_PLATFORM == 'java'
4
+ require 'stapfen/client/jms'
5
+
6
+ describe Stapfen::Client::JMS, :java => true do
7
+ let(:config) { {} }
8
+ subject(:client) { described_class.new(config) }
9
+
10
+ it { should respond_to :connect }
11
+
12
+ describe '#can_unreceive?' do
13
+ subject { client.can_unreceive? }
14
+
15
+ it { should_not be_true }
16
+ end
17
+
18
+ describe '#connect' do
19
+ subject(:connection) { client.connect }
20
+ let(:jms_conn) { double('JMS::Connection') }
21
+
22
+ before :each do
23
+ ::JMS::Connection.should_receive(:new).and_return(jms_conn)
24
+ end
25
+
26
+ it 'should start the connection' do
27
+ jms_conn.should_receive(:start)
28
+ expect(connection).to eql(jms_conn)
29
+ end
30
+ end
31
+
32
+ describe '#session' do
33
+ let(:session) { double('JMS::Session') }
34
+ let(:connection) { double('JMS::Connection') }
35
+
36
+ before :each do
37
+ client.stub(:connection => connection)
38
+ end
39
+
40
+ context 'without a session already' do
41
+ it 'should create a new session' do
42
+ connection.should_receive(:create_session).and_return(session)
43
+ expect(client.session).to eql(session)
44
+ end
45
+ end
46
+
47
+ context 'with an existing session' do
48
+ it 'should return that existing session' do
49
+ connection.should_receive(:create_session).once.and_return(session)
50
+ 3.times do
51
+ expect(client.session).to eql(session)
52
+ end
53
+ end
54
+ end
55
+ end
56
+
57
+ describe '#publish' do
58
+ end
59
+
60
+ describe '#closed?' do
61
+ subject(:result) { client.closed? }
62
+
63
+ context 'if a connection exists' do
64
+ before :each do
65
+ client.stub(:connection).and_return(double('JMS::Connection'))
66
+ end
67
+
68
+ it { should be_false }
69
+ end
70
+
71
+ context 'without a connection' do
72
+ it { should be_true }
73
+ end
74
+ end
75
+
76
+ describe '#close' do
77
+ subject(:result) { client.close }
78
+ let(:connection) { double('JMS::Connection') }
79
+
80
+ before :each do
81
+ client.instance_variable_set(:@connection, connection)
82
+ end
83
+
84
+ context 'without an existing session' do
85
+ it 'should close the client' do
86
+ connection.should_receive(:close)
87
+ expect(result).to be_true
88
+ end
89
+ end
90
+
91
+ context 'with an existing session' do
92
+ let(:session) { double('JMS::Session') }
93
+
94
+ before :each do
95
+ client.instance_variable_set(:@session, session)
96
+ end
97
+
98
+ it 'should close the client and session' do
99
+ session.should_receive(:close)
100
+ connection.should_receive(:close)
101
+ expect(result).to be_true
102
+ end
103
+ end
104
+ end
105
+ end
106
+ end
@@ -0,0 +1,5 @@
1
+ require 'spec_helper'
2
+ require 'stapfen/client/stomp'
3
+
4
+ describe Stapfen::Client::Stomp do
5
+ end
@@ -0,0 +1,5 @@
1
+ require 'spec_helper'
2
+ require 'stapfen/client'
3
+
4
+ describe Stapfen::Client do
5
+ 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_jms' do
9
+ let(:name) { 'rspec/dlq' }
10
+ subject(:destination) do
11
+ d = described_class.new
12
+ d.type = :queue
13
+ d.name = name
14
+ d.as_jms
15
+ end
16
+
17
+ it { should be_instance_of String }
18
+ it { should eql "queue://#{name}" }
19
+ end
20
+
8
21
  describe '#as_stomp' do
9
22
  let(:name) { 'rspec/dlq' }
10
23
 
data/spec/logger_spec.rb CHANGED
@@ -29,7 +29,7 @@ describe Stapfen::Logger do
29
29
  let(:plogger) { double('RSpec Logger') }
30
30
 
31
31
  before :each do
32
- logger.class.stub(:logger).and_return(plogger)
32
+ logger.class.stub(:logger).and_return(lambda { plogger })
33
33
  end
34
34
 
35
35
  it 'should pass info messages along' do
data/spec/worker_spec.rb CHANGED
@@ -38,6 +38,22 @@ describe Stapfen::Worker do
38
38
  end
39
39
  end
40
40
 
41
+ describe '#log' do
42
+ it "should store the block it's passed" do
43
+ logger = double('Mock Logger')
44
+
45
+ worker.log do
46
+ logger
47
+ end
48
+
49
+ expect(worker.logger).to be_instance_of Proc
50
+ end
51
+
52
+ after :each do
53
+ worker.logger = nil
54
+ end
55
+ end
56
+
41
57
  describe '#configure' do
42
58
  it 'should error when not passed a block' do
43
59
  expect {
@@ -52,11 +68,10 @@ describe Stapfen::Worker do
52
68
  config
53
69
  end
54
70
 
55
- worker.configuration.call.should == config
71
+ expect(worker.configuration.call).to eql(config)
56
72
  end
57
73
  end
58
74
 
59
-
60
75
  describe '#exit_cleanly' do
61
76
  subject(:result) { worker.exit_cleanly }
62
77
 
@@ -120,14 +135,28 @@ describe Stapfen::Worker do
120
135
  end
121
136
 
122
137
  context 'unreceive behavior' do
123
- let(:client) { double('Stomp::Client', :running => false) }
138
+ let(:client) do
139
+ c = double('Mock Stapfen::Client')
140
+ c.stub(:connect)
141
+ c.stub(:can_unreceive? => true)
142
+ c.stub(:runloop)
143
+ c
144
+ end
145
+
124
146
  let(:name) { '/queue/some_queue' }
147
+ let(:message) do
148
+ m = Stomp::Message.new(nil)
149
+ m.stub(:body => 'rspec msg')
150
+ m
151
+ end
152
+
153
+
125
154
  before :each do
126
- Stomp::Client.stub(:new).and_return(client)
155
+ Stapfen::Client::Stomp.stub(:new).and_return(client)
127
156
 
128
157
  # Get a subscription? Call the message handler block.
129
158
  client.stub(:subscribe) do |name, headers, &block|
130
- block.call('msg')
159
+ block.call(message)
131
160
  end
132
161
  end
133
162
 
@@ -164,7 +193,7 @@ describe Stapfen::Worker do
164
193
  worker.new.run
165
194
  end
166
195
  it 'should pass :unreceive_headers through to the unreceive call' do
167
- client.should_receive(:unreceive).with('msg', unrec_headers).once
196
+ client.should_receive(:unreceive).with(message, unrec_headers).once
168
197
 
169
198
  worker.consume(name, raw_headers) {|msg| false }
170
199
  worker.new.run
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.5.0
4
+ version: 2.0.0
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -9,7 +9,7 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2013-09-27 00:00:00.000000000 Z
12
+ date: 2013-10-03 00:00:00.000000000 Z
13
13
  dependencies: []
14
14
  description: A simple gem for writing good basic STOMP workers
15
15
  email:
@@ -19,6 +19,7 @@ extensions: []
19
19
  extra_rdoc_files: []
20
20
  files:
21
21
  - .gitignore
22
+ - CHANGES.md
22
23
  - Gemfile
23
24
  - Guardfile
24
25
  - LICENSE.txt
@@ -26,11 +27,17 @@ files:
26
27
  - Rakefile
27
28
  - examples/simple.rb
28
29
  - lib/stapfen.rb
30
+ - lib/stapfen/client.rb
31
+ - lib/stapfen/client/jms.rb
32
+ - lib/stapfen/client/stomp.rb
29
33
  - lib/stapfen/destination.rb
30
34
  - lib/stapfen/logger.rb
31
35
  - lib/stapfen/message.rb
32
36
  - lib/stapfen/version.rb
33
37
  - lib/stapfen/worker.rb
38
+ - spec/client/jms_spec.rb
39
+ - spec/client/stomp_spec.rb
40
+ - spec/client_spec.rb
34
41
  - spec/destination_spec.rb
35
42
  - spec/logger_spec.rb
36
43
  - spec/message_spec.rb
@@ -51,7 +58,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
51
58
  version: '0'
52
59
  segments:
53
60
  - 0
54
- hash: -1455385429346077259
61
+ hash: 497669016429276389
55
62
  required_rubygems_version: !ruby/object:Gem::Requirement
56
63
  none: false
57
64
  requirements:
@@ -60,7 +67,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
60
67
  version: '0'
61
68
  segments:
62
69
  - 0
63
- hash: -1455385429346077259
70
+ hash: 497669016429276389
64
71
  requirements: []
65
72
  rubyforge_project:
66
73
  rubygems_version: 1.8.25
@@ -68,6 +75,9 @@ signing_key:
68
75
  specification_version: 3
69
76
  summary: A simple gem for writing good basic STOMP workers
70
77
  test_files:
78
+ - spec/client/jms_spec.rb
79
+ - spec/client/stomp_spec.rb
80
+ - spec/client_spec.rb
71
81
  - spec/destination_spec.rb
72
82
  - spec/logger_spec.rb
73
83
  - spec/message_spec.rb