ruote-amqp 2.2.0 → 2.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/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
|
-
|