nebulous_stomp 2.0.1 → 2.0.2

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: 210d0ff5d3c99590ab6356e5456e2fa67e9ab0ae
4
- data.tar.gz: ac6782c4ef1969f7f0854de505a393927487cd00
3
+ metadata.gz: a4ac7c514b6d925e6186924b2dd93a175de94e02
4
+ data.tar.gz: 8aca7aa180be4c84fe6ccbe89b172980cd2a56a1
5
5
  SHA512:
6
- metadata.gz: e12b2880dff2e61135575fcb2f694315621fcd8a69f29156e01eec0d1248b8f679241d1907bf75da452ec3bb6cf69152009e364ed9aeaa218b2735c929a7daf2
7
- data.tar.gz: 2e5a0161b8c527dd8633562d1f359b781e105554a4c4d396c2dcba265f78750c0697051d0049cc9f26e6ef060b68cc97358d358e64a6caa1d0a64d3065922f92
6
+ metadata.gz: abb4de512e2aec3d8720505f9f06d7a00b2d5aa4caba2a1e9dab977f6c36cb6970f791289509cc6fbe96b945d6eeec84a65d7fe86b54d7402b97104dcd71c18d
7
+ data.tar.gz: 3e44c452fa7f94cd331cfc637b90b427c5171bd7fa9663b4ebe5118320e8d1ea8554628b57bcecfcc55cbc2f7f69aed9d13f49951c8e1ce82836db55cb7b26d5
data/.hgtags CHANGED
@@ -16,3 +16,4 @@ cff04defabb0895ff2f032087b97ea9616bee6a9 1.14
16
16
  6ddf180c9a2fc1cef55f5d128faa4d5df28d1353 1.1.5
17
17
  6da65ce15fab9722deb05d8c0ed2d0c8e2cfe2ff 2.0.0
18
18
  9c4ec9af8f6b8a848082bf118be037696ff357c7 2.0.1
19
+ 63eb0028eeedf7cc3938fd8ecda1add9246fb905 2.02
@@ -18,18 +18,6 @@ module NebulousStomp
18
18
  # The target name as set up by call to Nebulous::add_target
19
19
  attr_reader :target
20
20
 
21
- # The 'verb' part of the message
22
- attr_reader :verb
23
-
24
- # The 'parameters' part of the message
25
- attr_reader :params
26
-
27
- # The 'description' part of the message
28
- attr_reader :desc
29
-
30
- # The 'replyID' header to use in this message
31
- attr_reader :replyID
32
-
33
21
  # Message timeout in seconds
34
22
  attr_reader :mTimeout
35
23
 
@@ -73,21 +61,23 @@ module NebulousStomp
73
61
  NebulousStomp.logger.debug(__FILE__) {"New NebRequest for verb #{verb}"}
74
62
 
75
63
  @target = target.to_s
76
- @verb = verb.to_s
77
- @params = params.nil? ? nil : params.to_s
78
- @desc = desc.nil? ? nil : desc.to_s
79
64
  @stomp_handler = stompHandler
80
65
  @redis_handler = redisHandler
81
66
  @requestQ = nil
82
67
  @responseQ = nil
83
68
  @message = nil
84
- @replyID = nil
85
69
  @mTimeout = 0
86
70
  @cTimeout = 0
87
71
 
72
+ xverb = verb.to_s
73
+ xparams = params.nil? ? nil : params.to_s
74
+ xdesc = desc.nil? ? nil : desc.to_s
75
+
88
76
  @redis_handler ||= RedisHandler.new( Param.get(:redisConnectHash) )
89
77
  @stomp_handler ||= StompHandler.new( Param.get(:stompConnectHash) )
90
78
 
79
+ neb_setup if nebulous_on?
80
+ @message = Message.from_parts(@responseQ, nil, xverb, xparams, xdesc)
91
81
  neb_connect if nebulous_on?
92
82
  end
93
83
 
@@ -112,7 +102,7 @@ module NebulousStomp
112
102
 
113
103
  # If we've lost the connection then reconnect but *keep replyID*
114
104
  @stomp_handler.stomp_connect unless @stomp_handler.connected?
115
- @replyID = @stomp_handler.calc_reply_id if @replyID.nil?
105
+ @message.reply_id = @stomp_handler.calc_reply_id if @message.reply_id.nil?
116
106
 
117
107
  neb_qna(mTimeout)
118
108
 
