klomp 1.0.4 → 1.0.5
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/.simplecov +1 -1
- data/ChangeLog.md +10 -0
- data/Gemfile +2 -0
- data/Gemfile.lock +8 -0
- data/Manifest.txt +2 -0
- data/Rakefile +6 -0
- data/klomp.gemspec +8 -2
- data/lib/klomp.rb +1 -1
- data/lib/klomp/connection.rb +5 -3
- data/lib/klomp/frames.rb +6 -2
- data/spec/acceptance/acceptance_spec.rb +1 -8
- data/spec/acceptance/reconnect_spec.rb +66 -0
- data/spec/klomp/connection_spec.rb +22 -2
- data/spec/support/shared_contexts.rb +9 -0
- metadata +37 -3
data/.simplecov
CHANGED
data/ChangeLog.md
CHANGED
@@ -1,6 +1,16 @@
|
|
1
1
|
Klomp Changes
|
2
2
|
--------------------------------------------------------------------------------
|
3
3
|
|
4
|
+
1.0.5 (2012/10/17)
|
5
|
+
================================================================================
|
6
|
+
|
7
|
+
- Ensure subscriptions don't get lost if re-subscribe calls fail
|
8
|
+
- Add a test of the reconnect logic using em-proxy
|
9
|
+
- Rescue all errors while parsing server frames and treat them like foreign
|
10
|
+
(server/IO/socket) errors
|
11
|
+
- Bump up default select timeout to avoid niggling read errors on connect
|
12
|
+
- Don't log exceptions if we're already offline or closing
|
13
|
+
|
4
14
|
1.0.4 (2012/10/10)
|
5
15
|
================================================================================
|
6
16
|
|
data/Gemfile
CHANGED
@@ -13,6 +13,8 @@ gem "rspec", "~>2.11.0", :group => [:development, :test]
|
|
13
13
|
gem "ZenTest", "~>4.8.0", :group => [:development, :test]
|
14
14
|
gem "rspec-given", "~>1.0", :group => [:development, :test]
|
15
15
|
gem "simplecov", "~>0.6.0", :group => [:development, :test]
|
16
|
+
gem "em-proxy", "~>0.1.0", :group => [:development, :test]
|
17
|
+
gem "ci_reporter", "~>1.7.0", :group => [:development, :test]
|
16
18
|
gem "hoe", "~>3.0", :group => [:development, :test]
|
17
19
|
|
18
20
|
# vim: syntax=ruby
|
data/Gemfile.lock
CHANGED
@@ -2,7 +2,13 @@ GEM
|
|
2
2
|
remote: http://rubygems.org/
|
3
3
|
specs:
|
4
4
|
ZenTest (4.8.0)
|
5
|
+
builder (3.1.4)
|
6
|
+
ci_reporter (1.7.3)
|
7
|
+
builder (>= 2.1.2)
|
5
8
|
diff-lcs (1.1.3)
|
9
|
+
em-proxy (0.1.7)
|
10
|
+
eventmachine
|
11
|
+
eventmachine (1.0.0)
|
6
12
|
hoe (3.0.3)
|
7
13
|
rake (~> 0.8)
|
8
14
|
hoe-bundler (1.1.0)
|
@@ -36,6 +42,8 @@ PLATFORMS
|
|
36
42
|
|
37
43
|
DEPENDENCIES
|
38
44
|
ZenTest (~> 4.8.0)
|
45
|
+
ci_reporter (~> 1.7.0)
|
46
|
+
em-proxy (~> 0.1.0)
|
39
47
|
hoe (~> 3.0)
|
40
48
|
hoe-bundler (~> 1.1.0)
|
41
49
|
hoe-gemspec (~> 1.0.0)
|
data/Manifest.txt
CHANGED
@@ -12,6 +12,7 @@ lib/klomp/connection.rb
|
|
12
12
|
lib/klomp/frames.rb
|
13
13
|
lib/klomp/sentinel.rb
|
14
14
|
spec/acceptance/acceptance_spec.rb
|
15
|
+
spec/acceptance/reconnect_spec.rb
|
15
16
|
spec/frames/auth_error.txt
|
16
17
|
spec/frames/connect.txt
|
17
18
|
spec/frames/connect_vhost.txt
|
@@ -29,3 +30,4 @@ spec/klomp/sentinel_spec.rb
|
|
29
30
|
spec/klomp_spec.rb
|
30
31
|
spec/spec_helper.rb
|
31
32
|
spec/support/have_received.rb
|
33
|
+
spec/support/shared_contexts.rb
|
data/Rakefile
CHANGED
@@ -10,6 +10,8 @@ Hoe.spec 'klomp' do
|
|
10
10
|
self.history_file = 'CHANGELOG.md'
|
11
11
|
self.readme_file = 'README.md'
|
12
12
|
|
13
|
+
self.clean_globs << 'spec/reports'
|
14
|
+
|
13
15
|
### dependencies!
|
14
16
|
self.extra_dev_deps << [ 'hoe-bundler', '~> 1.1.0' ]
|
15
17
|
self.extra_dev_deps << [ 'hoe-gemspec', '~> 1.0.0' ]
|
@@ -18,4 +20,8 @@ Hoe.spec 'klomp' do
|
|
18
20
|
self.extra_dev_deps << [ 'ZenTest', '~> 4.8.0' ]
|
19
21
|
self.extra_dev_deps << [ 'rspec-given', '~> 1.0' ]
|
20
22
|
self.extra_dev_deps << [ 'simplecov', '~> 0.6.0' ]
|
23
|
+
self.extra_dev_deps << [ 'em-proxy', '~> 0.1.0' ]
|
24
|
+
self.extra_dev_deps << [ 'ci_reporter', '~> 1.7.0' ]
|
21
25
|
end
|
26
|
+
|
27
|
+
require 'ci/reporter/rake/rspec'
|
data/klomp.gemspec
CHANGED
@@ -2,11 +2,11 @@
|
|
2
2
|
|
3
3
|
Gem::Specification.new do |s|
|
4
4
|
s.name = "klomp"
|
5
|
-
s.version = "1.0.
|
5
|
+
s.version = "1.0.5"
|
6
6
|
|
7
7
|
s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
|
8
8
|
s.authors = ["Nick Sieger"]
|
9
|
-
s.date = "2012-10-
|
9
|
+
s.date = "2012-10-17"
|
10
10
|
s.description = "Klomp is a simple [Stomp] messaging client that keeps your sanity intact.\n\nThe purpose of Klomp is to be the simplest possible Stomp client. No in-memory\nbuffering of outgoing messages, no fanout subscriptions in-process, no\ntransactions, no complicated messaging patterns. Code simple enough so that when\nsomething goes wrong, the problem is obvious.\n\n[Stomp]: http://stomp.github.com/"
|
11
11
|
s.email = ["nick.sieger@livingsocial.com"]
|
12
12
|
s.extra_rdoc_files = ["Manifest.txt"]
|
@@ -30,6 +30,8 @@ Gem::Specification.new do |s|
|
|
30
30
|
s.add_development_dependency(%q<ZenTest>, ["~> 4.8.0"])
|
31
31
|
s.add_development_dependency(%q<rspec-given>, ["~> 1.0"])
|
32
32
|
s.add_development_dependency(%q<simplecov>, ["~> 0.6.0"])
|
33
|
+
s.add_development_dependency(%q<em-proxy>, ["~> 0.1.0"])
|
34
|
+
s.add_development_dependency(%q<ci_reporter>, ["~> 1.7.0"])
|
33
35
|
s.add_development_dependency(%q<hoe>, ["~> 3.0"])
|
34
36
|
else
|
35
37
|
s.add_dependency(%q<rdoc>, ["~> 3.10"])
|
@@ -40,6 +42,8 @@ Gem::Specification.new do |s|
|
|
40
42
|
s.add_dependency(%q<ZenTest>, ["~> 4.8.0"])
|
41
43
|
s.add_dependency(%q<rspec-given>, ["~> 1.0"])
|
42
44
|
s.add_dependency(%q<simplecov>, ["~> 0.6.0"])
|
45
|
+
s.add_dependency(%q<em-proxy>, ["~> 0.1.0"])
|
46
|
+
s.add_dependency(%q<ci_reporter>, ["~> 1.7.0"])
|
43
47
|
s.add_dependency(%q<hoe>, ["~> 3.0"])
|
44
48
|
end
|
45
49
|
else
|
@@ -51,6 +55,8 @@ Gem::Specification.new do |s|
|
|
51
55
|
s.add_dependency(%q<ZenTest>, ["~> 4.8.0"])
|
52
56
|
s.add_dependency(%q<rspec-given>, ["~> 1.0"])
|
53
57
|
s.add_dependency(%q<simplecov>, ["~> 0.6.0"])
|
58
|
+
s.add_dependency(%q<em-proxy>, ["~> 0.1.0"])
|
59
|
+
s.add_dependency(%q<ci_reporter>, ["~> 1.7.0"])
|
54
60
|
s.add_dependency(%q<hoe>, ["~> 3.0"])
|
55
61
|
end
|
56
62
|
end
|
data/lib/klomp.rb
CHANGED
data/lib/klomp/connection.rb
CHANGED
@@ -28,7 +28,7 @@ class Klomp
|
|
28
28
|
@options['host'] ||= host
|
29
29
|
@subscriptions = {}
|
30
30
|
@logger = options['logger']
|
31
|
-
@select_timeout = options['select_timeout'] || 0.
|
31
|
+
@select_timeout = options['select_timeout'] || 0.5
|
32
32
|
connect
|
33
33
|
end
|
34
34
|
|
@@ -77,6 +77,8 @@ class Klomp
|
|
77
77
|
subscriptions.clear
|
78
78
|
subs.each {|queue, subscriber| subscribe(queue, subscriber) }
|
79
79
|
@sentinel = nil
|
80
|
+
ensure
|
81
|
+
@subscriptions = subs if subs && subs.size != @subscriptions.size
|
80
82
|
end
|
81
83
|
|
82
84
|
private
|
@@ -134,8 +136,8 @@ class Klomp
|
|
134
136
|
end
|
135
137
|
|
136
138
|
def go_offline(ex)
|
139
|
+
return if @closing || (@sentinel && @sentinel.alive?)
|
137
140
|
log_exception(ex, :warn, "offline server=#{options['server'].join(':')} ") if logger
|
138
|
-
return if @sentinel && @sentinel.alive?
|
139
141
|
@socket.close rescue nil
|
140
142
|
@socket = nil
|
141
143
|
@sentinel = Sentinel.new(self)
|
@@ -156,7 +158,7 @@ class Klomp
|
|
156
158
|
rescue INTERRUPT
|
157
159
|
break
|
158
160
|
rescue => e
|
159
|
-
log_exception(e, :warn) if logger
|
161
|
+
log_exception(e, :warn) if logger && !@closing
|
160
162
|
end
|
161
163
|
break if @closing
|
162
164
|
end
|
data/lib/klomp/frames.rb
CHANGED
@@ -1,5 +1,5 @@
|
|
1
1
|
class Klomp
|
2
|
-
class FrameError <
|
2
|
+
class FrameError < ::StandardError; end
|
3
3
|
|
4
4
|
module Frames
|
5
5
|
class Frame
|
@@ -36,6 +36,10 @@ class Klomp
|
|
36
36
|
def parse(data)
|
37
37
|
headers, body = data.split("\n\n")
|
38
38
|
[parse_headers(headers), body.chomp(FRAME_SEP)]
|
39
|
+
rescue FrameError
|
40
|
+
raise
|
41
|
+
rescue
|
42
|
+
raise FrameError, "malformed frame from server"
|
39
43
|
end
|
40
44
|
|
41
45
|
def parse_headers(data)
|
@@ -47,7 +51,7 @@ class Klomp
|
|
47
51
|
frame = line.chomp
|
48
52
|
@error = frame == "ERROR"
|
49
53
|
if !@error && frame != name
|
50
|
-
raise
|
54
|
+
raise FrameError,
|
51
55
|
"unexpected frame #{frame} (expected #{name}):\n#{data}"
|
52
56
|
end
|
53
57
|
next
|
@@ -4,11 +4,7 @@ require 'open-uri'
|
|
4
4
|
|
5
5
|
describe "Klomp acceptance", :acceptance => true do
|
6
6
|
|
7
|
-
|
8
|
-
Given(:credentials) { %w(admin password) }
|
9
|
-
Given(:options) { Hash[*%w(login passcode).zip(credentials).flatten] }
|
10
|
-
Given(:clients) { [] }
|
11
|
-
Given(:klomp) { Klomp.new(server, options).tap {|l| clients << l } }
|
7
|
+
include_context :acceptance_client
|
12
8
|
|
13
9
|
context "connect" do
|
14
10
|
|
@@ -51,7 +47,6 @@ describe "Klomp acceptance", :acceptance => true do
|
|
51
47
|
subscriber.message.body.should == "hello subscriber!"
|
52
48
|
end
|
53
49
|
|
54
|
-
|
55
50
|
context "and unsubscribe" do
|
56
51
|
|
57
52
|
When do
|
@@ -135,8 +130,6 @@ describe "Klomp acceptance", :acceptance => true do
|
|
135
130
|
end
|
136
131
|
end
|
137
132
|
|
138
|
-
after { clients.each(&:disconnect) }
|
139
|
-
|
140
133
|
def apollo_mgmt_url(path)
|
141
134
|
"http://localhost:61680#{path}"
|
142
135
|
end
|
@@ -0,0 +1,66 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
require 'em-proxy'
|
3
|
+
require 'logger'
|
4
|
+
|
5
|
+
describe "Klomp reconnect logic", :acceptance => true do
|
6
|
+
|
7
|
+
include_context :acceptance_client
|
8
|
+
Given(:origin_server) { "127.0.0.1:61613" }
|
9
|
+
Given(:server) { "127.0.0.1:62623" }
|
10
|
+
Given(:options) { Hash[*%w(login passcode).zip(credentials).flatten] }
|
11
|
+
|
12
|
+
it "reconnects after a server goes down" do
|
13
|
+
# Publish and receive a message
|
14
|
+
klomp.publish "/queue/greeting", "hello"
|
15
|
+
incoming = []
|
16
|
+
klomp.subscribe "/queue/greeting" do |msg|
|
17
|
+
incoming << msg
|
18
|
+
end
|
19
|
+
sleep 2
|
20
|
+
incoming.should_not be_empty
|
21
|
+
|
22
|
+
# Server disappears
|
23
|
+
stop_proxy
|
24
|
+
expect { klomp.publish "/queue/greeting", "hello" }.to raise_error
|
25
|
+
klomp.should_not be_connected
|
26
|
+
|
27
|
+
# Server reappears
|
28
|
+
start_proxy
|
29
|
+
klomp.should be_connected
|
30
|
+
|
31
|
+
# Subscription is re-established
|
32
|
+
incoming = []
|
33
|
+
klomp.publish "/queue/greeting", "hello"
|
34
|
+
sleep 2
|
35
|
+
incoming.should_not be_empty
|
36
|
+
|
37
|
+
klomp.unsubscribe "/queue/greeting"
|
38
|
+
end
|
39
|
+
|
40
|
+
before { start_proxy }
|
41
|
+
after { stop_proxy }
|
42
|
+
|
43
|
+
def server_to_hash(s)
|
44
|
+
Hash[*[:host, :port].zip(s.split(':')).flatten]
|
45
|
+
end
|
46
|
+
|
47
|
+
def start_proxy
|
48
|
+
listen, forward = server_to_hash(server), server_to_hash(origin_server)
|
49
|
+
@pid = fork do
|
50
|
+
[STDIN, STDOUT, STDERR].each {|s| s.reopen "/dev/null" }
|
51
|
+
Proxy.start listen do |conn|
|
52
|
+
conn.server :origin, forward.merge(:relay_client => true, :relay_server => true)
|
53
|
+
end
|
54
|
+
end
|
55
|
+
sleep 2
|
56
|
+
end
|
57
|
+
|
58
|
+
def stop_proxy
|
59
|
+
if @pid
|
60
|
+
Process.kill "TERM", @pid
|
61
|
+
Process.waitpid @pid
|
62
|
+
@pid = nil
|
63
|
+
end
|
64
|
+
end
|
65
|
+
|
66
|
+
end
|
@@ -161,8 +161,6 @@ describe Klomp::Connection do
|
|
161
161
|
|
162
162
|
Then { subscriber.should_not have_received(:call) }
|
163
163
|
|
164
|
-
Then { logger.should have_received(:warn) }
|
165
|
-
|
166
164
|
end
|
167
165
|
|
168
166
|
context "fails if neither a subscriber nor a block is given" do
|
@@ -351,6 +349,28 @@ describe Klomp::Connection do
|
|
351
349
|
|
352
350
|
end
|
353
351
|
|
352
|
+
context "ensures subscriptions don't get lost if re-subscribe calls fail" do
|
353
|
+
|
354
|
+
Given do
|
355
|
+
connection.subscribe "/queue/greeting", subscriber
|
356
|
+
connection.subscribe "/queue/hello", subscriber
|
357
|
+
thread.stub!(:raise)
|
358
|
+
connection.disconnect
|
359
|
+
socket.messages_received.clear
|
360
|
+
socket.stub!(:write).and_return do |data|
|
361
|
+
raise "some error" if data =~ /SUBSCRIBE/
|
362
|
+
end
|
363
|
+
end
|
364
|
+
|
365
|
+
When(:expect_reconnect) { expect { connection.reconnect } }
|
366
|
+
|
367
|
+
Then do
|
368
|
+
expect_reconnect.to raise_error
|
369
|
+
connection.subscriptions.size.should == 2
|
370
|
+
end
|
371
|
+
|
372
|
+
end
|
373
|
+
|
354
374
|
end
|
355
375
|
|
356
376
|
end
|
@@ -0,0 +1,9 @@
|
|
1
|
+
shared_context :acceptance_client do
|
2
|
+
Given(:server) { "127.0.0.1:61613" }
|
3
|
+
Given(:credentials) { %w(admin password) }
|
4
|
+
Given(:options) { Hash[*%w(login passcode).zip(credentials).flatten] }
|
5
|
+
Given(:clients) { [] }
|
6
|
+
Given(:klomp) { Klomp.new(server, options).tap {|l| clients << l } }
|
7
|
+
|
8
|
+
after { clients.each(&:disconnect) }
|
9
|
+
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: klomp
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.0.
|
4
|
+
version: 1.0.5
|
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: 2012-10-
|
12
|
+
date: 2012-10-17 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: rdoc
|
@@ -139,6 +139,38 @@ dependencies:
|
|
139
139
|
- - ~>
|
140
140
|
- !ruby/object:Gem::Version
|
141
141
|
version: 0.6.0
|
142
|
+
- !ruby/object:Gem::Dependency
|
143
|
+
name: em-proxy
|
144
|
+
requirement: !ruby/object:Gem::Requirement
|
145
|
+
none: false
|
146
|
+
requirements:
|
147
|
+
- - ~>
|
148
|
+
- !ruby/object:Gem::Version
|
149
|
+
version: 0.1.0
|
150
|
+
type: :development
|
151
|
+
prerelease: false
|
152
|
+
version_requirements: !ruby/object:Gem::Requirement
|
153
|
+
none: false
|
154
|
+
requirements:
|
155
|
+
- - ~>
|
156
|
+
- !ruby/object:Gem::Version
|
157
|
+
version: 0.1.0
|
158
|
+
- !ruby/object:Gem::Dependency
|
159
|
+
name: ci_reporter
|
160
|
+
requirement: !ruby/object:Gem::Requirement
|
161
|
+
none: false
|
162
|
+
requirements:
|
163
|
+
- - ~>
|
164
|
+
- !ruby/object:Gem::Version
|
165
|
+
version: 1.7.0
|
166
|
+
type: :development
|
167
|
+
prerelease: false
|
168
|
+
version_requirements: !ruby/object:Gem::Requirement
|
169
|
+
none: false
|
170
|
+
requirements:
|
171
|
+
- - ~>
|
172
|
+
- !ruby/object:Gem::Version
|
173
|
+
version: 1.7.0
|
142
174
|
- !ruby/object:Gem::Dependency
|
143
175
|
name: hoe
|
144
176
|
requirement: !ruby/object:Gem::Requirement
|
@@ -190,6 +222,7 @@ files:
|
|
190
222
|
- lib/klomp/frames.rb
|
191
223
|
- lib/klomp/sentinel.rb
|
192
224
|
- spec/acceptance/acceptance_spec.rb
|
225
|
+
- spec/acceptance/reconnect_spec.rb
|
193
226
|
- spec/frames/auth_error.txt
|
194
227
|
- spec/frames/connect.txt
|
195
228
|
- spec/frames/connect_vhost.txt
|
@@ -207,6 +240,7 @@ files:
|
|
207
240
|
- spec/klomp_spec.rb
|
208
241
|
- spec/spec_helper.rb
|
209
242
|
- spec/support/have_received.rb
|
243
|
+
- spec/support/shared_contexts.rb
|
210
244
|
- .gemtest
|
211
245
|
homepage: http://github.com/livingsocial/klomp
|
212
246
|
licenses: []
|
@@ -224,7 +258,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
224
258
|
version: '0'
|
225
259
|
segments:
|
226
260
|
- 0
|
227
|
-
hash:
|
261
|
+
hash: -3900239592679067652
|
228
262
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
229
263
|
none: false
|
230
264
|
requirements:
|