ruote-amqp 2.2.0 → 2.3.0
Sign up to get free protection for your applications and to get access to all the features.
- data/CHANGELOG.txt +5 -0
- data/CREDITS.txt +4 -0
- data/LICENSE.txt +21 -0
- data/README.md +173 -0
- data/Rakefile +30 -28
- data/TODO.txt +8 -0
- data/lib/ruote/amqp/alert_participant.rb +146 -0
- data/lib/ruote/amqp/participant.rb +350 -0
- data/lib/ruote/amqp/receiver.rb +181 -0
- data/lib/ruote/amqp/version.rb +28 -0
- data/lib/ruote/amqp.rb +68 -0
- data/lib/ruote-amqp.rb +1 -78
- data/ruote-amqp.gemspec +9 -6
- data/spec/alert_participant_spec.rb +58 -0
- data/spec/participant_spec.rb +268 -122
- data/spec/participant_subclass_spec.rb +66 -0
- data/spec/receiver_spec.rb +187 -79
- data/spec/spec_helper.rb +12 -70
- data/spec/support/ruote_amqp_helper.rb +40 -0
- metadata +28 -34
- data/PostInstall.txt +0 -12
- data/README.rdoc +0 -91
- data/lib/ruote-amqp/launchitem_listener.rb +0 -22
- data/lib/ruote-amqp/participant.rb +0 -241
- data/lib/ruote-amqp/receiver.rb +0 -147
- data/lib/ruote-amqp/version.rb +0 -6
- data/lib/ruote-amqp/workitem_listener.rb +0 -12
- data/spec/launchitem_listener_spec.rb +0 -70
- data/spec/ruote_amqp_spec.rb +0 -18
- data/spec/support/ruote_helpers.rb +0 -29
- data/spec/support/ruote_matchers.rb +0 -51
- data/spec/workitem_listener_spec.rb +0 -66
@@ -1,22 +0,0 @@
|
|
1
|
-
|
2
|
-
module RuoteAMQP
|
3
|
-
|
4
|
-
#
|
5
|
-
# Got replaced by RuoteAMQP::Receiver
|
6
|
-
#
|
7
|
-
# This class is kept for backward compatibility.
|
8
|
-
#
|
9
|
-
class LaunchitemListener < ::RuoteAMQP::Receiver
|
10
|
-
|
11
|
-
# Start a new LaunchItem listener
|
12
|
-
#
|
13
|
-
# @param [ Ruote::Engine, Ruote::Storage ] A configured ruote engine or storage instance
|
14
|
-
# @param opts :queue / :unsubscribe
|
15
|
-
#
|
16
|
-
def initialize(engine_or_storage, opts={})
|
17
|
-
|
18
|
-
super(engine_or_storage, opts.merge(:launchitems => :only))
|
19
|
-
end
|
20
|
-
end
|
21
|
-
end
|
22
|
-
|
@@ -1,241 +0,0 @@
|
|
1
|
-
|
2
|
-
require 'ruote/part/local_participant'
|
3
|
-
require 'ruote-amqp'
|
4
|
-
|
5
|
-
|
6
|
-
module RuoteAMQP
|
7
|
-
|
8
|
-
#
|
9
|
-
# = AMQP Participants
|
10
|
-
#
|
11
|
-
# The RuoteAMQP::ParticipantProxy allows you to send workitems (serialized as
|
12
|
-
# JSON) or messages to any AMQP queues right from the process
|
13
|
-
# definition. When combined with the RuoteAMQP::Receiver you can easily
|
14
|
-
# leverage an extremely powerful local/remote participant
|
15
|
-
# combinations.
|
16
|
-
#
|
17
|
-
# For local/remote participants The local part of the
|
18
|
-
# RuoteAMQP::ParticipantProxy relies on the presence of a
|
19
|
-
# RuoteAMQP::Receiver. Workitems are sent to the remote participant
|
20
|
-
# and the local part does not normally reply to the engine. Instead
|
21
|
-
# the engine will continue when a reply is received on the
|
22
|
-
# 'ruote_workitems' queue (see RuoteAMQP::Receiver).
|
23
|
-
#
|
24
|
-
# Of course, the standard :forget => true format can be used even
|
25
|
-
# with remote particpants and :forget can even be set as a default in
|
26
|
-
# the options.
|
27
|
-
#
|
28
|
-
# A simple way to create a remote participant to act upon workitems
|
29
|
-
# is to use the daemon-kit ruote responder.
|
30
|
-
#
|
31
|
-
# Simple AMQP messages are treated as 'fire and forget' and the flow
|
32
|
-
# will continue when the local participant has queued the message
|
33
|
-
# for sending. (As there is no meaningful way to receive a workitem
|
34
|
-
# in reply).
|
35
|
-
#
|
36
|
-
# == Configuration
|
37
|
-
#
|
38
|
-
# AMQP configuration is handled by directly manipulating the
|
39
|
-
# values of the +AMQP.settings+ hash, as provided by the AMQP
|
40
|
-
# gem. No AMQP defaults are set by the participant.
|
41
|
-
#
|
42
|
-
# == Usage
|
43
|
-
#
|
44
|
-
# Define the queue used by an AMQP participant :
|
45
|
-
#
|
46
|
-
# engine.register_participant(
|
47
|
-
# :delete_user, RuoteAMQP::ParticipantProxy, 'queue' => 'user_manager')
|
48
|
-
#
|
49
|
-
# Sending a workitem to the remote participant defined above:
|
50
|
-
#
|
51
|
-
# Ruote.process_definition do
|
52
|
-
# sequence do
|
53
|
-
# delete_user
|
54
|
-
# end
|
55
|
-
# end
|
56
|
-
#
|
57
|
-
# Let the local participant reply to the engine without involving
|
58
|
-
# the receiver
|
59
|
-
#
|
60
|
-
# Ruote.process_definition do
|
61
|
-
# sequence do
|
62
|
-
# delete_user :forget => true
|
63
|
-
# end
|
64
|
-
# end
|
65
|
-
#
|
66
|
-
# Setting up the participant in a slightly more 'raw' way:
|
67
|
-
#
|
68
|
-
# engine.register_participant(
|
69
|
-
# :amqp, RuoteAMQP::ParticipantProxy )
|
70
|
-
#
|
71
|
-
# Sending a workitem to a specific queue:
|
72
|
-
#
|
73
|
-
# Ruote.process_definition do
|
74
|
-
# sequence do
|
75
|
-
# amqp :queue => 'test', 'command' => '/run/regression_test'
|
76
|
-
# end
|
77
|
-
# end
|
78
|
-
#
|
79
|
-
# Setup a 'fire and forget' participant that always replies to the
|
80
|
-
# engine:
|
81
|
-
#
|
82
|
-
# engine.register_participant(
|
83
|
-
# :jfdi, RuoteAMQP::ParticipantProxy, 'forget' => true )
|
84
|
-
#
|
85
|
-
# Sending a message example to a specific queue (both steps are
|
86
|
-
# equivalent):
|
87
|
-
#
|
88
|
-
# Ruote.process_definition do
|
89
|
-
# sequence do
|
90
|
-
# amqp :queue => 'test', :message => 'foo'
|
91
|
-
# amqp :queue => 'test', :message => 'foo', :forget => true
|
92
|
-
# end
|
93
|
-
# end
|
94
|
-
#
|
95
|
-
#
|
96
|
-
# == AMQP notes
|
97
|
-
#
|
98
|
-
# The participant currently only makes use of direct
|
99
|
-
# exchanges. Possible future improvements might see use for topic
|
100
|
-
# and fanout exchanges as well.
|
101
|
-
#
|
102
|
-
# The direct exchanges are always marked as durable by the
|
103
|
-
# participant, and messages are marked as persistent by default (see
|
104
|
-
# #RuoteAMQP)
|
105
|
-
#
|
106
|
-
class ParticipantProxy
|
107
|
-
|
108
|
-
include Ruote::LocalParticipant
|
109
|
-
|
110
|
-
# The following parameters are used in the process definition.
|
111
|
-
#
|
112
|
-
# An options hash with the same keys to provide defaults is
|
113
|
-
# accepted at registration time (see above).
|
114
|
-
#
|
115
|
-
# * :queue => (string) The AMQP queue used by the remote participant.
|
116
|
-
# nil by default.
|
117
|
-
# * :forget => (bool) Whether the flow should block until the remote
|
118
|
-
# participant replies.
|
119
|
-
# false by default
|
120
|
-
#
|
121
|
-
def initialize(options)
|
122
|
-
|
123
|
-
RuoteAMQP.start!
|
124
|
-
|
125
|
-
@options = {
|
126
|
-
'queue' => nil,
|
127
|
-
'forget' => false,
|
128
|
-
}.merge(options.inject({}) { |h, (k, v)|
|
129
|
-
h[k.to_s] = v; h
|
130
|
-
})
|
131
|
-
#
|
132
|
-
# the inject is here to make sure that all options have String keys
|
133
|
-
end
|
134
|
-
|
135
|
-
# Process the workitem at hand. By default the workitem will be
|
136
|
-
# published to the direct exchange specified in the +queue+
|
137
|
-
# workitem parameter. You can specify a +message+ workitem
|
138
|
-
# parameter to have that sent instead of the workitem.
|
139
|
-
#
|
140
|
-
def consume(workitem)
|
141
|
-
|
142
|
-
target_queue = determine_queue(workitem)
|
143
|
-
|
144
|
-
raise 'no queue specified (outbound delivery)' unless target_queue
|
145
|
-
|
146
|
-
q = MQ.queue(target_queue, :durable => true)
|
147
|
-
forget = determine_forget(workitem)
|
148
|
-
|
149
|
-
opts = {
|
150
|
-
:persistent => RuoteAMQP.use_persistent_messages?,
|
151
|
-
:content_type => 'application/json' }
|
152
|
-
|
153
|
-
if message = workitem.fields['message'] || workitem.params['message']
|
154
|
-
|
155
|
-
forget = true # sending a message implies 'forget' => true
|
156
|
-
|
157
|
-
q.publish(message, opts)
|
158
|
-
|
159
|
-
else
|
160
|
-
|
161
|
-
q.publish(encode_workitem(workitem), opts)
|
162
|
-
end
|
163
|
-
|
164
|
-
reply_to_engine(workitem) if forget
|
165
|
-
end
|
166
|
-
|
167
|
-
# (Stops the underlying queue subscription)
|
168
|
-
#
|
169
|
-
def stop
|
170
|
-
|
171
|
-
RuoteAMQP.stop!
|
172
|
-
end
|
173
|
-
|
174
|
-
def cancel(fei, flavour)
|
175
|
-
#
|
176
|
-
# TODO : sending a cancel item is not a bad idea, especially if the
|
177
|
-
# job done over the amqp fence lasts...
|
178
|
-
#
|
179
|
-
end
|
180
|
-
|
181
|
-
# The current AMQP (0.6.7) has 1 queue per thread. If you let the default
|
182
|
-
# "one thread per participant consume call" kick in, you'll end up with
|
183
|
-
# 1 queue per consume call (and...)
|
184
|
-
#
|
185
|
-
# So, by returning true here, we force the queue to be always the same.
|
186
|
-
#
|
187
|
-
# Many thanks to https://github.com/weifeng365 for reporting this issue
|
188
|
-
# and suggesting the fix.
|
189
|
-
#
|
190
|
-
# TODO : should we have something to close queues when the engine / worker
|
191
|
-
# shuts down ?
|
192
|
-
# or is it already covered in the #stop ?
|
193
|
-
#
|
194
|
-
def do_not_thread
|
195
|
-
|
196
|
-
true
|
197
|
-
end
|
198
|
-
|
199
|
-
private
|
200
|
-
|
201
|
-
def determine_forget(workitem)
|
202
|
-
|
203
|
-
return workitem.params['forget'] if workitem.params.has_key?('forget')
|
204
|
-
return @options['forget'] if @options.has_key?('forget')
|
205
|
-
false
|
206
|
-
end
|
207
|
-
|
208
|
-
def determine_queue(workitem)
|
209
|
-
|
210
|
-
workitem.params['queue'] || @options['queue']
|
211
|
-
end
|
212
|
-
|
213
|
-
# Encodes the workitem as JSON. Makes sure to add to the field 'params'
|
214
|
-
# an entry named 'participant_options' which contains the options of
|
215
|
-
# this participant.
|
216
|
-
#
|
217
|
-
def encode_workitem(wi)
|
218
|
-
|
219
|
-
wi.params['participant_options'] = @options
|
220
|
-
|
221
|
-
Rufus::Json.encode(wi.to_h)
|
222
|
-
end
|
223
|
-
end
|
224
|
-
|
225
|
-
#
|
226
|
-
# Kept for backward compatibility.
|
227
|
-
#
|
228
|
-
# You should use RuoteAMQP::ParticipantProxy.
|
229
|
-
#
|
230
|
-
class Participant < ParticipantProxy
|
231
|
-
|
232
|
-
def initialize(options)
|
233
|
-
puts '=' * 80
|
234
|
-
puts "RuoteAMQP::Participant will be deprecated soon (2.1.12)"
|
235
|
-
puts "please use RuoteAMQP::ParticipantProxy instead"
|
236
|
-
puts '=' * 80
|
237
|
-
super
|
238
|
-
end
|
239
|
-
end
|
240
|
-
end
|
241
|
-
|
data/lib/ruote-amqp/receiver.rb
DELETED
@@ -1,147 +0,0 @@
|
|
1
|
-
|
2
|
-
require 'ruote-amqp'
|
3
|
-
|
4
|
-
|
5
|
-
module RuoteAMQP
|
6
|
-
|
7
|
-
#
|
8
|
-
# = AMQP Receiver
|
9
|
-
#
|
10
|
-
# Used in conjunction with the RuoteAMQP::Participant, the WorkitemListener
|
11
|
-
# subscribes to a specific direct exchange and monitors for
|
12
|
-
# incoming workitems. It expects workitems to arrive serialized as
|
13
|
-
# JSON.
|
14
|
-
#
|
15
|
-
# == Configuration
|
16
|
-
#
|
17
|
-
# AMQP configuration is handled by directly manipulating the values of
|
18
|
-
# the +AMQP.settings+ hash, as provided by the AMQP gem. No
|
19
|
-
# defaults are set by the listener. The only +option+ parsed by
|
20
|
-
# the initializer of the workitem listener is the +queue+ key (Hash
|
21
|
-
# expected). If no +queue+ key is set, the listener will subscribe
|
22
|
-
# to the +ruote_workitems+ direct exchange for workitems, otherwise it will
|
23
|
-
# subscribe to the direct exchange provided.
|
24
|
-
#
|
25
|
-
# == Usage
|
26
|
-
#
|
27
|
-
# Register the engine or storage with the listener:
|
28
|
-
#
|
29
|
-
# RuoteAMQP::Receiver.new(engine_or_storage)
|
30
|
-
#
|
31
|
-
# The workitem listener leverages the asynchronous nature of the amqp gem,
|
32
|
-
# so no timers are setup when initialized.
|
33
|
-
#
|
34
|
-
# == Options
|
35
|
-
#
|
36
|
-
# :queue and :launchitems
|
37
|
-
#
|
38
|
-
# See the RuoteAMQP::Participant docs for information on sending
|
39
|
-
# workitems out to remote participants, and have them send replies
|
40
|
-
# to the correct direct exchange specified in the workitem
|
41
|
-
# attributes.
|
42
|
-
#
|
43
|
-
class Receiver < Ruote::Receiver
|
44
|
-
|
45
|
-
attr_reader :queue
|
46
|
-
|
47
|
-
# Starts a new Receiver
|
48
|
-
#
|
49
|
-
# Two arguments for this method.
|
50
|
-
#
|
51
|
-
# The first oone should be a Ruote::Engine, a Ruote::Storage or
|
52
|
-
# a Ruote::Worker instance.
|
53
|
-
#
|
54
|
-
# The second one is a hash for options. There are two known options :
|
55
|
-
#
|
56
|
-
# :queue for setting the queue on which to listen (defaults to
|
57
|
-
# 'ruote_workitems').
|
58
|
-
#
|
59
|
-
# The :launchitems option :
|
60
|
-
#
|
61
|
-
# :launchitems => true
|
62
|
-
# # the receiver accepts workitems and launchitems
|
63
|
-
# :launchitems => false
|
64
|
-
# # the receiver only accepts workitems
|
65
|
-
# :launchitems => :only
|
66
|
-
# # the receiver only accepts launchitems
|
67
|
-
#
|
68
|
-
def initialize(engine_or_storage, opts={})
|
69
|
-
|
70
|
-
super(engine_or_storage)
|
71
|
-
|
72
|
-
@launchitems = opts[:launchitems]
|
73
|
-
|
74
|
-
@queue =
|
75
|
-
opts[:queue] ||
|
76
|
-
(@launchitems == :only ? 'ruote_launchitems' : 'ruote_workitems')
|
77
|
-
|
78
|
-
RuoteAMQP.start!
|
79
|
-
|
80
|
-
if opts[:unsubscribe]
|
81
|
-
MQ.queue(@queue, :durable => true).unsubscribe
|
82
|
-
sleep 0.300
|
83
|
-
end
|
84
|
-
|
85
|
-
MQ.queue(@queue, :durable => true).subscribe do |message|
|
86
|
-
if AMQP.closing?
|
87
|
-
# do nothing, we're going down
|
88
|
-
else
|
89
|
-
handle(message)
|
90
|
-
end
|
91
|
-
end
|
92
|
-
end
|
93
|
-
|
94
|
-
def stop
|
95
|
-
|
96
|
-
RuoteAMQP.stop!
|
97
|
-
end
|
98
|
-
|
99
|
-
# (feel free to overwrite me)
|
100
|
-
#
|
101
|
-
def decode_workitem(msg)
|
102
|
-
|
103
|
-
(Rufus::Json.decode(msg) rescue nil)
|
104
|
-
end
|
105
|
-
|
106
|
-
private
|
107
|
-
|
108
|
-
def handle(msg)
|
109
|
-
|
110
|
-
item = decode_workitem(msg)
|
111
|
-
|
112
|
-
return unless item.is_a?(Hash)
|
113
|
-
|
114
|
-
not_li = ! item.has_key?('definition')
|
115
|
-
|
116
|
-
return if @launchitems == :only && not_li
|
117
|
-
return unless @launchitems || not_li
|
118
|
-
|
119
|
-
if not_li
|
120
|
-
receive(item) # workitem resumes in its process instance
|
121
|
-
else
|
122
|
-
launch(item) # new process instance launch
|
123
|
-
end
|
124
|
-
|
125
|
-
rescue => e
|
126
|
-
# something went wrong
|
127
|
-
# let's simply discard the message
|
128
|
-
$stderr.puts('=' * 80)
|
129
|
-
$stderr.puts(self.class.name)
|
130
|
-
$stderr.puts("couldn't handle incoming message :")
|
131
|
-
$stderr.puts('')
|
132
|
-
$stderr.puts(msg.inspect)
|
133
|
-
$stderr.puts('')
|
134
|
-
$stderr.puts(Rufus::Json.pretty_encode(item)) rescue nil
|
135
|
-
$stderr.puts('')
|
136
|
-
$stderr.puts(e.inspect)
|
137
|
-
$stderr.puts(e.backtrace)
|
138
|
-
$stderr.puts('=' * 80)
|
139
|
-
end
|
140
|
-
|
141
|
-
def launch(hash)
|
142
|
-
|
143
|
-
super(hash['definition'], hash['fields'] || {}, hash['variables'] || {})
|
144
|
-
end
|
145
|
-
end
|
146
|
-
end
|
147
|
-
|
data/lib/ruote-amqp/version.rb
DELETED
@@ -1,70 +0,0 @@
|
|
1
|
-
|
2
|
-
require File.join(File.dirname(__FILE__), 'spec_helper')
|
3
|
-
|
4
|
-
#
|
5
|
-
# NOTE : RuoteAMQP::LaunchitemListener has been depreacted in favour of
|
6
|
-
# RuoteAMQP::Receiver
|
7
|
-
#
|
8
|
-
|
9
|
-
describe RuoteAMQP::LaunchitemListener do
|
10
|
-
|
11
|
-
after(:each) do
|
12
|
-
purge_engine
|
13
|
-
end
|
14
|
-
|
15
|
-
it 'launches processes' do
|
16
|
-
|
17
|
-
json = {
|
18
|
-
'definition' => %{
|
19
|
-
Ruote.process_definition :name => 'test' do
|
20
|
-
sequence do
|
21
|
-
echo '${f:foo}'
|
22
|
-
end
|
23
|
-
end
|
24
|
-
},
|
25
|
-
'fields' => { 'foo' => 'bar' }
|
26
|
-
}.to_json
|
27
|
-
|
28
|
-
RuoteAMQP::LaunchitemListener.new(@engine)
|
29
|
-
|
30
|
-
MQ.queue('ruote_launchitems', :durable => true).publish(json)
|
31
|
-
|
32
|
-
sleep 0.5
|
33
|
-
|
34
|
-
@engine.should_not have_errors
|
35
|
-
@engine.should_not have_remaining_expressions
|
36
|
-
|
37
|
-
@tracer.to_s.should == 'bar'
|
38
|
-
end
|
39
|
-
|
40
|
-
it 'discards corrupt process definitions' do
|
41
|
-
|
42
|
-
json = {
|
43
|
-
'definition' => %{
|
44
|
-
I'm a broken process definition
|
45
|
-
},
|
46
|
-
'fields' => { 'foo' => 'bar' }
|
47
|
-
}.to_json
|
48
|
-
|
49
|
-
RuoteAMQP::LaunchitemListener.new(@engine, :unsubscribe => true)
|
50
|
-
|
51
|
-
serr = String.new
|
52
|
-
err = StringIO.new(serr, 'w+')
|
53
|
-
$stderr = err
|
54
|
-
|
55
|
-
MQ.queue('ruote_launchitems', :durable => true).publish(json)
|
56
|
-
|
57
|
-
sleep 0.5
|
58
|
-
|
59
|
-
err.close
|
60
|
-
$stderr = STDERR
|
61
|
-
|
62
|
-
@engine.should_not have_errors
|
63
|
-
@engine.should_not have_remaining_expressions
|
64
|
-
|
65
|
-
@tracer.to_s.should == ''
|
66
|
-
|
67
|
-
serr.should match(/^===/)
|
68
|
-
end
|
69
|
-
end
|
70
|
-
|
data/spec/ruote_amqp_spec.rb
DELETED
@@ -1,18 +0,0 @@
|
|
1
|
-
|
2
|
-
require File.join(File.dirname(__FILE__), 'spec_helper')
|
3
|
-
|
4
|
-
|
5
|
-
describe RuoteAMQP do
|
6
|
-
|
7
|
-
it "uses persistent messages by default" do
|
8
|
-
|
9
|
-
RuoteAMQP.use_persistent_messages?.should be_true
|
10
|
-
end
|
11
|
-
|
12
|
-
it "allows switching to transient messages" do
|
13
|
-
|
14
|
-
RuoteAMQP.use_persistent_messages = false
|
15
|
-
RuoteAMQP.use_persistent_messages?.should be_false
|
16
|
-
end
|
17
|
-
end
|
18
|
-
|
@@ -1,29 +0,0 @@
|
|
1
|
-
|
2
|
-
module RuoteSpecHelpers
|
3
|
-
|
4
|
-
def purge_engine
|
5
|
-
|
6
|
-
# TODO : adapt to ruote 2.1.10
|
7
|
-
end
|
8
|
-
|
9
|
-
def run_definition(pdef)
|
10
|
-
|
11
|
-
wfid = @engine.launch(pdef)
|
12
|
-
|
13
|
-
#r = @engine.wait_for(wfid)
|
14
|
-
#@engine.wait_for(wfid) if r['action'] == 'ceased'
|
15
|
-
# # make sure to wait for 'terminated'
|
16
|
-
@engine.wait_for(:inactive)
|
17
|
-
|
18
|
-
@engine.should_not have_errors
|
19
|
-
@engine.should_not have_remaining_expressions
|
20
|
-
|
21
|
-
purge_engine
|
22
|
-
end
|
23
|
-
|
24
|
-
def noisy(on = true)
|
25
|
-
|
26
|
-
@engine.context.logger.noisy = on
|
27
|
-
end
|
28
|
-
end
|
29
|
-
|
@@ -1,51 +0,0 @@
|
|
1
|
-
|
2
|
-
RSpec::Matchers.define :have_errors do |*args|
|
3
|
-
|
4
|
-
match do |engine|
|
5
|
-
|
6
|
-
@ps = if wfid = args.shift
|
7
|
-
engine.processes(wfid)
|
8
|
-
else
|
9
|
-
engine.processes.first
|
10
|
-
end
|
11
|
-
|
12
|
-
@ps ? (@ps.errors.size != 0) : false
|
13
|
-
end
|
14
|
-
|
15
|
-
failure_message_for_should do |engine|
|
16
|
-
|
17
|
-
"Expected engine to have errors, but didn't"
|
18
|
-
end
|
19
|
-
|
20
|
-
failure_message_for_should_not do |engine|
|
21
|
-
|
22
|
-
"Expected the engine to not have errors, but it did.\n" +
|
23
|
-
@ps.errors.map { |e| " * error: #{e.message}\n\"#{e.trace}\"" }.join("\n")
|
24
|
-
end
|
25
|
-
|
26
|
-
description do
|
27
|
-
end
|
28
|
-
end
|
29
|
-
|
30
|
-
RSpec::Matchers.define :have_remaining_expressions do
|
31
|
-
|
32
|
-
match do |engine|
|
33
|
-
|
34
|
-
(engine.storage.get_many('expressions').size != 0)
|
35
|
-
end
|
36
|
-
|
37
|
-
failure_message_for_should do |engine|
|
38
|
-
|
39
|
-
"Expected engine to have processes remaining, but it didn't"
|
40
|
-
end
|
41
|
-
|
42
|
-
failure_message_for_should_not do |engine|
|
43
|
-
|
44
|
-
"Expected engine to have no processes remaining, but it did." +
|
45
|
-
"#{engine.storage.get_many('expressions').inspect}"
|
46
|
-
end
|
47
|
-
|
48
|
-
description do
|
49
|
-
end
|
50
|
-
end
|
51
|
-
|
@@ -1,66 +0,0 @@
|
|
1
|
-
|
2
|
-
require File.join(File.dirname(__FILE__), 'spec_helper')
|
3
|
-
|
4
|
-
#
|
5
|
-
# NOTE : RuoteAMQP::WorkitemListener has been depreacted in favour of
|
6
|
-
# RuoteAMQP::Receiver
|
7
|
-
#
|
8
|
-
|
9
|
-
|
10
|
-
describe RuoteAMQP::WorkitemListener do
|
11
|
-
|
12
|
-
after(:each) do
|
13
|
-
purge_engine
|
14
|
-
end
|
15
|
-
|
16
|
-
it "handles replies" do
|
17
|
-
|
18
|
-
pdef = Ruote.process_definition :name => 'test' do
|
19
|
-
set :field => 'foo', :value => 'foo'
|
20
|
-
sequence do
|
21
|
-
echo '${f:foo}'
|
22
|
-
amqp :queue => 'test7'
|
23
|
-
echo '${f:foo}'
|
24
|
-
end
|
25
|
-
end
|
26
|
-
|
27
|
-
@engine.register_participant(:amqp, RuoteAMQP::ParticipantProxy)
|
28
|
-
|
29
|
-
RuoteAMQP::WorkitemListener.new(@engine, :unsubscribe => true)
|
30
|
-
|
31
|
-
#@engine.noisy = true
|
32
|
-
|
33
|
-
wfid = @engine.launch(pdef)
|
34
|
-
|
35
|
-
workitem = nil
|
36
|
-
|
37
|
-
begin
|
38
|
-
Timeout::timeout(5) do
|
39
|
-
|
40
|
-
MQ.queue('test7', :durable => true).subscribe { |msg|
|
41
|
-
wi = Ruote::Workitem.new(Rufus::Json.decode(msg))
|
42
|
-
workitem = wi if wi.wfid == wfid
|
43
|
-
}
|
44
|
-
|
45
|
-
loop do
|
46
|
-
break unless workitem.nil?
|
47
|
-
sleep 0.1
|
48
|
-
end
|
49
|
-
end
|
50
|
-
rescue Timeout::Error
|
51
|
-
violated "Timeout waiting for message"
|
52
|
-
end
|
53
|
-
|
54
|
-
workitem.fields['foo'] = 'bar'
|
55
|
-
|
56
|
-
MQ.queue('ruote_workitems', :durable => true).publish(Rufus::Json.encode(workitem.to_h), :persistent => true)
|
57
|
-
|
58
|
-
@engine.wait_for(wfid)
|
59
|
-
|
60
|
-
@engine.should_not have_errors
|
61
|
-
@engine.should_not have_remaining_expressions
|
62
|
-
|
63
|
-
@tracer.to_s.should == "foo\nbar"
|
64
|
-
end
|
65
|
-
end
|
66
|
-
|