@@ -201,14 +191,23 @@ module NebulousStomp
201
191
  end
202
192
 
203
193
 
194
+ #
195
+ # Some of our attributes are actually on Message
196
+ #
197
+
198
+ def verb; @message ? @message.verb : nil; end
199
+ def params; @message ? @message.params : nil; end
200
+ def desc; @message ? @message.desc : nil; end
201
+ def replyID; @message ? @message.reply_id : nil; end
202
+
203
+
204
204
  private
205
205
 
206
206
 
207
207
  ##
208
208
  # Connect to STOMP etc and do initial setup
209
- # Called automatically by initialize, if Nebulous is 'on' in the config.
210
209
  #
211
- def neb_connect
210
+ def neb_setup
212
211
  targetHash = Param.get_target(@target)
213
212
  raise NebulousError, "Unknown target #{target}" if targetHash.nil?
214
213
 
@@ -216,11 +215,16 @@ module NebulousStomp
216
215
  @mTimeout = targetHash[:messageTimeout] || Param.get(:messageTimeout)
217
216
  @requestQ = targetHash[:sendQueue]
218
217
  @responseQ = targetHash[:receiveQueue]
219
- @message = Message.from_parts(@responseQ, nil, verb, params, desc)
220
218
 
221
- @stomp_handler.stomp_connect
222
- @replyID = @stomp_handler.calc_reply_id
219
+ self
220
+ end
223
221
 
222
+
223
+ # Called automatically by initialize, if Nebulous is 'on' in the config.
224
+ #
225
+ def neb_connect
226
+ @stomp_handler.stomp_connect
227
+ @message.reply_id = @stomp_handler.calc_reply_id
224
228
  self
225
229
  end
226
230
 
@@ -236,7 +240,12 @@ module NebulousStomp
236
240
 
237
241
  response = nil
238
242
  @stomp_handler.listen_with_timeout(@responseQ, mTimeout) do |msg|
239
- response = msg
243
+ if replyID && msg.in_reply_to != replyID
244
+ false
245
+ else
246
+ response = msg
247
+ true
248
+ end
240
249
  end
241
250
 
242
251
  response
@@ -17,11 +17,15 @@ module NebulousStomp
17
17
  ##
18
18
  # Initialise an instance of the handler by passing it the connection hash
19
19
  #
20
+ # If no hash is passed, we try and get it from Nebulous::Params
21
+ #
20
22
  # We use the optional testRedis parameter to mock connections to Redis, for
21
23
  # testing. It's probably of no use to anyone else.
22
24
  #
23
- def initialize(connectHash, testRedis=nil)
24
- @redis_hash = connectHash ? connectHash.dup : nil
25
+ def initialize(connectHash=nil, testRedis=nil)
26
+ @redis_hash = connectHash ? connectHash.dup : nil
27
+ @redis_hash ||= Param.get(:redisConnectHash)
28
+
25
29
  @test_redis = testRedis
26
30
  @redis = nil
27
31
  end
@@ -110,10 +110,14 @@ module NebulousStomp
110
110
 
111
111
  ##
112
112
  # Initialise StompHandler by passing the parameter hash.
113
+ #
114
+ # If no hash is set we try and get it from NebulousStomp::Param.
113
115
  # ONLY set testClient when testing.
114
116
  #
115
- def initialize(connectHash, testClient=nil)
116
- @stomp_hash = connectHash ? connectHash.dup : nil
117
+ def initialize(connectHash=nil, testClient=nil)
118
+ @stomp_hash = connectHash ? connectHash.dup : nil
119
+ @stomp_hash ||= Param.get(:stompConnectHash)
120
+
117
121
  @test_client = testClient
118
122
  @client = nil
119
123
  end
@@ -207,11 +211,13 @@ module NebulousStomp
207
211
  ##
208
212
  # As listen() but give up after yielding a single message, and only wait
209
213
  # for a set number of seconds before giving up anyway.
210
- #--
211
- # Ideally I'd like to DRY this and listen() up, but with this
212
- # yield-within-a-thread stuff going on, I'm actually not sure how to do
213
- # that safely.
214
- #++
214
+ #
215
+ # The behaviour here is slightly different than listen(). If you return true from your block,
216
+ # the message will be consumed and the method will end. Otherwise it will continue until it
217
+ # sees another message, or reaches the timeout.
218
+ #
219
+ # Put another way, since most things are truthy -- if you want to examine messages to find the
220
+ # right one, return false from the block to get another.
215
221
  #
