onstomp 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/CHANGELOG.md +7 -0
- data/README.md +27 -1
- data/examples/basic.rb +5 -5
- data/extra_doc/API.md +14 -6
- data/lib/onstomp/client.rb +3 -0
- data/lib/onstomp/components/threaded_processor.rb +12 -7
- data/lib/onstomp/connections/base.rb +7 -0
- data/lib/onstomp/connections/heartbeating.rb +2 -2
- data/lib/onstomp/failover/client.rb +6 -5
- data/lib/onstomp/version.rb +1 -1
- data/spec/onstomp/client_spec.rb +1 -0
- data/spec/onstomp/failover/client_spec.rb +21 -0
- metadata +50 -58
- data/extra_doc/DeveloperNarrative.md +0 -123
data/CHANGELOG.md
CHANGED
@@ -1,5 +1,12 @@
|
|
1
1
|
# Changes
|
2
2
|
|
3
|
+
## 1.0.5
|
4
|
+
* fixed a race condition that would occur if a user (or the failover extension)
|
5
|
+
tried to re-connect an OnStomp::Client instance within an `on_connection_closed`
|
6
|
+
(or similar) event handler. The fix is more of a band-aid at the moment,
|
7
|
+
and a proper fix will follow. Thanks to [alcy](https://github.com/alcy) for
|
8
|
+
helping me track this down.
|
9
|
+
|
3
10
|
## 1.0.4
|
4
11
|
* fixed major oversight when using ruby 1.8.7 / jruby with an SSL connection.
|
5
12
|
it will use blocking read/write methods if nonblocking methods are unavailable
|
data/README.md
CHANGED
@@ -46,10 +46,36 @@ in the hopes of increasing performance.
|
|
46
46
|
The `stomp` gem is a good gem that works well, I just desired a different
|
47
47
|
style API for working with message brokers.
|
48
48
|
|
49
|
+
## Gotchas
|
50
|
+
|
51
|
+
Both Ruby 1.8.7 and JRuby (as of 1.6.1) do not provide non-blocking read
|
52
|
+
or write methods for OpenSSL connections. While a gem named
|
53
|
+
[openssl-nonblock](https://github.com/tarcieri/openssl-nonblock) exists for
|
54
|
+
Ruby < 1.9.2, I have not personally used it and given that it's a C extension,
|
55
|
+
it may not be compatible with JRuby's openssl gem. When an OnStomp connection
|
56
|
+
is created, the socket (SSL or TCP) is checked to see whether or not the methods
|
57
|
+
`write_nonblock` and `read_nonblock` have been defined. If not, OnStomp will
|
58
|
+
fall back on `write` for writing and `readpartial` for reading. While both of
|
59
|
+
these methods will block, the use of `IO::select` should help mitigate their
|
60
|
+
effects. I initially missed this detail, so if you're using an older version
|
61
|
+
of OnStomp (pre 1.0.4) with Ruby 1.8.7 or JRuby, you either want to upgrade
|
62
|
+
your gem or avoid `stomp+ssl://` URIs like the plague.
|
63
|
+
|
64
|
+
The final "gotcha" is more of an advanced warning. When JRuby's support
|
65
|
+
for the Ruby 1.9 API stabilizes (and `read_nonblock` and `write_nonblock` are
|
66
|
+
available for OpenSSL connections), I will be dropping support for Ruby 1.8.x
|
67
|
+
entirely. This is probably a ways off yet, but when the time comes, I'll
|
68
|
+
post obvious warnings and increment the gem's major version. OnStomp 1.x
|
69
|
+
will always be compatible with Ruby 1.8.7+, OnStomp 2.x will be Ruby 1.9.x
|
70
|
+
only.
|
71
|
+
|
49
72
|
## Further Reading
|
50
73
|
|
74
|
+
* The [OnStomp YARD Documentation](http://mdvlrb.com/onstomp/)
|
75
|
+
* The [OnStomp Github Wiki](https://github.com/meadvillerb/onstomp/wiki)
|
76
|
+
* Some [Contrived Examples](https://github.com/meadvillerb/onstomp/tree/master/examples)
|
51
77
|
* A {file:extra_doc/UserNarrative.md User's Narrative}
|
52
|
-
*
|
78
|
+
* The {file:extra_doc/API.md OnStomp API Promise} (sort of)
|
53
79
|
* A {file:extra_doc/CHANGELOG.md History of Changes}
|
54
80
|
|
55
81
|
## License
|
data/examples/basic.rb
CHANGED
@@ -6,21 +6,21 @@ puts "Starting demo"
|
|
6
6
|
puts "----------------------------"
|
7
7
|
|
8
8
|
running = true
|
9
|
-
client = OnStomp::Client.new("stomp://localhost")
|
9
|
+
client = OnStomp::Client.new("stomp://localhost:61613")
|
10
10
|
client.connect
|
11
11
|
|
12
12
|
puts "Connected to broker using protocol #{client.connection.version}"
|
13
13
|
|
14
|
-
client.subscribe("/queue/
|
14
|
+
client.subscribe("/queue/onstomp_test") do |message|
|
15
15
|
puts "Received: '#{message.body}'"
|
16
16
|
if message.body == 'finished'
|
17
17
|
running = false
|
18
18
|
end
|
19
19
|
end
|
20
20
|
|
21
|
-
client.send("/queue/
|
22
|
-
client.send("/queue/
|
23
|
-
client.send("/queue/
|
21
|
+
client.send("/queue/onstomp_test", "hello world")
|
22
|
+
client.send("/queue/onstomp_test", "this is a simple demo of onstomp")
|
23
|
+
client.send("/queue/onstomp_test", "finished")
|
24
24
|
|
25
25
|
Thread.pass while running
|
26
26
|
client.disconnect
|
data/extra_doc/API.md
CHANGED
@@ -33,18 +33,18 @@
|
|
33
33
|
<tr>
|
34
34
|
<td>{OnStomp::Interfaces::FrameMethods#ack ack}</td>
|
35
35
|
<td>
|
36
|
-
<code>ack(message_id, headers=<optional hash>)</code>
|
36
|
+
<code>ack(message_id, subscription_id, headers=<optional hash>)</code>
|
37
37
|
</td>
|
38
38
|
<td style="background-color: #bfb;">true</td>
|
39
|
-
<td style="background-color: #
|
39
|
+
<td style="background-color: #bfb;">true</td>
|
40
40
|
</tr>
|
41
41
|
<tr>
|
42
42
|
<td>{OnStomp::Interfaces::FrameMethods#ack ack}</td>
|
43
43
|
<td>
|
44
|
-
<code>ack(message_id,
|
44
|
+
<code>ack(message_id, headers=<optional hash>)</code>
|
45
45
|
</td>
|
46
46
|
<td style="background-color: #bfb;">true</td>
|
47
|
-
<td style="background-color: #
|
47
|
+
<td style="background-color: #fbb;">false</td>
|
48
48
|
</tr>
|
49
49
|
<tr>
|
50
50
|
<td>{OnStomp::Interfaces::ClientEvents#after_receiving after_receiving}</td>
|
@@ -310,6 +310,14 @@
|
|
310
310
|
<td style="background-color: #bfb;">true</td>
|
311
311
|
<td style="background-color: #bfb;">true</td>
|
312
312
|
</tr>
|
313
|
+
<tr>
|
314
|
+
<td>{OnStomp::Interfaces::ConnectionEvents#on_blocked on_blocked}</td>
|
315
|
+
<td>
|
316
|
+
<code>create_event_methods :blocked, :on</code>
|
317
|
+
</td>
|
318
|
+
<td style="background-color: #bfb;">true</td>
|
319
|
+
<td style="background-color: #bfb;">true</td>
|
320
|
+
</tr>
|
313
321
|
<tr>
|
314
322
|
<td>{OnStomp::Interfaces::ClientEvents#on_broker_beat on_broker_beat}</td>
|
315
323
|
<td>
|
@@ -473,7 +481,7 @@
|
|
473
481
|
<tr>
|
474
482
|
<td>{OnStomp::Interfaces::FrameMethods#unsubscribe unsubscribe}</td>
|
475
483
|
<td>
|
476
|
-
<code>unsubscribe(
|
484
|
+
<code>unsubscribe(subscribe_frame, headers=<optional hash>)</code>
|
477
485
|
</td>
|
478
486
|
<td style="background-color: #bfb;">true</td>
|
479
487
|
<td style="background-color: #bfb;">true</td>
|
@@ -481,7 +489,7 @@
|
|
481
489
|
<tr>
|
482
490
|
<td>{OnStomp::Interfaces::FrameMethods#unsubscribe unsubscribe}</td>
|
483
491
|
<td>
|
484
|
-
<code>unsubscribe(
|
492
|
+
<code>unsubscribe(id, headers=<optional hash>)</code>
|
485
493
|
</td>
|
486
494
|
<td style="background-color: #bfb;">true</td>
|
487
495
|
<td style="background-color: #bfb;">true</td>
|
data/lib/onstomp/client.rb
CHANGED
@@ -79,6 +79,9 @@ class OnStomp::Client
|
|
79
79
|
# @param [{#to_sym => #to_s}] headers
|
80
80
|
# @return [self]
|
81
81
|
def connect headers={}
|
82
|
+
# FIXME: This is a quick fix to force the Threaded IO processor to
|
83
|
+
# complete its work before we establish a connection.
|
84
|
+
processor_inst.stop
|
82
85
|
@connection = OnStomp::Connections.connect self, headers,
|
83
86
|
{ :'accept-version' => @versions.join(','), :host => @host,
|
84
87
|
:'heart-beat' => @heartbeats.join(','), :login => @login,
|
@@ -30,7 +30,9 @@ class OnStomp::Components::ThreadedProcessor
|
|
30
30
|
end
|
31
31
|
rescue OnStomp::StopReceiver
|
32
32
|
rescue Exception
|
33
|
-
|
33
|
+
# FIXME: This is pretty hacky, too. The problem is one of race
|
34
|
+
# conditions and how we access the connection.
|
35
|
+
raise if @run_thread == Thread.current
|
34
36
|
end
|
35
37
|
end
|
36
38
|
self
|
@@ -63,13 +65,16 @@ class OnStomp::Components::ThreadedProcessor
|
|
63
65
|
# and the {OnStomp::Client client} is still
|
64
66
|
# {OnStomp::Client#connected? connected} after the thread is joined.
|
65
67
|
def stop
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
68
|
+
if @run_thread
|
69
|
+
begin
|
70
|
+
@run_thread.raise OnStomp::StopReceiver if @run_thread.alive?
|
71
|
+
@run_thread.join
|
72
|
+
rescue OnStomp::StopReceiver
|
73
|
+
rescue IOError, SystemCallError
|
74
|
+
raise if @client.connected?
|
75
|
+
end
|
76
|
+
@run_thread = nil
|
71
77
|
end
|
72
|
-
@run_thread = nil
|
73
78
|
self
|
74
79
|
end
|
75
80
|
end
|
@@ -220,6 +220,13 @@ class OnStomp::Connections::Base
|
|
220
220
|
rescue EOFError
|
221
221
|
triggered_close $!.message
|
222
222
|
rescue Exception
|
223
|
+
# TODO: Fix this potential race condition the right way.
|
224
|
+
# This is the problematic area! If the user (or failover library)
|
225
|
+
# try to reconnect the Client when the connection is closed, the
|
226
|
+
# exception won't be raised until the IO Processing thread has
|
227
|
+
# already been joined to the main thread. Thus, the connection gets
|
228
|
+
# re-established, the "dying" thread re-enters here, and immediately
|
229
|
+
# raises the exception that terminated it.
|
223
230
|
triggered_close $!.message, :terminated
|
224
231
|
raise
|
225
232
|
end
|
@@ -53,14 +53,14 @@ module OnStomp::Connections::Heartbeating
|
|
53
53
|
end
|
54
54
|
|
55
55
|
# Returns true if client-side heartbeating is disabled, or
|
56
|
-
# {#duration_since_transmitted} has not exceeded {#heartbeat_client_limit}
|
56
|
+
# {OnStomp::Connections::Base#duration_since_transmitted} has not exceeded {#heartbeat_client_limit}
|
57
57
|
# @return [true, false]
|
58
58
|
def client_pulse?
|
59
59
|
heartbeat_client_limit == 0 || duration_since_transmitted <= heartbeat_client_limit
|
60
60
|
end
|
61
61
|
|
62
62
|
# Returns true if broker-side heartbeating is disabled, or
|
63
|
-
# {#duration_since_received} has not exceeded {#heartbeat_broker_limit}
|
63
|
+
# {OnStomp::Connections::Base#duration_since_received} has not exceeded {#heartbeat_broker_limit}
|
64
64
|
# @return [true, false]
|
65
65
|
def broker_pulse?
|
66
66
|
heartbeat_broker_limit == 0 || duration_since_received <= heartbeat_broker_limit
|
@@ -87,16 +87,17 @@ class OnStomp::Failover::Client
|
|
87
87
|
# {OnStomp::Client#disconnect disconnect} on the {#active_client}
|
88
88
|
def disconnect *args, &block
|
89
89
|
if active_client
|
90
|
-
Thread.pass until connected?
|
90
|
+
Thread.pass until connected? || @failed
|
91
91
|
@client_mutex.synchronize do
|
92
92
|
@disconnecting = true
|
93
|
-
active_client.disconnect *args, &block
|
93
|
+
active_client.disconnect *args, &block if connected?
|
94
94
|
end
|
95
95
|
end
|
96
96
|
end
|
97
97
|
|
98
98
|
private
|
99
99
|
def reconnect
|
100
|
+
@failed = false
|
100
101
|
attempt = 1
|
101
102
|
until connected? || retry_exceeded?(attempt)
|
102
103
|
sleep_for_retry attempt
|
@@ -112,9 +113,9 @@ class OnStomp::Failover::Client
|
|
112
113
|
trigger_failover_retry :after, attempt
|
113
114
|
attempt += 1
|
114
115
|
end
|
115
|
-
|
116
|
-
|
117
|
-
|
116
|
+
@failed = !connected?
|
117
|
+
trigger_failover_event(:connected, :on, active_client) unless @failed
|
118
|
+
!@failed
|
118
119
|
end
|
119
120
|
|
120
121
|
def retry_exceeded? attempt
|
data/lib/onstomp/version.rb
CHANGED
data/spec/onstomp/client_spec.rb
CHANGED
@@ -117,6 +117,7 @@ module OnStomp
|
|
117
117
|
{ :'accept-version' => '1.1', :host => 'my host',
|
118
118
|
:'heart-beat' => '30,110', :login => 'my login',
|
119
119
|
:passcode => 's3cr3t' }, pending_events, 30, 50).and_return(connection)
|
120
|
+
processor.should_receive(:stop)
|
120
121
|
processor.should_receive(:start)
|
121
122
|
client.stub(:pending_connection_events => pending_events)
|
122
123
|
client.versions = '1.1'
|
@@ -107,6 +107,27 @@ module OnStomp::Failover
|
|
107
107
|
active_client.should_receive(:disconnect).with(:header1 => 'value 1')
|
108
108
|
client.disconnect :header1 => 'value 1'
|
109
109
|
end
|
110
|
+
it "should disconnect promptly if retrying exceeds maximum attempts" do
|
111
|
+
client.retry_attempts = 3
|
112
|
+
client.retry_delay = 0
|
113
|
+
active_client.stub(:connected? => false)
|
114
|
+
active_client.stub(:connect).and_return do
|
115
|
+
active_client.stub(:connected? => true)
|
116
|
+
end
|
117
|
+
client.connect
|
118
|
+
actual_disconnect = client.method(:disconnect)
|
119
|
+
client.stub(:disconnect).and_return do |*args|
|
120
|
+
active_client.stub(:connect => false)
|
121
|
+
active_client.stub(:connected? => false)
|
122
|
+
# Fire this off in a separate thread, as would be the real case
|
123
|
+
t = Thread.new do
|
124
|
+
connection.trigger_event :on_closed, active_client, connection
|
125
|
+
end
|
126
|
+
Thread.pass while t.alive?
|
127
|
+
actual_disconnect.call *args
|
128
|
+
end
|
129
|
+
client.disconnect :header1 => 'value 1'
|
130
|
+
end
|
110
131
|
end
|
111
132
|
|
112
133
|
describe ".transmit" do
|
metadata
CHANGED
@@ -1,71 +1,68 @@
|
|
1
|
-
--- !ruby/object:Gem::Specification
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
2
|
name: onstomp
|
3
|
-
version: !ruby/object:Gem::Version
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 1.0.5
|
4
5
|
prerelease:
|
5
|
-
version: 1.0.4
|
6
6
|
platform: ruby
|
7
|
-
authors:
|
7
|
+
authors:
|
8
8
|
- Ian D. Eccles
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
- !ruby/object:Gem::Dependency
|
12
|
+
date: 2011-10-13 00:00:00.000000000Z
|
13
|
+
dependencies:
|
14
|
+
- !ruby/object:Gem::Dependency
|
16
15
|
name: rspec
|
17
|
-
|
18
|
-
requirement: &id001 !ruby/object:Gem::Requirement
|
16
|
+
requirement: &2156950640 !ruby/object:Gem::Requirement
|
19
17
|
none: false
|
20
|
-
requirements:
|
18
|
+
requirements:
|
21
19
|
- - ~>
|
22
|
-
- !ruby/object:Gem::Version
|
20
|
+
- !ruby/object:Gem::Version
|
23
21
|
version: 2.4.0
|
24
22
|
type: :development
|
25
|
-
version_requirements: *id001
|
26
|
-
- !ruby/object:Gem::Dependency
|
27
|
-
name: simplecov
|
28
23
|
prerelease: false
|
29
|
-
|
24
|
+
version_requirements: *2156950640
|
25
|
+
- !ruby/object:Gem::Dependency
|
26
|
+
name: simplecov
|
27
|
+
requirement: &2156950180 !ruby/object:Gem::Requirement
|
30
28
|
none: false
|
31
|
-
requirements:
|
32
|
-
- -
|
33
|
-
- !ruby/object:Gem::Version
|
29
|
+
requirements:
|
30
|
+
- - ! '>='
|
31
|
+
- !ruby/object:Gem::Version
|
34
32
|
version: 0.3.0
|
35
33
|
type: :development
|
36
|
-
version_requirements: *id002
|
37
|
-
- !ruby/object:Gem::Dependency
|
38
|
-
name: yard
|
39
34
|
prerelease: false
|
40
|
-
|
35
|
+
version_requirements: *2156950180
|
36
|
+
- !ruby/object:Gem::Dependency
|
37
|
+
name: yard
|
38
|
+
requirement: &2156949720 !ruby/object:Gem::Requirement
|
41
39
|
none: false
|
42
|
-
requirements:
|
43
|
-
- -
|
44
|
-
- !ruby/object:Gem::Version
|
40
|
+
requirements:
|
41
|
+
- - ! '>='
|
42
|
+
- !ruby/object:Gem::Version
|
45
43
|
version: 0.6.0
|
46
44
|
type: :development
|
47
|
-
version_requirements: *id003
|
48
|
-
- !ruby/object:Gem::Dependency
|
49
|
-
name: rake
|
50
45
|
prerelease: false
|
51
|
-
|
46
|
+
version_requirements: *2156949720
|
47
|
+
- !ruby/object:Gem::Dependency
|
48
|
+
name: rake
|
49
|
+
requirement: &2156949340 !ruby/object:Gem::Requirement
|
52
50
|
none: false
|
53
|
-
requirements:
|
54
|
-
- -
|
55
|
-
- !ruby/object:Gem::Version
|
56
|
-
version:
|
51
|
+
requirements:
|
52
|
+
- - ! '>='
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: '0'
|
57
55
|
type: :development
|
58
|
-
|
59
|
-
|
60
|
-
|
56
|
+
prerelease: false
|
57
|
+
version_requirements: *2156949340
|
58
|
+
description: Client library for message passing with brokers that support the Stomp
|
59
|
+
protocol.
|
60
|
+
email:
|
61
61
|
- ian.eccles@gmail.com
|
62
62
|
executables: []
|
63
|
-
|
64
63
|
extensions: []
|
65
|
-
|
66
64
|
extra_rdoc_files: []
|
67
|
-
|
68
|
-
files:
|
65
|
+
files:
|
69
66
|
- .autotest
|
70
67
|
- .gitignore
|
71
68
|
- .rspec
|
@@ -80,7 +77,6 @@ files:
|
|
80
77
|
- examples/openuri.rb
|
81
78
|
- extra_doc/API.md
|
82
79
|
- extra_doc/API.md.erb
|
83
|
-
- extra_doc/DeveloperNarrative.md
|
84
80
|
- extra_doc/UserNarrative.md
|
85
81
|
- lib/onstomp.rb
|
86
82
|
- lib/onstomp/client.rb
|
@@ -197,32 +193,29 @@ files:
|
|
197
193
|
- yard_extensions.rb
|
198
194
|
homepage: http://github.com/meadvillerb/onstomp
|
199
195
|
licenses: []
|
200
|
-
|
201
196
|
post_install_message:
|
202
197
|
rdoc_options: []
|
203
|
-
|
204
|
-
require_paths:
|
198
|
+
require_paths:
|
205
199
|
- lib
|
206
|
-
required_ruby_version: !ruby/object:Gem::Requirement
|
200
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
207
201
|
none: false
|
208
|
-
requirements:
|
209
|
-
- -
|
210
|
-
- !ruby/object:Gem::Version
|
202
|
+
requirements:
|
203
|
+
- - ! '>='
|
204
|
+
- !ruby/object:Gem::Version
|
211
205
|
version: 1.8.7
|
212
|
-
required_rubygems_version: !ruby/object:Gem::Requirement
|
206
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
213
207
|
none: false
|
214
|
-
requirements:
|
215
|
-
- -
|
216
|
-
- !ruby/object:Gem::Version
|
217
|
-
version:
|
208
|
+
requirements:
|
209
|
+
- - ! '>='
|
210
|
+
- !ruby/object:Gem::Version
|
211
|
+
version: '0'
|
218
212
|
requirements: []
|
219
|
-
|
220
213
|
rubyforge_project: onstomp-core
|
221
|
-
rubygems_version: 1.
|
214
|
+
rubygems_version: 1.8.10
|
222
215
|
signing_key:
|
223
216
|
specification_version: 3
|
224
217
|
summary: Client for message queues implementing the Stomp protocol interface.
|
225
|
-
test_files:
|
218
|
+
test_files:
|
226
219
|
- spec/onstomp/client_spec.rb
|
227
220
|
- spec/onstomp/components/frame_headers_spec.rb
|
228
221
|
- spec/onstomp/components/frame_spec.rb
|
@@ -286,4 +279,3 @@ test_files:
|
|
286
279
|
- spec/support/custom_argument_matchers.rb
|
287
280
|
- spec/support/frame_matchers.rb
|
288
281
|
- spec/support/shared_frame_method_examples.rb
|
289
|
-
has_rdoc:
|
@@ -1,123 +0,0 @@
|
|
1
|
-
# A Narrative for Developers
|
2
|
-
|
3
|
-
This document explores the `OnStomp` library through a narrative aimed at end
|
4
|
-
developers who wish to extend or modify the library. It will start with the
|
5
|
-
basics and work through the important code through exposition and examples.
|
6
|
-
It may be helpful to
|
7
|
-
review the [STOMP specification](http://stomp.github.com/index.html) before
|
8
|
-
diving into this document. It's also important to note that `onstomp` can
|
9
|
-
only be used with Ruby 1.8.7+. Support for Rubies prior to 1.8.7 does not
|
10
|
-
exist, and even requiring the library in your code will probably generate
|
11
|
-
errors.
|
12
|
-
|
13
|
-
## Clients & Frames
|
14
|
-
|
15
|
-
An instance of {OnStomp::Client} is the primary way a user will interact
|
16
|
-
with the `OnStomp` gem. It provides the helper methods to generate STOMP
|
17
|
-
frames by including the {OnStomp::Interfaces::FrameMethods} mixin, and allows
|
18
|
-
binding event callbacks by including {OnStomp::Interfaces::ClientEvents}
|
19
|
-
(which in turn includes {OnStomp::Interfaces::EventManager}.) Every client
|
20
|
-
instance will provide the same frame methods, regardless of the version of
|
21
|
-
the STOMP protocol being used. This is accomplished through by a client's use
|
22
|
-
of {OnStomp::Connections connections} and
|
23
|
-
{OnStomp::Connections::Serializers serializers} to actually generate the
|
24
|
-
frames and convert them to their appropriate string representation. You can
|
25
|
-
read more about these components in a later section.
|
26
|
-
|
27
|
-
All of the frame methods (eg: {OnStomp::Interfaces::FrameMethods#send send},
|
28
|
-
{OnStomp::Interfaces::FrameMethods#send unsubscribe}) will either generate a
|
29
|
-
new {OnStomp::Components::Frame} instance or raise an error if the STOMP
|
30
|
-
protocol version negotiated between broker and client does not support
|
31
|
-
the requested command (eg: STOMP 1.0 does not support NACK frames.) All
|
32
|
-
frame instances are composed of a {OnStomp::Components::Frame#command command},
|
33
|
-
a set of {OnStomp::Components::Frame#headers headers}, and a
|
34
|
-
{OnStomp::Components::Frame#body body}.
|
35
|
-
|
36
|
-
A frame's {OnStomp::Components::Frame#command command} attribute is a string
|
37
|
-
that matches the corresponding STOMP command (eg: SEND, RECEIPT) with one
|
38
|
-
exception: heart-beats. The STOMP 1.1 protocol supports "heart-beating" to
|
39
|
-
let brokers and clients know that the connection is still active on the other
|
40
|
-
end by sending bare line-feed (ie: `\n`) characters between frame exchanges.
|
41
|
-
As a result, calling {OnStomp::Interfaces::FrameMethods#beat beat} on a client
|
42
|
-
will generate a frame whose command attribute is `nil`. This in turn lets the
|
43
|
-
serializer know that this isn't a true frame and it will convert it to
|
44
|
-
+"\n"+ instead of performing the normal serialization operation.
|
45
|
-
|
46
|
-
A frame's {OnStomp::Components::FrameHeaders headers} behave much like a
|
47
|
-
standard Ruby `Hash` but with a few important differences. First, the order
|
48
|
-
that header names were added is preserved. This is also true of Ruby 1.9+
|
49
|
-
hashes but not those of Ruby 1.8.7, and as a result there is some code
|
50
|
-
to maintain the ordering when running 1.8.7. Second, accessing headers
|
51
|
-
is somewhat indifferent:
|
52
|
-
|
53
|
-
frame[:some_header] = 'a value'
|
54
|
-
frame["some_header"] #=> 'a value'
|
55
|
-
|
56
|
-
What actually happens is all header names are converted to `Symbol`s
|
57
|
-
(by calling `obj.to_sym`) before any setting or getting takes place. Using
|
58
|
-
an object as a header name that does not respond to `to_sym` will raise an
|
59
|
-
error. The final major difference between headers and hashes is that header
|
60
|
-
values are only strings:
|
61
|
-
|
62
|
-
frame[:another_header] = 42
|
63
|
-
frame[:another_header] #=> '42'
|
64
|
-
|
65
|
-
If the object passed as a header value cannot be converted to a string an
|
66
|
-
error will be raised.
|
67
|
-
|
68
|
-
For most kinds of frames, the {OnStomp::Components::Frame#body body} attribute
|
69
|
-
will often be an empty string or `nil`. The only frames that support
|
70
|
-
non-empty bodies are SEND, MESSAGE, and ERROR.
|
71
|
-
|
72
|
-
## Events
|
73
|
-
|
74
|
-
### Frame-centric Events
|
75
|
-
|
76
|
-
Event triggering sequence for client generated frames:
|
77
|
-
|
78
|
-
1. `client.send ...` is invoked and a SEND frame is created
|
79
|
-
1. The event `before_transmitting` is triggered for the SEND frame
|
80
|
-
1. The event `before_send` is triggered for the SEND frame
|
81
|
-
1. The SEND frame is added to the {OnStomp::Connections::Base connection}'s
|
82
|
-
write buffer
|
83
|
-
1. Some amount of time passes
|
84
|
-
1. The SEND frame is serialized and fully written to the broker.
|
85
|
-
1. The event `after_transmitting` is triggered for the SEND frame
|
86
|
-
1. The event `on_send` is triggered for the SEND frame
|
87
|
-
|
88
|
-
Event triggering sequence for broker generated frames:
|
89
|
-
|
90
|
-
1. The broker writes a MESSAGE frame to the TCP/IP socket
|
91
|
-
1. Some amount of time passes
|
92
|
-
1. The client fully reads and de-serializes the MESSAGE frame
|
93
|
-
1. The event `before_receiving` is triggered for the MESSAGE frame
|
94
|
-
1. The event `before_message` is triggered for the MESSAGE frame
|
95
|
-
1. The event `after_receiving` is triggered for the MESSAGE frame
|
96
|
-
1. The event `on_message` is triggered for the MESSAGE frame
|
97
|
-
|
98
|
-
### Connection-centric Events
|
99
|
-
|
100
|
-
Event trigger sequence for connection events:
|
101
|
-
|
102
|
-
1. An IO error occurs while the connection is reading or writing
|
103
|
-
1. The connection closes its socket
|
104
|
-
1. The connection triggers :on\_terminated
|
105
|
-
1. The connection triggers :on\_closed
|
106
|
-
|
107
|
-
## Subscription and Receipt Management
|
108
|
-
|
109
|
-
### Subscription Manager
|
110
|
-
|
111
|
-
### Receipt Manager
|
112
|
-
|
113
|
-
## URI Based Configuration
|
114
|
-
|
115
|
-
## Processors
|
116
|
-
|
117
|
-
## Connections & Serializers
|
118
|
-
|
119
|
-
### Connections
|
120
|
-
|
121
|
-
### Serializers
|
122
|
-
|
123
|
-
|