openwferu 0.9.5 → 0.9.6

Sign up to get free protection for your applications and to get access to all the features.
Files changed (65) hide show
  1. data/examples/mano_tracker.rb +11 -13
  2. data/lib/openwfe.rb +2 -4
  3. data/lib/openwfe/contextual.rb +8 -2
  4. data/lib/openwfe/engine/engine.rb +118 -2
  5. data/lib/openwfe/expool/expressionpool.rb +148 -53
  6. data/lib/openwfe/expool/expstorage.rb +36 -4
  7. data/lib/openwfe/expool/yamlexpstorage.rb +18 -0
  8. data/lib/openwfe/expressions/environment.rb +1 -1
  9. data/lib/openwfe/expressions/fe_misc.rb +14 -2
  10. data/lib/openwfe/expressions/fe_raw.rb +27 -11
  11. data/lib/openwfe/expressions/fe_subprocess.rb +45 -12
  12. data/lib/openwfe/expressions/fe_utils.rb +1 -1
  13. data/lib/openwfe/expressions/flowexpression.rb +5 -1
  14. data/lib/openwfe/expressions/raw_prog.rb +80 -32
  15. data/lib/openwfe/expressions/raw_xml.rb +10 -0
  16. data/lib/openwfe/flowexpressionid.rb +28 -7
  17. data/lib/openwfe/listeners/listener.rb +106 -0
  18. data/lib/openwfe/listeners/listeners.rb +140 -0
  19. data/lib/openwfe/listeners/socketlisteners.rb +239 -0
  20. data/lib/openwfe/listeners/sqslisteners.rb +145 -0
  21. data/lib/openwfe/participants/{csvparticipant.rb → csvparticipants.rb} +0 -0
  22. data/lib/openwfe/participants/{enoparticipant.rb → enoparticipants.rb} +1 -1
  23. data/lib/openwfe/participants/participantmap.rb +33 -1
  24. data/lib/openwfe/participants/participants.rb +99 -11
  25. data/lib/openwfe/participants/soapparticipants.rb +28 -8
  26. data/lib/openwfe/participants/socketparticipants.rb +172 -0
  27. data/lib/openwfe/participants/sqsparticipants.rb +121 -0
  28. data/lib/openwfe/rest/definitions.rb +1 -1
  29. data/lib/openwfe/{osocket.rb → rest/osocket.rb} +16 -8
  30. data/lib/openwfe/rest/xmlcodec.rb +41 -5
  31. data/lib/openwfe/storage/yamlfilestorage.rb +10 -13
  32. data/lib/openwfe/util/dollar.rb +23 -2
  33. data/lib/openwfe/util/otime.rb +1 -1
  34. data/lib/openwfe/util/safe.rb +149 -0
  35. data/lib/openwfe/util/scheduler.rb +47 -5
  36. data/lib/openwfe/util/sqs.rb +582 -0
  37. data/lib/openwfe/utils.rb +23 -0
  38. data/lib/openwfe/version.rb +1 -1
  39. data/lib/openwfe/workitem.rb +86 -3
  40. data/lib/openwfe/worklist/storeparticipant.rb +44 -4
  41. data/test/csv_test.rb +1 -1
  42. data/test/eno_test.rb +1 -1
  43. data/test/fei_test.rb +2 -15
  44. data/test/flowtestbase.rb +6 -2
  45. data/test/ft_11_ppd.rb +31 -0
  46. data/test/ft_13_eno.rb +1 -1
  47. data/test/ft_14b_subprocess.rb +74 -0
  48. data/test/ft_15_iterator.rb +0 -1
  49. data/test/ft_19_csv.rb +1 -1
  50. data/test/ft_20_cron.rb +1 -1
  51. data/test/ft_21_cron.rb +1 -1
  52. data/test/ft_27_getflowpos.rb +89 -0
  53. data/test/ft_28_fileparticipant.rb +65 -0
  54. data/test/ft_29_httprb.rb +95 -0
  55. data/test/ft_30_socketlistener.rb +197 -0
  56. data/test/ft_4_misc.rb +2 -1
  57. data/test/hash_test.rb +75 -0
  58. data/test/rake_qtest.rb +5 -4
  59. data/test/raw_prog_test.rb +205 -0
  60. data/test/rutest_utils.rb +16 -0
  61. data/test/safely_test.rb +89 -0
  62. data/test/scheduler_test.rb +71 -0
  63. data/test/sqs_test.rb +103 -0
  64. metadata +21 -6
  65. data/test/journal_persistence_test.rb +0 -147