216
222
  def listen_with_timeout(queue, timeout)
217
223
  return unless nebulous_on?
@@ -230,11 +236,13 @@ module NebulousStomp
230
236
  @client.subscribe( queue, {ack: "client-individual"} ) do |msg|
231
237
 
232
238
  begin
233
- unless msg.body == "boo"
234
- yield Message.from_stomp(msg)
235
- done = true
239
+ if msg.body == "boo"
240
+ @client.ack(msg)
241
+ else
242
+ done = yield Message.from_stomp(msg)
243
+ @client.ack(msg) if done
236
244
  end
237
- @client.ack(msg)
245
+
238
246
  rescue =>e
239
247
  NebulousStomp.logger.error(__FILE__) {"Error during polling: #{e}" }
240
248
  end
@@ -1,5 +1,5 @@
1
1
  module NebulousStomp
2
2
 
3
3
  # Nebulous version number
4
- VERSION = "2.0.1"
4
+ VERSION = "2.0.2"
5
5
  end
@@ -1,59 +1,51 @@
1
1
  Nebulous: The Protocol
2
2
  ======================
3
3
 
4
- (It was going to be "The Nebulous Protocol", but that sounds like something with
5
- Matt Damon in it.)
4
+ (It was going to be "The Nebulous Protocol", but that sounds like something with Matt Damon in it.)
6
5
 
7
6
 
8
7
  Introduction
9
8
  ------------
10
- Project Nebulous is a STOMP client written in ABL, and also the protocol that
11
- allows our different systems, ABL or not, to pass messages. This document,
12
- obviously, concentrates on the protocol.
9
+ Project Nebulous is a STOMP client written in ABL, and also the protocol that allows our different
10
+ systems, ABL or not, to pass messages. This document, obviously, concentrates on the protocol.
13
11
 
14
- The basic idea is this: one system passes a message, a _request_; and then
15
- waits for an answer to that message, a _response_, from another system. STOMP
16
- doesn't explicitly support that; the protocol does it.
12
+ The basic idea is this: one system passes a message, a _request_; and then waits for an answer to
13
+ that message, a _response_, from another system. STOMP doesn't explicitly support that; the
14
+ protocol does it.
17
15
 
18
- (Note that a request and a response are just notional terms; you might in
19
- theory have a request which provokes a response which provokes another response
20
- in return, in which case the second message is both a response and a request,
21
- and the terms get rather less useful.)
16
+ (Note that a request and a response are just notional terms; you might in theory have a request
17
+ which provokes a response which provokes another response in return, in which case the second
18
+ message is both a response and a request, and the terms get rather less useful.)
22
19
 
23
20
 
24
21
  The Protocol
25
22
  ------------
26
- Let's start with the actual protocol, the rules. They won't make sense without
27
- reading the rest of the document, but:
23
+ Let's start with the actual protocol, the rules. They won't make sense without reading the rest of the document, but:
28
24
 
29
- 1. Every valid request (that is, every message with an identifiable verb other
30
- than "success" or "error") will always generate a response. If the handling
31
- routine cannot generate a valid response, or if there is no routine to handle
32
- the verb in question, then the response should be the error verb. If no
33
- response is required, you should still receive the success verb.
25
+ 1. Every valid request (that is, every message with an identifiable verb other than "success" or
26
+ "error") will always generate a response. If the handling routine cannot generate a valid
27
+ response, or if there is no routine to handle the verb in question, then the response should be
28
+ the error verb. If no response is required, you should still receive the success verb.
34
29
 
35
- 2. You should expect that requests that do not have a verb will not be responded
36
- to or even understood. (However, there is no general requirement for message
37
- bodies to follow the verb / parameters / description format. If you have a
38
- program that sends a request and waits for a response, the format of that
39
- response is outside the remit of The Protocol.)
30
+ 2. You should expect that requests that do not have a verb will not be responded to or even
31
+ understood. (However, there is no general requirement for message bodies to follow the verb /
32
+ parameters / description format. If you have a program that sends a request and waits for a
33
+ response, the format of that response is outside the remit of The Protocol.)
40
34
 
41
- 3. If a request has the _neb-reply-to_ header, the response should use that as
42
- a destination; otherwise it should be sent to the same destination that the
43
- request was sent to.
35
+ 3. If a request has the _neb-reply-to_ header, the response should use that as a destination;
36
+ otherwise it should be sent to the same destination that the request was sent to.
44
37
 
