w_flow 0.11.0 → 0.12.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/README.md +106 -34
- data/lib/w_flow/configuration.rb +2 -0
- data/lib/w_flow/data.rb +2 -0
- data/lib/w_flow/node.rb +4 -104
- data/lib/w_flow/node_worker.rb +91 -0
- data/lib/w_flow/process.rb +4 -4
- data/lib/w_flow/process_worker.rb +16 -29
- data/lib/w_flow/tasks_worker.rb +70 -0
- data/lib/w_flow/version.rb +1 -1
- data/lib/w_flow.rb +2 -0
- data/w_flow.gemspec +2 -2
- metadata +7 -6
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 4c6971610a0278716309118842acdfd7532ed202
|
4
|
+
data.tar.gz: bbda595555d7dcc881280bd7369d1456c8561ff6
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 2012a6ea13452f2dc30418ea861fe8f54b5dcb30723cf8aa4a372835b25a9713670695ec4efee5a187b70885f40830e15fe9ddf62c0d85d9ff8c994915c4404d
|
7
|
+
data.tar.gz: fca65b36b9966e01f743fe9619b9477e5200ff96ddf2b23100749d2101b6a26a15a1550cac133067c3a843a52dc9ec81e5782a120e88b3b86480055e52a1f575
|
data/README.md
CHANGED
@@ -8,8 +8,7 @@
|
|
8
8
|
|
9
9
|
WFlow aims to help on designing workflows based on [Single
|
10
10
|
Responsibility Principle](http://en.wikipedia.org/wiki/Single_responsibility_principle). WFlow
|
11
|
-
proposes to achieve this by providing tools to
|
12
|
-
and one task only, and by providing tools to compose these classes.
|
11
|
+
proposes to achieve this by providing tools to help compose those classes into a workflow.
|
13
12
|
|
14
13
|
Word of appreciation for [usecasing](https://github.com/tdantas/usecasing),
|
15
14
|
[interactor](https://github.com/collectiveidea/interactor) and
|
@@ -40,66 +39,139 @@ Or install it yourself as:
|
|
40
39
|
|
41
40
|
## Usage
|
42
41
|
|
43
|
-
|
44
|
-
and publish it in google calendar if needed:
|
42
|
+
In its most simplest form a Process would look like this:
|
45
43
|
|
46
44
|
```ruby
|
47
|
-
|
45
|
+
# Process to retrive a user from the database given a user_id
|
46
|
+
class FindUser
|
47
|
+
# include module Process
|
48
48
|
include WFlow::Process
|
49
49
|
|
50
|
-
#
|
51
|
-
data_reader :appointment_id
|
52
|
-
data_writer :appointment
|
53
|
-
|
54
|
-
# perform is the name of the method that will be invoked when calling 'run'
|
50
|
+
# perform is where you'll execute your business logic
|
55
51
|
def perform
|
56
|
-
|
52
|
+
# flow is an object present in a Process, and it is how you retrieve data
|
53
|
+
# from the current flow, in this case the input user_id
|
54
|
+
user_id = flow.data.user_id
|
57
55
|
|
58
|
-
#
|
59
|
-
|
56
|
+
# when you want to output a value from the Process you set it in data
|
57
|
+
flow.data.user = User.find(user_id)
|
60
58
|
end
|
61
59
|
end
|
60
|
+
```
|
62
61
|
|
63
|
-
|
64
|
-
|
62
|
+
And you invoke it like this:
|
63
|
+
|
64
|
+
```ruby
|
65
|
+
# run will returns a report object
|
66
|
+
report = FindUser.run(user_id: 10)
|
65
67
|
|
66
|
-
|
68
|
+
# this report object will contain the output from the Process
|
69
|
+
report.data.user
|
70
|
+
```
|
67
71
|
|
68
|
-
|
72
|
+
This and any other Process can be used to compose a workflow, so lets try that:
|
69
73
|
|
70
|
-
|
74
|
+
```ruby
|
75
|
+
class SendWelcomeEmail
|
76
|
+
include WFlow::Process
|
77
|
+
|
78
|
+
# use previously created Process to find the user
|
79
|
+
execute FindUser
|
71
80
|
|
72
|
-
def
|
73
|
-
|
81
|
+
def perform
|
82
|
+
# code to send email to user
|
74
83
|
end
|
75
84
|
end
|
76
85
|
|
77
|
-
|
78
|
-
report = UpdateAppointment.run(appointment_id: appointment_id, attributes: new_attributes)
|
79
|
-
|
80
|
-
# ask if workflow was a success
|
81
|
-
report.success?
|
86
|
+
report = SendWelcomeEmail.run(user_id: 10)
|
82
87
|
```
|
83
88
|
|
84
|
-
|
85
|
-
|
89
|
+
Processes passed to execute will be called before the perform method. You can
|
90
|
+
have as any execute as you want and as many Processes (and method nomes and Procs) in a execute.
|
91
|
+
This means that when you run SendWelcomeEmail process, it will first execute FindUser which will
|
92
|
+
set the user under flow.data, and than you can use that user to get the email address
|
93
|
+
for where to send the email.
|
94
|
+
|
95
|
+
So far so good, but lets go back to FindUser. Looking at it, we are currently not accounting for
|
96
|
+
errors cases, like what should happen when we can't find an user, or when the connection to the
|
97
|
+
database fails? This depends on what you want to do, but for this example we'll raise a flow failure,
|
98
|
+
and we'll also simplify the code a bit using data helpers:
|
86
99
|
|
87
100
|
```ruby
|
88
|
-
class
|
101
|
+
class FindUser
|
89
102
|
include WFlow::Process
|
103
|
+
|
104
|
+
# helper methods to access attributes under flow.data
|
105
|
+
data_reader :user_id
|
106
|
+
data_accessor :user
|
107
|
+
|
108
|
+
def perform
|
109
|
+
self.user = User.find(user_id)
|
110
|
+
rescue
|
111
|
+
# you can pass whatever you want to the failure! method (or even call it without arguments)
|
112
|
+
# passed value will be available in returned report under failure_log
|
113
|
+
flow.failure!('unable to find user')
|
114
|
+
end
|
115
|
+
end
|
116
|
+
|
117
|
+
report = FindUser.run(user_id: 10)
|
118
|
+
|
119
|
+
# check if success
|
120
|
+
unless report.success? # there's also a report.failure?
|
121
|
+
# failure_log is an array that contains all the objects passed to failure!
|
122
|
+
report.failure_log.each do |log|
|
123
|
+
puts log
|
124
|
+
end
|
125
|
+
end
|
90
126
|
```
|
91
127
|
|
92
|
-
|
128
|
+
Invoking failure! will interrupt a workflow immediatly. This means that if you run
|
129
|
+
SendWelcomeEmail for a non existing user it will never run the code under perform (which
|
130
|
+
is a good thing, since there's no one to send the email to). But what if we want to do
|
131
|
+
something more even in case of failure? You can pass a handler for that:
|
93
132
|
|
94
133
|
```ruby
|
95
|
-
|
96
|
-
|
134
|
+
class SendWelcomeEmail
|
135
|
+
include WFlow::Process
|
136
|
+
|
137
|
+
attr_writer :admin_email
|
138
|
+
|
139
|
+
# you can pass a name or a proc as a failure handler, which will be called if one
|
140
|
+
# of the Processes in execute chain raises a flow failure
|
141
|
+
execute FindUser, failure: :on_failure
|
142
|
+
|
143
|
+
# we'll use an if handler (there's also an unless handler), which allows us to control if a execute chain
|
144
|
+
# should be executed or not
|
145
|
+
execute :compose_email, SendMessageToAdmin, -> { flow.failure! }, if: -> { @no_user_found }
|
146
|
+
|
147
|
+
def perform
|
148
|
+
# ...
|
149
|
+
end
|
150
|
+
|
151
|
+
protected
|
97
152
|
|
98
|
-
#
|
99
|
-
|
153
|
+
# failure handler, return false to cancel failure, or true to let Process fail
|
154
|
+
def on_failure
|
155
|
+
@no_user_found = true
|
156
|
+
|
157
|
+
false
|
158
|
+
end
|
159
|
+
|
160
|
+
def compose_email
|
161
|
+
self.admin_email = "we were unable to find user :("
|
162
|
+
end
|
163
|
+
end
|
100
164
|
```
|
101
165
|
|
102
|
-
|
166
|
+
Wow it suddenly become complex, but it reflects a more realistic situation. So what's
|
167
|
+
going on? First we try to find the user, which will raise a flow failure if no user
|
168
|
+
is found. In this case we want to inform the admin that something went wrong, so instead of allowing
|
169
|
+
the flow to be interrupted right away, we return false in the failure handler to cancel failure.
|
170
|
+
After that, the second execute chain will be executed, because @no_user_found is set to true. This
|
171
|
+
execution chain will invoke the method compose_email, SendMessageToAdmin, and than
|
172
|
+
call proc that reraises failure.
|
173
|
+
|
174
|
+
This is some of the features of WFlow, please check [wiki](https://github.com/junhanamaki/w_flow/wiki) for more details.
|
103
175
|
|
104
176
|
## Contributing
|
105
177
|
|
data/lib/w_flow/configuration.rb
CHANGED
data/lib/w_flow/data.rb
CHANGED
data/lib/w_flow/node.rb
CHANGED
@@ -3,115 +3,15 @@ module WFlow
|
|
3
3
|
|
4
4
|
class << self
|
5
5
|
|
6
|
-
attr_reader :
|
7
|
-
:if_condition,
|
8
|
-
:unless_condition,
|
9
|
-
:stop_condition,
|
10
|
-
:failure_condition,
|
11
|
-
:around_handler
|
6
|
+
attr_reader :tasks, :options
|
12
7
|
|
13
|
-
def build(
|
8
|
+
def build(tasks, options)
|
14
9
|
Class.new(self) do |klass|
|
15
|
-
@
|
16
|
-
@
|
17
|
-
@unless_condition = options[:unless]
|
18
|
-
@stop_condition = options[:stop]
|
19
|
-
@failure_condition = options[:failure]
|
20
|
-
@around_handler = options[:around]
|
10
|
+
@tasks = tasks
|
11
|
+
@options = options
|
21
12
|
end
|
22
13
|
end
|
23
14
|
|
24
|
-
def execute?(process)
|
25
|
-
(if_condition.nil? || process_eval(process, if_condition)) &&
|
26
|
-
(unless_condition.nil? || !process_eval(process, unless_condition))
|
27
|
-
end
|
28
|
-
|
29
|
-
def cancel_stop?(process)
|
30
|
-
!stop_condition.nil? && !process_eval(process, stop_condition)
|
31
|
-
end
|
32
|
-
|
33
|
-
def cancel_failure?(process)
|
34
|
-
!failure_condition.nil? && !process_eval(process, failure_condition)
|
35
|
-
end
|
36
|
-
|
37
|
-
def process_eval(process, object, *args)
|
38
|
-
if object.is_a?(String) || object.is_a?(Symbol)
|
39
|
-
process.send(object.to_s, *args)
|
40
|
-
elsif object.is_a?(Proc)
|
41
|
-
process.instance_exec(*args, &object)
|
42
|
-
else
|
43
|
-
raise InvalidArguments, UNKNOWN_EXPRESSION
|
44
|
-
end
|
45
|
-
end
|
46
|
-
|
47
|
-
end
|
48
|
-
|
49
|
-
def initialize(owner_process)
|
50
|
-
@owner_process = owner_process
|
51
|
-
@components = self.class.components
|
52
|
-
@around_handler = self.class.around_handler
|
53
|
-
end
|
54
|
-
|
55
|
-
def run(flow)
|
56
|
-
@flow = flow
|
57
|
-
@execution_chains = []
|
58
|
-
|
59
|
-
if @around_handler.nil?
|
60
|
-
execute_components
|
61
|
-
else
|
62
|
-
@around_handler.call(method(:execute_components))
|
63
|
-
end
|
64
|
-
end
|
65
|
-
|
66
|
-
def finalize
|
67
|
-
@execution_chains.reverse_each do |execution_chain|
|
68
|
-
execution_chain.reverse_each(&:finalize)
|
69
|
-
end
|
70
|
-
end
|
71
|
-
|
72
|
-
def rollback
|
73
|
-
@execution_chains.reverse_each do |execution_chain|
|
74
|
-
execution_chain.reverse_each(&:rollback)
|
75
|
-
end
|
76
|
-
end
|
77
|
-
|
78
|
-
protected
|
79
|
-
|
80
|
-
def execute_components(options = {})
|
81
|
-
execution_chain = []
|
82
|
-
|
83
|
-
@components.each do |component|
|
84
|
-
report = Supervisor.supervise do
|
85
|
-
if component.is_a?(Class) && component <= Process
|
86
|
-
process_worker = ProcessWorker.new(component)
|
87
|
-
|
88
|
-
execution_chain << process_worker
|
89
|
-
|
90
|
-
process_worker.run_as_child(@flow)
|
91
|
-
else
|
92
|
-
self.class.process_eval(@owner_process, component)
|
93
|
-
end
|
94
|
-
end
|
95
|
-
|
96
|
-
if report.failed?
|
97
|
-
execution_chain.reverse_each(&:rollback)
|
98
|
-
execution_chain.reverse_each(&:finalize)
|
99
|
-
|
100
|
-
if options[:failure].nil? || options[:failure].call
|
101
|
-
@flow.log_failure(report.message)
|
102
|
-
return
|
103
|
-
else
|
104
|
-
Supervisor.resignal!(report)
|
105
|
-
end
|
106
|
-
else
|
107
|
-
if report.stopped? && (options[:stop].nil? || !options[:stop].call)
|
108
|
-
@execution_chains << execution_chain
|
109
|
-
Supervisor.resignal!(report)
|
110
|
-
end
|
111
|
-
end
|
112
|
-
end
|
113
|
-
|
114
|
-
@execution_chains << execution_chain
|
115
15
|
end
|
116
16
|
|
117
17
|
end
|
@@ -0,0 +1,91 @@
|
|
1
|
+
module WFlow
|
2
|
+
class NodeWorker
|
3
|
+
|
4
|
+
def initialize(owner_process, node_class)
|
5
|
+
@owner_process = owner_process
|
6
|
+
@tasks = node_class.tasks
|
7
|
+
|
8
|
+
options = node_class.options
|
9
|
+
|
10
|
+
@execute_if = options[:if]
|
11
|
+
@execute_unless = options[:unless]
|
12
|
+
@around_proc = options[:around]
|
13
|
+
@confirm_stop = options[:stop]
|
14
|
+
@confirm_failure = options[:failure]
|
15
|
+
end
|
16
|
+
|
17
|
+
def execute?
|
18
|
+
(@execute_if.nil? || process_eval(@execute_if)) &&
|
19
|
+
(@execute_unless.nil? || !process_eval(@execute_unless))
|
20
|
+
end
|
21
|
+
|
22
|
+
def run(flow)
|
23
|
+
@flow = flow
|
24
|
+
@executed_tasks_workers = []
|
25
|
+
|
26
|
+
report = Supervisor.supervise do
|
27
|
+
if @around_proc.nil?
|
28
|
+
execute_tasks
|
29
|
+
else
|
30
|
+
process_eval(@around_proc, method(:execute_tasks))
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
if report.failed?
|
35
|
+
rollback
|
36
|
+
finalize
|
37
|
+
|
38
|
+
@executed_tasks_workers.clear
|
39
|
+
|
40
|
+
if signal_failure?
|
41
|
+
Supervisor.resignal!(report)
|
42
|
+
else
|
43
|
+
@flow.log_failure(report.message)
|
44
|
+
end
|
45
|
+
elsif report.stopped? && signal_stop?
|
46
|
+
Supervisor.resignal!(report)
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
50
|
+
def finalize
|
51
|
+
executed_do(:finalize)
|
52
|
+
end
|
53
|
+
|
54
|
+
def rollback
|
55
|
+
executed_do(:rollback)
|
56
|
+
end
|
57
|
+
|
58
|
+
def process_eval(object, *args)
|
59
|
+
if object.is_a?(String) || object.is_a?(Symbol)
|
60
|
+
@owner_process.send(object.to_s, *args)
|
61
|
+
elsif object.is_a?(Proc)
|
62
|
+
@owner_process.instance_exec(*args, &object)
|
63
|
+
else
|
64
|
+
raise InvalidArguments, UNKNOWN_EXPRESSION
|
65
|
+
end
|
66
|
+
end
|
67
|
+
|
68
|
+
protected
|
69
|
+
|
70
|
+
def execute_tasks(options = {})
|
71
|
+
tasks_worker = TasksWorker.new(self, @tasks)
|
72
|
+
|
73
|
+
@executed_tasks_workers << tasks_worker
|
74
|
+
|
75
|
+
tasks_worker.run(@flow, options)
|
76
|
+
end
|
77
|
+
|
78
|
+
def signal_stop?
|
79
|
+
@confirm_stop.nil? || process_eval(@confirm_stop)
|
80
|
+
end
|
81
|
+
|
82
|
+
def signal_failure?
|
83
|
+
@confirm_failure.nil? || process_eval(@confirm_failure)
|
84
|
+
end
|
85
|
+
|
86
|
+
def executed_do(order)
|
87
|
+
@executed_tasks_workers.reverse_each(&order)
|
88
|
+
end
|
89
|
+
|
90
|
+
end
|
91
|
+
end
|
data/lib/w_flow/process.rb
CHANGED
@@ -46,10 +46,10 @@ module WFlow
|
|
46
46
|
end
|
47
47
|
end
|
48
48
|
|
49
|
-
def execute(*
|
50
|
-
options =
|
51
|
-
|
52
|
-
wflow_nodes << Node.build(
|
49
|
+
def execute(*tasks, &block)
|
50
|
+
options = tasks.last.is_a?(Hash) ? tasks.pop : {}
|
51
|
+
tasks << block if block_given?
|
52
|
+
wflow_nodes << Node.build(tasks, options)
|
53
53
|
end
|
54
54
|
|
55
55
|
def run(params = {})
|
@@ -1,5 +1,6 @@
|
|
1
1
|
module WFlow
|
2
2
|
class ProcessWorker
|
3
|
+
|
3
4
|
def initialize(process_class)
|
4
5
|
@process_class = process_class
|
5
6
|
end
|
@@ -28,59 +29,45 @@ module WFlow
|
|
28
29
|
end
|
29
30
|
|
30
31
|
def finalize
|
31
|
-
@
|
32
|
+
@executed_nodes.reverse_each(&:finalize)
|
32
33
|
|
33
34
|
@process.finalize if @setup_completed
|
34
35
|
end
|
35
36
|
|
36
37
|
def rollback
|
37
|
-
@
|
38
|
+
@executed_nodes.reverse_each(&:rollback)
|
38
39
|
|
39
40
|
@process.rollback if @perform_completed
|
40
41
|
end
|
41
42
|
|
42
43
|
protected
|
43
44
|
|
45
|
+
def setup(flow)
|
46
|
+
@flow = flow
|
47
|
+
@process = @process_class.new(flow)
|
48
|
+
|
49
|
+
@executed_nodes = []
|
50
|
+
@setup_completed = false
|
51
|
+
@perform_completed = false
|
52
|
+
end
|
53
|
+
|
44
54
|
def run
|
45
55
|
@process.setup
|
46
56
|
@setup_completed = true
|
47
57
|
|
48
58
|
@process_class.wflow_nodes.each do |node_class|
|
49
|
-
|
50
|
-
|
51
|
-
node = node_class.new(@process)
|
59
|
+
node_worker = NodeWorker.new(@process, node_class)
|
52
60
|
|
53
|
-
|
61
|
+
next unless node_worker.execute?
|
54
62
|
|
55
|
-
|
56
|
-
node.rollback
|
57
|
-
node.finalize
|
63
|
+
@executed_nodes << node_worker
|
58
64
|
|
59
|
-
|
60
|
-
@flow.log_failure(report.message)
|
61
|
-
else
|
62
|
-
Supervisor.resignal!(report)
|
63
|
-
end
|
64
|
-
else
|
65
|
-
@nodes << node
|
66
|
-
|
67
|
-
if report.stopped? && !node_class.cancel_stop?(@process)
|
68
|
-
Supervisor.resignal!(report)
|
69
|
-
end
|
70
|
-
end
|
65
|
+
report = node_worker.run(@flow)
|
71
66
|
end
|
72
67
|
|
73
68
|
@process.perform
|
74
69
|
@perform_completed = true
|
75
70
|
end
|
76
71
|
|
77
|
-
def setup(flow)
|
78
|
-
@flow = flow
|
79
|
-
@process = @process_class.new(flow)
|
80
|
-
@nodes = []
|
81
|
-
@setup_completed = false
|
82
|
-
@perform_completed = false
|
83
|
-
end
|
84
|
-
|
85
72
|
end
|
86
73
|
end
|
@@ -0,0 +1,70 @@
|
|
1
|
+
module WFlow
|
2
|
+
class TasksWorker
|
3
|
+
|
4
|
+
def initialize(owner_node, tasks)
|
5
|
+
@owner_node = owner_node
|
6
|
+
@tasks = tasks
|
7
|
+
end
|
8
|
+
|
9
|
+
def run(flow, options = {})
|
10
|
+
@flow = flow
|
11
|
+
@options = options
|
12
|
+
@executed_tasks = []
|
13
|
+
|
14
|
+
@tasks.each do |task|
|
15
|
+
report = Supervisor.supervise { execute_task(task) }
|
16
|
+
|
17
|
+
if report.failed?
|
18
|
+
rollback
|
19
|
+
finalize
|
20
|
+
|
21
|
+
@executed_tasks.clear
|
22
|
+
|
23
|
+
if signal_failure?
|
24
|
+
Supervisor.resignal!(report)
|
25
|
+
else
|
26
|
+
flow.log_failure(report.message)
|
27
|
+
return
|
28
|
+
end
|
29
|
+
else
|
30
|
+
Supervisor.resignal!(report) if report.stopped? && signal_stop?
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
def finalize
|
36
|
+
executed_do(:finalize)
|
37
|
+
end
|
38
|
+
|
39
|
+
def rollback
|
40
|
+
executed_do(:rollback)
|
41
|
+
end
|
42
|
+
|
43
|
+
protected
|
44
|
+
|
45
|
+
def execute_task(task)
|
46
|
+
if task.is_a?(Class) && task <= Process
|
47
|
+
process_worker = ProcessWorker.new(task)
|
48
|
+
|
49
|
+
@executed_tasks << process_worker
|
50
|
+
|
51
|
+
process_worker.run_as_child(@flow)
|
52
|
+
else
|
53
|
+
@owner_node.process_eval(task)
|
54
|
+
end
|
55
|
+
end
|
56
|
+
|
57
|
+
def signal_failure?
|
58
|
+
@options[:failure].nil? || @options[:failure].call
|
59
|
+
end
|
60
|
+
|
61
|
+
def signal_stop?
|
62
|
+
@options[:stop].nil? || @options[:stop].call
|
63
|
+
end
|
64
|
+
|
65
|
+
def executed_do(order)
|
66
|
+
@executed_tasks.reverse_each(&order)
|
67
|
+
end
|
68
|
+
|
69
|
+
end
|
70
|
+
end
|
data/lib/w_flow/version.rb
CHANGED
data/lib/w_flow.rb
CHANGED
data/w_flow.gemspec
CHANGED
@@ -9,8 +9,8 @@ Gem::Specification.new do |spec|
|
|
9
9
|
spec.authors = ["junhanamaki"]
|
10
10
|
spec.email = ["jun.hanamaki@gmail.com"]
|
11
11
|
|
12
|
-
spec.summary = %q{A workflow composer based on Single Responsability Principle
|
13
|
-
spec.description = %q{WFlow is a workflow composer that helps in
|
12
|
+
spec.summary = %q{A workflow composer based on Single Responsability Principle}
|
13
|
+
spec.description = %q{WFlow is a workflow composer that helps in code organization by splitting logic into reusable modules, more at https://github.com/junhanamaki/w_flow}
|
14
14
|
spec.homepage = "https://github.com/junhanamaki/w_flow"
|
15
15
|
|
16
16
|
spec.files = `git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) }
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: w_flow
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.12.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- junhanamaki
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date: 2015-06-
|
11
|
+
date: 2015-06-07 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: bundler
|
@@ -80,8 +80,8 @@ dependencies:
|
|
80
80
|
- - "~>"
|
81
81
|
- !ruby/object:Gem::Version
|
82
82
|
version: '0.4'
|
83
|
-
description: WFlow is a workflow composer that helps in
|
84
|
-
logic into reusable modules
|
83
|
+
description: WFlow is a workflow composer that helps in code organization by splitting
|
84
|
+
logic into reusable modules, more at https://github.com/junhanamaki/w_flow
|
85
85
|
email:
|
86
86
|
- jun.hanamaki@gmail.com
|
87
87
|
executables: []
|
@@ -100,10 +100,12 @@ files:
|
|
100
100
|
- lib/w_flow/flow.rb
|
101
101
|
- lib/w_flow/flow_report.rb
|
102
102
|
- lib/w_flow/node.rb
|
103
|
+
- lib/w_flow/node_worker.rb
|
103
104
|
- lib/w_flow/process.rb
|
104
105
|
- lib/w_flow/process_worker.rb
|
105
106
|
- lib/w_flow/supervisor.rb
|
106
107
|
- lib/w_flow/supervisor_report.rb
|
108
|
+
- lib/w_flow/tasks_worker.rb
|
107
109
|
- lib/w_flow/version.rb
|
108
110
|
- w_flow.gemspec
|
109
111
|
homepage: https://github.com/junhanamaki/w_flow
|
@@ -129,6 +131,5 @@ rubyforge_project:
|
|
129
131
|
rubygems_version: 2.4.7
|
130
132
|
signing_key:
|
131
133
|
specification_version: 4
|
132
|
-
summary: A workflow composer based on Single Responsability Principle
|
133
|
-
projects
|
134
|
+
summary: A workflow composer based on Single Responsability Principle
|
134
135
|
test_files: []
|