@@ -0,0 +1,145 @@
1
+ #
2
+ #--
3
+ # Copyright (c) 2007, John Mettraux, OpenWFE.org
4
+ # All rights reserved.
5
+ #
6
+ # Redistribution and use in source and binary forms, with or without
7
+ # modification, are permitted provided that the following conditions are met:
8
+ #
9
+ # . Redistributions of source code must retain the above copyright notice, this
10
+ # list of conditions and the following disclaimer.
11
+ #
12
+ # . Redistributions in binary form must reproduce the above copyright notice,
13
+ # this list of conditions and the following disclaimer in the documentation
14
+ # and/or other materials provided with the distribution.
15
+ #
16
+ # . Neither the name of the "OpenWFE" nor the names of its contributors may be
17
+ # used to endorse or promote products derived from this software without
18
+ # specific prior written permission.
19
+ #
20
+ # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
21
+ # AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22
+ # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
23
+ # ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
24
+ # LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
25
+ # CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
26
+ # SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
27
+ # INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
28
+ # CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
29
+ # ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
30
+ # POSSIBILITY OF SUCH DAMAGE.
31
+ #++
32
+ #
33
+ # $Id: definitions.rb 2725 2006-06-02 13:26:32Z jmettraux $
34
+ #
35
+
36
+ #
37
+ # "made in Japan"
38
+ #
39
+ # John Mettraux at openwfe.org
40
+ #
41
+
42
+ require 'yaml'
43
+ require 'base64'
44
+ require 'monitor'
45
+
46
+ require 'openwfe/service'
47
+ #require 'openwfe/rudefinitions'
48
+ require 'openwfe/util/scheduler'
49
+ require 'openwfe/listeners/listener'
50
+
51
+ require 'openwfe/util/sqs'
52
+
53
+
54
+ #
55
+ # some base listener implementations
56
+ #
57
+ module OpenWFE
58
+
59
+ #
60
+ # Polls an Amazon SQS queue for workitems
61
+ #
62
+ # Workitems can be instances of InFlowWorkItem or LaunchItem.
63
+ #
64
+ # require 'openwfe/listeners/sqslisteners'
65
+ #
66
+ # ql = OpenWFE::SqsListener("workqueue1", engine.application_context)
67
+ #
68
+ # engine.add_workitem_listener(ql, "2m30s")
69
+ # #
70
+ # # thus, the engine will poll our "workqueue1" SQS queue
71
+ # # every 2 minutes and 30 seconds
72
+ #
73
+ class SqsListener < Service
74
+ include MonitorMixin, WorkItemListener, Schedulable
75
+
76
+ attr_reader :queue_name
77
+
78
+ def initialize (queue_name, application_context)
79
+
80
+ @queue_name = queue_name.to_s
81
+
82
+ service_name = "#{self.class}::#{@queue_name}"
83
+
84
+ super(service_name, application_context)
85
+
86
+ linfo { "new() queue is '#{@queue_name}'" }
87
+ end
88
+
89
+ #
90
+ # Will 'find' files in the work directory (by default ./work/in/),
91
+ # extract the workitem in them and feed it back to the engine.
92
+ #
93
+ def trigger (params)
94
+ synchronize do
95
+
96
+ ldebug { "trigger()" }
97
+
98
+ qs = SQS::QueueService.new
99
+
100
+ qs.create_queue(@queue_name)
101
+ # just to be sure it is there
102
+
103
+ while true
104
+
105
+ l = qs.get_messages(
106
+ @queue_name, :timeout => 0, :count => 255)
107
+
108
+ break if l.length < 1
109
+
110
+ l.each do |msg|
111
+
112
+ o = decode_object(msg)
113
+
114
+ handle_object(o)
115
+
116
+ msg.delete
117
+
118
+ ldebug do
119
+ "trigger() " +
120
+ "handled successfully msg #{msg.message_id}"
121
+ end
122
+ end
123
+ end
124
+ end
125
+ end
126
+
127
+ #
128
+ # Extracts a workitem from the message's body.
129
+ #
130
+ # By default, this listeners assumes the workitem is stored in
131
+ # its "hash form" (not directly as a Ruby InFlowWorkItem instance).
132
+ #
133
+ # LaunchItem instances (as hash as well) are also accepted.
134
+ #
135
+ def decode_object (message)
136
+
137
+ o = Base64.decode64(message.message_body)
138
+ o = YAML.load(o)
139
+ o = OpenWFE::workitem_from_h(o)
140
+ o
141
+ end
142
+ end
143
+
144
+ end
145
+
@@ -90,7 +90,7 @@ module OpenWFE
90
90
  # "eno@outoftheblue.co.jp",
91
91
  # File.new("path/to/my/mail/template.txt")))
92
92
  #
93
- # You can also define the email template as a ruby block :
93
+ # You can also define the email template as a Ruby block :
94
94
  #
95
95
  # p = EmailNotificationParticipant.new("googlemail.l.google.com", 25, "eno@co.co.jp") do | flowexpression, participant, workitem |
96
96
  #
@@ -79,10 +79,26 @@ module OpenWFE
79
79
  participant = BlockParticipant.new(block)
80
80
  end
81
81
 
82
+ ldebug do
83
+ "register_participant() "+
84
+ "participant class is #{participant.class}"
85
+ end
86
+
82
87
  if participant.kind_of? Class
88
+
89
+ ldebug { "register_participant() class #{participant}" }
90
+
83
91
  begin
92
+
84
93
  participant = participant.new(regex, @application_context)
85
- rescue
94
+
95
+ rescue Exception => e
96
+ #ldebug do
97
+ # "register_participant() " +
98
+ # "falling back to no param constructor because of \n" +
99
+ # OpenWFE::exception_to_s(e)
100
+ #end
101
+
86
102
  participant = participant.new
87
103
  end
88
104
  end
@@ -109,6 +125,22 @@ module OpenWFE
109
125
  return nil
110
126
  end
111
127
 
128
+ #
129
+ # Deletes the first participant matching the given name.
130
+ #
131
+ def unregister_participant (participant_name)
132
+
133
+ pos = -1
134
+ @participants.each_with_index do |tuple, index|
135
+ if tuple[0].match(participant_name)
136
+ pos = index
137
+ break
138
+ end
139
+ end
140
+ @participants.delete(pos) if pos > -1
141
+ return pos > -1
142
+ end
143
+
112
144
  #
113
145
  # Dispatches to the given participant.
114
146
  # The workitem will be fed to the consume() method of that participant.
@@ -39,6 +39,9 @@
39
39
  # John Mettraux at openwfe.org
40
40
  #
41
41
 
42
+ require 'yaml'
43
+
44
+ require 'openwfe/utils'
42
45
  require 'openwfe/participants/participant'
43
46
 
44
47
 
@@ -48,27 +51,90 @@ require 'openwfe/participants/participant'
48
51
  module OpenWFE
49
52
 
50
53
  #
51
- # The PrintParticipant will just emit its name to the
52
- # test tracer if any or to stdout else.
53
- # Used by some unit tests.
54
+ # Just dumps the incoming workitem in a file as a YAML String.
54
55
  #
55
- class PrintParticipant
56
+ # By default, this participant will not reply to the engine once
57
+ # the workitem got dumped to its file, but you can set its
58
+ # reply_anyway field to true to make it reply anyway...
59
+ #
60
+ class FileParticipant
56
61
  include LocalParticipant
57
62
 
58
- def consume (workitem)
63
+ attr_accessor :reply_anyway, :workdir
59
64
 
60
- tracer = @application_context['__tracer']
65
+ #
66
+ # The constructor expects as a unique optional param either the
67
+ # application_context either the 'output' dir for the participant.
68
+ #
69
+ def initialize (context_or_dir=nil)
61
70
 
62
- if tracer
63
- tracer << workitem.participant_name
71
+ if context_or_dir.kind_of? Hash
72
+ @application_context = context_or_dir
73
+ @workdir = @application_context[:work_directory]
64
74
  else
65
- puts workitem.participant_name
75
+ @workdir = context_or_dir
66
76
  end
67
77
 
68
- reply_to_engine(workitem)
78
+ @workdir = OpenWFE::DEFAULT_WORK_DIRECTORY unless @workdir
79
+ @workdir = "#{@workdir}/out/"
80
+
81
+ @reply_anyway = false
69
82
  end
70
- end
71
83
 
84
+ #
85
+ # The method called by the engine for each incoming workitem.
86
+ #
87
+ def consume (workitem)
88
+
89
+ FileUtils.makedirs(@workdir) unless File.exist?(@workdir)
90
+
91
+ file_name = @workdir + determine_file_name(workitem)
92
+
93
+ dump_to_file(file_name, workitem)
94
+
95
+ reply_to_engine(workitem) if @reply_anyway
96
+ end
97
+
98
+ #
99
+ # This method does the actual job of dumping the workitem (as some
100
+ # YAML to a file).
101
+ # It can be easily overriden.
102
+ #
103
+ def dump_to_file (file_name, workitem)
104
+
105
+ File.open(file_name, "w") do |file|
106
+ file.print encode_workitem(workitem)
107
+ end
108
+ end
109
+
110
+ #
111
+ # You can override this method to control into which file (name)
112
+ # each workitem gets dumped.
113
+ # You could even have a unique file for all workitems transiting
114
+ # through this participant.
115
+ #
116
+ def determine_file_name (workitem)
117
+
118
+ fei = workitem.fei
119
+
120
+ OpenWFE::ensure_for_filename(
121
+ "#{fei.wfid}_#{fei.expression_id}__" +
122
+ "#{fei.workflow_definition_name}__" +
123
+ "#{fei.workflow_definition_revision}" +
124
+ "#{workitem.participant_name}.yaml")
125
+ end
126
+
127
+ protected
128
+
129
+ #
130
+ # By default, uses YAML to serialize the workitem
131
+ # (of course you can override this method).
132
+ #
133
+ def encode_workitem (wi)
134
+ YAML.dump(wi)
135
+ end
136
+ end
137
+
72
138
  #
73
139
  # This participant is used by the register_participant() method of
74
140
  # Engine class.
@@ -119,5 +185,27 @@ module OpenWFE
119
185
  end
120
186
  end
121
187
 
188
+ #
189
+ # The PrintParticipant will just emit its name to the
190
+ # test tracer if any or to stdout else.
191
+ # Used by some unit tests.
192
+ #
193
+ class PrintParticipant
194
+ include LocalParticipant
195
+
196
+ def consume (workitem)
197
+
198
+ tracer = @application_context['__tracer']
199
+
200
+ if tracer
201
+ tracer << workitem.participant_name
202
+ else
203
+ puts workitem.participant_name
204
+ end
205
+
206
+ reply_to_engine(workitem)
207
+ end
208
+ end
209
+
122
210
  end
123
211
 
@@ -57,8 +57,8 @@ module OpenWFE
57
57
  #
58
58
  # engine.register_participant("quote_service", quote_service)
59
59
  #
60
- # TODO #8425 : use blocks as hooks for the mapping (pre/post)
61
- # of workitems into webservice operation params.
60
+ # You can override the method handle_call_result for better mappings
61
+ # between web service calls and the workitems.
62
62
  #
63
63
  class SoapParticipant
64
64
  include LocalParticipant
@@ -79,17 +79,37 @@ module OpenWFE
79
79
 
80
80
  def consume (workitem)
81
81
 
82
- call_params = []
82
+ call_params = prepare_call_params(workitem)
83
83
 
84
- @params.each do |param|
85
- call_params << get_param(workitem, param)
84
+ call_result = @driver.send(@method_name, *call_params)
85
+
86
+ handle_call_result(call_result, workitem)
87
+
88
+ reply_to_engine(workitem)
89
+ end
90
+
91
+ #
92
+ # The base implementation : assumes that for each webservice operation
93
+ # param there is a workitem field with the same name.
94
+ #
95
+ # Feel free to override this method.
96
+ #
97
+ def prepare_call_params (workitem)
98
+
99
+ @params.collect do |param|
100
+ get_param(workitem, param)
86
101
  end
102
+ end
87
103
 
88
- result = @driver.send(@method_name, *call_params)
104
+ #
105
+ # This implementation simply stuffs the result into the workitem
106
+ # as an attribute named "__result__".
107
+ #
108
+ # Feel free to override this method.
109
+ #
110
+ def handle_call_result (result, workitem)
89
111
 
90
112
  workitem.attributes["__result__"] = result
91
-
92
- reply_to_engine(workitem)
93
113
  end
94
114
 
95
115
  protected
@@ -0,0 +1,172 @@
1
+ #
2
+ #--
3
+ # Copyright (c) 2007, John Mettraux, OpenWFE.org
4
+ # All rights reserved.
5
+ #
6
+ # Redistribution and use in source and binary forms, with or without
7
+ # modification, are permitted provided that the following conditions are met:
8
+ #
9
+ # . Redistributions of source code must retain the above copyright notice, this
10
+ # list of conditions and the following disclaimer.
11
+ #
12
+ # . Redistributions in binary form must reproduce the above copyright notice,
13
+ # this list of conditions and the following disclaimer in the documentation
14
+ # and/or other materials provided with the distribution.
15
+ #
16
+ # . Neither the name of the "OpenWFE" nor the names of its contributors may be
17
+ # used to endorse or promote products derived from this software without
18
+ # specific prior written permission.
19
+ #
20
+ # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
21
+ # AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22
+ # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
23
+ # ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
24
+ # LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
25
+ # CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
26
+ # SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
27
+ # INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
28
+ # CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
29
+ # ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
30
+ # POSSIBILITY OF SUCH DAMAGE.
31
+ #++
32
+ #
33
+ # $Id: definitions.rb 2725 2006-06-02 13:26:32Z jmettraux $
34
+ #
35
+
36
+ #
37
+ # "made in Japan"
38
+ #
39
+ # John Mettraux at openwfe.org
40
+ #
41
+
42
+ require 'yaml'
43
+ require 'socket'
44
+
45
+ #require 'openwfe/utils'
46
+ require 'openwfe/rest/xmlcodec'
47
+ require 'openwfe/participants/participant'
48
+
49
+
50
+ #
51
+ # some base participant implementations
52
+ #
53
+ module OpenWFE
54
+
55
+ #
56
+ # This participant implementation dispatches workitems over TCP sockets.
57
+ # By default the workitem are dumped as YAML strings, but you can override
58
+ # the encode_workitem(wi) method.
59
+ #
60
+ # A small example :
61
+ #
62
+ # require 'openwfe/particpants/socketparticipants'
63
+ #
64
+ # sp = OpenWFE::SocketParticipant.new("target.host.xx", 7007)
65
+ #
66
+ # engine.register_participant("Alfred", sp)
67
+ #
68
+ class SocketParticipant
69
+
70
+ attr_accessor :host, :port
71
+
72
+ #
73
+ # The constructor
74
+ #
75
+ def initialize (host, port)
76
+
77
+ @host = host
78
+ @port = port
79
+ end
80
+
81
+ #
82
+ # The method called by the engine for each incoming workitem.
83
+ #
84
+ def consume (workitem)
85
+
86
+ socket = TCPSocket.new(@host, @port)
87
+ socket.puts encode_workitem(workitem)
88
+ socket.close_write
89
+
90
+ reply = ""
91
+ while true
92
+ r = socket.gets
93
+ break unless r
94
+ reply << r
95
+ end
96
+ socket.close
97
+
98
+ decode_reply(reply)
99
+ end
100
+
101
+ #
102
+ # A 'static' method for dispatching workitems, you can use it
103
+ # directly, without instantiating the SocketParticipant :
104
+ #
105
+ # require 'openwfe/participants/socketparticipants'
106
+ #
107
+ # SocketParticipant.dispatch("127.0.0.1", 7007, workitem)
108
+ #
109
+ def SocketParticipant.dispatch (host, port, workitem)
110
+
111
+ SocketParticipant.new(host, port).consume(workitem)
112
+ end
113
+
114
+ protected
115
+
116
+ #
117
+ # By default, uses YAML to serialize the workitem
118
+ # (of course you can override this method).
119
+ #
120
+ def encode_workitem (wi)
121
+ YAML.dump(wi)
122
+ end
123
+
124
+ #
125
+ # By default, will just return the reply without touching it
126
+ #
127
+ def decode_reply (r)
128
+ r
129
+ end
130
+ end
131
+
132
+ #
133
+ # This extension of of SocketParticipant can be used to dispatch
134
+ # workitems towards an OpenWFEja instance, but OpenWFEru's SocketListener
135
+ # understands XML workitems as well.
136
+ #
137
+ class XmlSocketParticipant < SocketParticipant
138
+
139
+ #def initialize (host, port)
140
+ # super
141
+ #end
142
+
143
+ #
144
+ # A 'static' method for dispatching workitems, you can use it
145
+ # directly, without instantiating the SocketParticipant :
146
+ #
147
+ # require 'openwfe/participants/socketparticipants'
148
+ #
149
+ # SocketParticipant.dispatch("127.0.0.1", 7007, workitem)
150
+ #
151
+ def XmlSocketParticipant.dispatch (host, port, workitem)
152
+
153
+ XmlSocketParticipant.new(host, port).consume(workitem)
154
+ end
155
+
156
+ protected
157
+
158
+ def encode_workitem (wi)
159
+
160
+ sxml = OpenWFE::xml_encode(wi)
161
+
162
+ s = "xmlCoder #{sxml.length}\n"
163
+ s << "\n"
164
+ s << sxml
165
+ s << "\n"
166
+ s << "\n"
167
+ s
168
+ end
169
+ end
170
+
171
+ end
172
+