45
- 4. If the request has a _neb-reply-id_ header, then the response should set the
46
- _neb-in-reply-to_ header to that.
38
+ 4. If the request has a _neb-reply-id_ header, then the response should set the _neb-in-reply-to_
39
+ header to that.
47
40
 
48
- 5. The request may specify the content type of a response (JSON or text) by
49
- it's own content type. That is, if a response can be in either form, it
50
- should take the form of the request as an indication as which to use.
41
+ 5. The request may specify the content type of a response (JSON or text) by it's own content type.
42
+ That is, if a response can be in either form, it should take the form of the request as an
43
+ indication as which to use.
51
44
 
52
- 6. A given queue that is the target of requests within The Protocol will be for
53
- only one system or common group of systems. They may consume (ACK) messages
54
- sent to it even if they do not have the facility to process them. If
55
- multiple systems share a queue, they should understand that messages will be
56
- consumed from it at random.
45
+ 6. A given queue that is the target of requests within The Protocol will be for only one system or
46
+ common group of systems. They may consume (ACK) messages sent to it even if they do not have the
47
+ facility to process them. If multiple systems share a queue, they should understand that
48
+ messages will be consumed from it at random.
57
49
 
58
50
 
59
51
  Components
@@ -64,130 +56,112 @@ By way of an explanation of the above section.
64
56
 
65
57
  STOMP allows you to define custom headers. We have three.
66
58
 
67
- * _neb-reply-to_ is may be set on a request to the destination that any
68
- response should be posted to.
59
+ * _neb-reply-to_ is may be set on a request to the destination that any response should be posted
60
+ to. (See rule 3.)
69
61
 
70
- * _neb-reply-id_ may be set on a request to an arbitrary string to help
71
- you identify the response.
62
+ * _neb-reply-id_ may be set on a request to an arbitrary string to help you identify the response.
72
63
 
73
- * _neb-in-reply-to_ is set on a response and contains the nebulous-reply-id
74
- of the request.
64
+ * _neb-in-reply-to_ is set on a response and contains the neb-reply-id of the request. (see rule 4.)
75
65
 
76
66
  ### Message Body ###
77
67
 
78
- The Protocol specifies a format for the message body. It consists of three
79
- fields:
68
+ The Protocol specifies a format for the message body. It consists of three fields:
80
69
 
81
- * _verb_ is the keyword that tells the receiving system how to process the
82
- message.
70
+ * _verb_ is the keyword that tells the receiving system how to process the message.
83
71
 
84
- * _parameters_ is an arbitrary field that is context-dependant on verb. The
85
- routine that handles the verb is expected to be able to parse it. It is
86
- optional.
72
+ * _parameters_ is an arbitrary field that is context-dependant on verb. The routine that handles
73
+ the verb is expected to be able to parse it. It is optional.
87
74
 
88
75
  * _description_ is a text field and can contain anything. It is optional.
89
76
 
90
- Nebulous supports message bodies in either JSON (in which case parameters is an
91
- array) or plain text (in which case it expects to find the fields formatted in
92
- the same way as STOMP headers: seperated by line breaks, where each line
93
- consists of the field name, a colon, and the value).
77
+ Nebulous supports message bodies in either JSON (in which case parameters is probably an array) or
78
+ plain text (in which case it expects to find the fields formatted in the same way as STOMP headers:
79
+ seperated by line breaks, where each line consists of the field name, a colon, and the value).
94
80
 
95
81
  There are a couple of special verbs:
96
82
 
97
- * _success_ as a verb in a response is used when no information needs to be
98
- returned except that the request operation went ahead without problem.
83
+ * _success_ as a verb in a response is used when no information needs to be returned except that
84
+ the request operation went ahead without problem.
99
85
 
100
- * _error_ as a verb is used when the requested operation failed. The
101
- expectation is that you will put an error message in the description field;
102
- you can use parameters as you see fit, of course.
86
+ * _error_ as a verb is used when the requested operation failed. The expectation is that you will
87
+ put an error message in the description field; you can use parameters as you see fit, of course.
103
88
 
104
89
 
105
90
  Notes on usage
106
91
  --------------
107
- There are two use cases here. The first (let's call it _Q & A_) is when a
108
- process needs information and sends a request, then waits for a response. The
109
- second (let's call it _Responder_) is at the other end of that process; it
110
- camps onto one or more queues waiting for requests, and arranges for responses
111
- to be sent.
92
+
93
+ There are two use cases here. The first (let's call it _Q & A_) is when a process needs information
94
+ and sends a request, then waits for a response. The second (let's call it _Responder_) is at the
95
+ other end of that process; it camps onto one or more queues waiting for requests, and arranges for
96
+ responses to be sent.
112
97
 
113
98
  ### Responder ###
114
99
 
115
- Let's talk about the Responder use case first, since it's simpler; we've
116
- basically been talking about it for the whole of this document. You'll need to
117
- designate a queue for incoming requests on any given system. You might want
118
- more than one; in ABL, where traffic jams are likely because I can't just
119
- spawn up a thread to handle each incoming message, my current thinking is to
120
- have two incoming queues, one for reqests that take a few seconds, and another
121
- for requests that take longer.
122
-
123
- Remember that rule 6 says that any messages that go to a queue like this will
124
- be consumed without concern for whether the message will make sense to the
125
- system in question; this is basically there so that the ABL code can split up
126
- the process of grabbing new messages from the process of working out what they
127
- are and how to answer them.
128
-
129
- But the simplicity is appealing, regardless: post to this queue and the
130
- Responder that looks after this system will process it. Rule 1 guarantees
131
- you an answer so long as the system is up, so if you don't get one then either
132
- the target system is down or it's too busy to respond.
133
-
134
- The expectation is that the Responder system should use the verb of the message
135
- to control how it is dealt with. The parameters field is verb-specific; the
136
- combination of verb, expected parameters, and the nature of the returned
137
- message form a sort of contract, ie "verb x always expects parameters like
138
- this, and always behaves like that in response". This is partly implied by Rule
139
- 2, I think.
100
+ Let's talk about the Responder use case first, since it's simpler; we've basically been talking
101
+ about it for the whole of this document. You'll need to designate a queue for incoming requests on
102
+ any given system. You might want more than one; in ABL, where traffic jams are likely because I
103
+ can't just spawn up a thread to handle each incoming message, my current thinking is to have two
104
+ incoming queues, one for reqests that take a few seconds, and another for requests that take
105
+ longer.
106
+
107
+ Remember that rule 6 says that any messages that go to a queue like this will be consumed without
108
+ concern for whether the message will make sense to the system in question; this is basically there
109
+ so that the ABL code can split up the process of grabbing new messages from the process of working
110
+ out what they are and how to answer them.
111
+
112
+ But the simplicity is appealing, regardless: post to this queue and the Responder that looks after
113
+ this system will process it. Rule 1 guarantees you an answer so long as the system is up, so if you
114
+ don't get one then either the target system is down or it's too busy to respond.
115
+
116
+ The expectation is that the Responder system should use the verb of the message to control how it
117
+ is dealt with. The parameters field is verb-specific; the combination of verb, expected parameters,
118
+ and the nature of the returned message form a sort of contract, ie "verb x always expects
119
+ parameters like this, and always behaves like that in response". This is partly implied by Rule 2,
120
+ I think.
140
121
 
141
122
  ### Q & A ###
142
123
 
143
- The Q & A use case is more interesting since it's what the whole thing is for,
144
- but some of it really falls outside of The Protocol.
145
-
146
- In theory, Rule 3 says you can fail to use _neb-reply-to_ and pick up your
147
- response from the same queue you posted the message to. But rule 6 says that if
148
- you do that you don't have any guarantee at all of getting your message; the
149
- Responder will take it. So for practical purposes you almost always *have* to
150
- set a reply-to queue in your request.
151
-
152
- Likewise, Rule 4 says that _neb-reply-id_ is optional. But in practice you
153
- should almost certainly set it. Yes, you can specify a brand new queue that is
154
- unique to your request -- or probably unique, anyway -- but it turns out that
155
- some message servers, our RabbitMQ included, don't let you subscribe to a queue
156
- that doesn't exist. It's easy enough to create a queue: you just send a message
157
- to it. But now there are two messages in that queue (or more if turns out that
158
- you've got some queue namespace collision after all) and you have to pick your
159
- response from it, and the easiest way is to set a reply id.
160
-
161
- So let's assume a median worst case: you're posting a request to a Responder
162
- queue with a reply-id set to something hopefully unique, and reply-to set to a
163
- common queue that many processes use to pick up replies. There are two
164
- challenges here: first, working out which message is yours; second, avoiding
165
- consuming those messages that are not.
166
-
167
- For a unique reply-id you could do worse than starting with the session ID that
168
- STOMP returns when you send a CONNECT frame; clearly the message server thinks
169
- that is unique, and it should know. In the Ruby Stomp gem, you can get it with
170
- `client.connection_frame().headers["session"]` where client is your
171
- `Stomp::Client` instance; in my ABL jhstomp.p library call `get_session_id()`.
172
-
173
- Now that you have a good reply ID you can tell which is yours by Rule 4; just
174
- test the _neb-in-reply-to_ header of each message.
175
-
176
- The second problem, of avoiding consuming messages that don't match your
177
- reply-id, is handled by careful use of STOMP. If when subscribing you set the
178
- header `ack:client-individual`, then you must manually acknowledge each message
179
- you want to consume with an ACK frame.
180
-
181
- Finally, you get to handle the response. Rule 1 says that it will either be an
182
- error verb, a success verb ... or something else specific to the verb. The
183
- nature of messages in responses is really outside of The Protocol; you are free
184
- to use the verb / parameters / description format if you wish. Again, I'm
185
- assuming that a given verb will always require the same parameters and return
186
- the same message. I think that to do otherwise would be very confusing. But The
187
- Protocol can't enforce that.
188
-
189
- Note also that while The Protocol says that a request should always result in a
190
- response, there is nothing to say that the sender of the request should care --
191
- say, in the example of a request that results in a report being emailed, which
192
- takes 20 minutes.
124
+ The Q & A use case is more interesting since it's what the whole thing is for, but some of it
125
+ really falls outside of The Protocol.
126
+
127
+ In theory, Rule 3 says you can fail to use _neb-reply-to_ and pick up your response from the same
128
+ queue you posted the message to. But rule 6 says that if you do that you don't have any guarantee
129
+ at all of getting your message; the Responder will take it. So for practical purposes you almost
130
+ always *have* to set a reply-to queue in your request.
131
+
132
+ Likewise, Rule 4 says that _neb-reply-id_ is optional. But in practice you should almost certainly
133
+ set it. Yes, you can specify a brand new queue that is unique to your request -- or probably
134
+ unique, anyway -- but it turns out that some message servers, our RabbitMQ included, don't let you
135
+ subscribe to a queue that doesn't exist. It's easy enough to create a queue: you just send a
136
+ message to it. But now there are two messages in that queue (or more if turns out that you've got
137
+ some queue namespace collision after all) and you have to pick your response from it, and the
138
+ easiest way is to set a reply id.
139
+
140
+ So let's assume a median worst case: you're posting a request to a Responder queue with a reply-id
141
+ set to something hopefully unique, and reply-to set to a common queue that many processes use to
142
+ pick up replies. There are two challenges here: first, working out which message is yours; second,
143
+ avoiding consuming those messages that are not.
144
+
145
+ For a unique reply-id you could do worse than starting with the session ID that STOMP returns when
146
+ you send a CONNECT frame; clearly the message server thinks that is unique, and it should know. In
147
+ the Ruby Stomp gem, you can get it with `client.connection_frame().headers["session"]` where client
148
+ is your `Stomp::Client` instance; in my ABL jhstomp.p library call `get_session_id()`.
149
+
150
+ Now that you have a good reply ID you can tell which is yours by Rule 4; just test the
151
+ _neb-in-reply-to_ header of each message.
152
+
153
+ The second problem, of avoiding consuming messages that don't match your reply-id, is handled by
154
+ careful use of STOMP. If when subscribing you set the header `ack:client-individual`, then you must
155
+ manually acknowledge each message you want to consume with an ACK frame.
156
+
157
+ Finally, you get to handle the response. Rule 1 says that it will either be an error verb, a
158
+ success verb ... or something else specific to the verb. The nature of messages in responses is
159
+ really outside of The Protocol; you are free to use the verb / parameters / description format if
160
+ you wish. Again, I'm assuming that a given verb will always require the same parameters and return
161
+ the same message. I think that to do otherwise would be very confusing. But The Protocol can't
162
+ enforce that.
163
+
164
+ Note also that while The Protocol says that a request should always result in a response, there is
165
+ nothing to say that the sender of the request should care -- say, in the example of a request that
166
+ results in a report being emailed, which takes 20 minutes.
193
167
 
@@ -14,9 +14,9 @@ describe NebRequestNull do
14
14
 
15
15
  def disable(thing)
16
16
  NebulousStomp.init( :stompConnectHash => thing == :stomp ? {} : stomp_hash,
17
- :redisConnectHash => thing == :redis ? {} : redis_hash,
18
- :messageTimeout => 5,
19
- :cacheTimeout => 20 )
17
+ :redisConnectHash => thing == :redis ? {} : redis_hash,
18
+ :messageTimeout => 5,
19
+ :cacheTimeout => 20 )
20
20
 
21
21
  NebulousStomp.add_target( :accord,
22
22
  :sendQueue => "/queue/laplace.dev",
@@ -36,6 +36,7 @@ describe NebRequestNull do
36
36
 
37
37
  let(:redis_hash) { {host: '127.0.0.1', port: 6379, db: 0} }
38
38
 
39
+
39
40
  before do
40
41
  disable(:nothing)
41
42
  end
@@ -95,7 +96,7 @@ describe NebRequestNull do
95
96
 
96
97
  it "returns something from STOMP" do
97
98
  req = new_request('accord', 'foo')
98
- req.insert_fake_stomp( Message.from_parts('', '', 'foo', 'bar', 'baz') )
99
+ req.insert_fake_stomp( Message.from_parts(nil, req.replyID, 'foo', 'bar', 'baz') )
99
100
  response = req.send_no_cache
100
101
 
101
102
  expect( response ).to be_a NebulousStomp::Message
@@ -124,7 +125,7 @@ describe NebRequestNull do
124
125
 
125
126
  it "returns a Message object from STOMP the first time" do
126
127
  req = new_request('accord', 'foo')
127
- req.insert_fake_stomp( Message.from_parts('', '', 'foo', 'bar', 'baz') )
128
+ req.insert_fake_stomp( Message.from_parts(nil, req.replyID, 'foo', 'bar', 'baz') )
128
129
 
129
130
  response = req.send
130
131
  expect( response ).to be_a NebulousStomp::Message
@@ -133,7 +134,7 @@ describe NebRequestNull do
133
134
 
134
135
  it "returns the answer from the cache if there is one" do
135
136
  req = new_request('accord', 'foo')
136
- req.insert_fake_stomp( Message.from_parts('', '', 'foo', 'bar', 'baz') )
137
+ req.insert_fake_stomp( Message.from_parts(nil, req.replyID, 'foo', 'bar', 'baz') )
137
138
  req.insert_fake_redis('xxx', {'verb' => 'frog'}.to_json)
138
139
  response = req.send
139
140
 
@@ -143,14 +144,14 @@ describe NebRequestNull do
143
144
 
144
145
  it "allows you to specify a message timeout" do
145
146
  req = new_request('accord', 'foo')
146
- req.insert_fake_stomp( Message.from_parts('', '', 'foo', 'bar', 'baz') )
147
+ req.insert_fake_stomp( Message.from_parts(nil, req.replyID, 'foo', 'bar', 'baz') )
147
148
 
148
149
  expect{ req.send(3) }.not_to raise_exception
149
150
  end
150
151
 
151
152
  it "allows you to specify a message timeout & cache timeout" do
152
153
  req = new_request('accord', 'foo')
153
- req.insert_fake_stomp( Message.from_parts('', '', 'foo', 'bar', 'baz') )
154
+ req.insert_fake_stomp( Message.from_parts(nil, req.replyID, 'foo', 'bar', 'baz') )
154
155
 
155
156
  expect{ req.send(3, 120) }.not_to raise_exception
156
157
  end
@@ -163,7 +164,7 @@ describe NebRequestNull do
163
164
  it 'still works if Redis is turned off in the config' do
164
165
  disable(:redis)
165
166
  r = new_request('accord', 'tom')
166
- r.insert_fake_stomp( Message.from_parts('', '', 'foo', 'bar', 'baz') )
167
+ r.insert_fake_stomp( Message.from_parts(nil, r.replyID, 'foo', 'bar', 'baz') )
167
168
 
168
169
  response = r.send
169
170
  expect( response ).to be_a NebulousStomp::Message
@@ -104,8 +104,8 @@ describe NebRequest do
104
104
  describe "#send_no_cache" do
105
105
 
106
106
  it "returns something from STOMP" do
107
- stomp_h.insert_fake( Message.from_parts('', '', 'foo', 'bar', 'baz') )
108
107
  request = new_request('accord', 'foo')
108
+ stomp_h.insert_fake( Message.from_parts(nil, request.replyID, 'foo', 'bar', 'baz') )
109
109
  response = request.send_no_cache
110
110
 
111
111
  expect( response ).to be_a NebulousStomp::Message
@@ -133,8 +133,8 @@ describe NebRequest do
133
133
  describe "#send" do
134
134
 
135
135
  it "returns a Message object from STOMP the first time" do
136
- stomp_h.insert_fake( Message.from_parts('', '', 'foo', 'bar', 'baz') )
137
136
  request = new_request('accord', 'foo')
137
+ stomp_h.insert_fake( Message.from_parts(nil, request.replyID, 'foo', 'bar', 'baz') )
138
138
 
139
139
  response = request.send
140
140
  expect( response ).to be_a NebulousStomp::Message
@@ -142,7 +142,7 @@ describe NebRequest do
142
142
  end
143
143
 
144
144
  it "returns the answer from the cache the second time" do
145
- stomp_h.insert_fake( Message.from_parts('', '', 'foo', 'bar', 'baz') )
145
+ stomp_h.insert_fake( Message.from_parts(nil, nil, 'foo', 'bar', 'baz') )
146
146
  redis_h.insert_fake('xxx', {'verb' => 'frog'}.to_json)
147
147
 
148
148
  # First time
@@ -158,15 +158,15 @@ describe NebRequest do
158
158
  end
159
159
 
160
160
  it "allows you to specify a message timeout" do
161
- stomp_h.insert_fake( Message.from_parts('', '', 'foo', 'bar', 'baz') )
162
161
  request = new_request('accord', 'foo')
162
+ stomp_h.insert_fake( Message.from_parts(nil, request.replyID, 'foo', 'bar', 'baz') )
163
163
 
164
164
  expect{ request.send(3) }.not_to raise_exception
165
165
  end
166
166
 
167
167
  it "allows you to specify a message timeout & cache timeout" do
168
- stomp_h.insert_fake( Message.from_parts('', '', 'foo', 'bar', 'baz') )
169
168
  request = new_request('accord', 'foo')
169
+ stomp_h.insert_fake( Message.from_parts(nil, request.replyID, 'foo', 'bar', 'baz') )
170
170
 
171
171
  expect{ request.send(3, 120) }.not_to raise_exception
172
172
  end
@@ -178,8 +178,8 @@ describe NebRequest do
178
178
 
179
179
  it 'still works if Redis is turned off in the config' do
180
180
  rh = RedisHandlerNull.new({})
181
- stomp_h.insert_fake( Message.from_parts('', '', 'foo', 'bar', 'baz') )
182
181
  r = NebRequest.new('accord', 'tom', nil, nil, stomp_h, rh)
182
+ stomp_h.insert_fake( Message.from_parts(nil, r.replyID, 'foo', 'bar', 'baz') )
183
183
 
184
184
  response = r.send
185
185
  expect( response ).to be_a NebulousStomp::Message
@@ -158,7 +158,6 @@ describe StompHandler do
158
158
 
159
159
  it "takes an initialization hash" do
160
160
  expect{ StompHandler.new(foo: 'bar') }.not_to raise_exception
161
- expect{ StompHandler.new }.to raise_exception ArgumentError
162
161
  end
163
162
 
164
163
  end
@@ -6,8 +6,9 @@ require 'nebulous_stomp'
6
6
  # It's really only here to double check that the Stomp gem hasn't moved the
7
7
  # goalposts (again).
8
8
  #
9
- # In order for it to work, the JH RabbitMQ server has to be where we left it.
10
- # So this test won't work for you out of the box, unless you are me.
9
+ # In order for it to work, the JH RabbitMQ server has to be where we left it. And you need a
10
+ # responder listening to /queue/nebulout.test for the 'ping' verb. So this test won't work for you
11
+ # out of the box, unless you are me.
11
12
  #
12
13
  describe 'through test' do
13
14
 
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: nebulous_stomp
3
3
  version: !ruby/object:Gem::Version
4
- version: 2.0.1
4
+ version: 2.0.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - Andy Jones
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2016-06-21 00:00:00.000000000 Z
11
+ date: 2016-08-23 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler