taskflow-mongoid 0.1.0 → 0.1.1

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: 9f6207e24297a546ecaf6ac571ef038ff85df29d
4
- data.tar.gz: 897ccc7e04641d6506b106ce269513b85498bb44
3
+ metadata.gz: 1d7fcb6e49960147821299b3fadcfa8cb29c4ea6
4
+ data.tar.gz: 3aab13db0e1dc980bc0c2d7ca759d78025f27bdf
5
5
  SHA512:
6
- metadata.gz: 62153a6ef8a35f7840b01d3fdd4cb7466c5bce59a6a7bc53763b4dc0a0f15628d07f016f88964148ca844fb62b9f67c1b1a13fec644b9d32086ddd93eeeec6a6
7
- data.tar.gz: 0910446837c77db561162c8ccbb20bc4e6c506d4ca466526caf0969163ec34a14eb65a8804619f280a8f85c05efa7933c8503021aa1b9c6b9bb11470e6ffa6f1
6
+ metadata.gz: e3265a9cd061760cb56d2e43ce5417b86043834ccb8f7850387eb483aa77d8e6d97f689eef9e616937c853db7d5109819c09885c79ebb1443db4da6fd41fc529
7
+ data.tar.gz: 9184401ef5b052ecd3761fcb2c50ce7379a1bbdcda05f3d65f141a1938c049bda11dfab4693b07bd4f589f652b174368b4fdd1b4471a362cc04678561cba4bd2
data/README.md CHANGED
@@ -1,8 +1,6 @@
1
1
  # Taskflow
2
2
 
3
- Welcome to your new gem! In this directory, you'll find the files you need to be able to package up your Ruby library into a gem. Put your Ruby code in the file `lib/taskflow`. To experiment with that code, run `bin/console` for an interactive prompt.
4
-
5
- TODO: Delete this and the text above, and describe your gem
3
+ Taskflow is a cool rails plugin for creating and schedule task flows. NOTE: taskflow is based sidekiq, and use ActiveRecord/Mongoid as its database adapter, choose the right gem(another version taskflow is also available on my github) for your project.
6
4
 
7
5
  ## Installation
8
6
 
@@ -22,7 +20,8 @@ Or install it yourself as:
22
20
 
23
21
  ## Usage
24
22
 
25
- example:
23
+ Let's see an example first, the 'PlayFlow' has 7 task in total. When we start the flow, the t1(PendingTask) runs first, after t1 finishes, t2,t3,t4 would run in parallel; When t4 is done, the t5(OkTask) begins, when t2,t3,t5 are all done, the SummaryTask start to run, then run the last OkTask.
24
+
26
25
  ```ruby
27
26
  class PlayFlow < Taskflow::Flow
28
27
  NAME = "Play FLow"
@@ -141,6 +140,134 @@ Taskflow::Worker JID-d7d0c92da5ab820bc1f66651 INFO: finished-task finished
141
140
  Taskflow::Worker JID-d7d0c92da5ab820bc1f66651 INFO: done: 0.021 sec
142
141
  ```
143
142
 
143
+
144
+ ## Documentations
145
+ ### Taskflow state diagram
146
+ flow state
147
+ ![output](https://raw.githubusercontent.com/qjpcpu/taskflow-mongoid/master/images/flow-state.png)
148
+
149
+ ### the Taskflow::Flow
150
+ First, you should create your taskflow by inherit `Taskflow::Flow`, and you *must implement the `configure` method* to tell taskflow engine the detail info.
151
+
152
+ In `configure` method, you can use the keyword `run` to define task:
153
+
154
+ ```ruby
155
+ # the keyword run
156
+ run Task_Class, name: 'task_name'
157
+ # task1 would run before another_task_obj
158
+ run Task_Class, name: 'task1',:before=>another_task_obj
159
+ # task2 would run after another_task_obj
160
+ run Task_Class, name: 'task2',:after=>another_task_obj
161
+ # the wait_task would run after task3,task4,task5 all done
162
+ run Task_Class, name: 'wait_task',:after=>[task3,task4,task5]
163
+ # pass some parameter to task, the params would set as task's input
164
+ run Task_Class, name: 'params_task',params: { :param1=>'abc' }
165
+ ```
166
+
167
+ You can use `after` or `before` to specify the schedule order for certain task, if there's no after or before, the current task would just run after the previous task.
168
+
169
+ #### 0. config taskflow
170
+ You can config taskflow worker run in which sidekiq queue(default is `default`), forexample in `config/environments/production.rb`:
171
+ ```ruby
172
+ Taskflow.configure do |config|
173
+ config.worker_options = { queue: 'workflow' }
174
+ end
175
+ ```
176
+
177
+ #### 1. launch taskflow
178
+ ```ruby
179
+ # the params would be set as taskflow's input field
180
+ Taskflow::Flow.launch 'PlayFlow',:params=>{word: 'hello'},:launched_by=>'Jason',:workflow_description=>'description'
181
+ # check whether can launch taskflow, if there's already a taskflow which has the some taskflow_klass and params, return false
182
+ Taskflow::Flow.can_launch? 'PlayFlow',:params=>{word: 'hello'},:launched_by=>'Jason',:workflow_description=>'description'
183
+ ```
184
+
185
+ #### 2. taskflow control
186
+ ```ruby
187
+ # Taskflow::Flow#stop! stop taskflow
188
+ flow.stop!
189
+ flow.stop! 'tom' # => stopped by tom
190
+ # Taskflow::Flow#resume, resume paused flow
191
+ flow.resume
192
+ ```
193
+
194
+ ### the Taskflow::Task
195
+ Define your own taskflow task. Inherit the class `Taskflow::Task`, and *implement go method*.
196
+
197
+ ```ruby
198
+ def go(logger)
199
+ # write your task code here
200
+ end
201
+ ```
202
+
203
+ #### 1.Sidekiq logger
204
+ the parameter `logger` of `Taskflow::Task#go` is sidekiq logger, so you can use it to log to sidekiq log file for debug.
205
+
206
+ #### 2.taskflow logger
207
+ There's another logger in `Taskflow::Task#go` : `tflogger`, `tflogger` can write log information to database. for example:
208
+
209
+ ```ruby
210
+ def go(logger)
211
+ tflogger.info 'the info message would write to database'
212
+ tflogger.error 'this error message would write to database,too'
213
+ end
214
+ ```
215
+
216
+ #### 3. input & output
217
+ There's a very cool feature. Every task has its own `input` and `ouput`.
218
+ ```ruby
219
+ def go(logger)
220
+ puts input # => the input hash
221
+ puts input[:some_key] # => get the input value of the key 'some_key'
222
+ puts upstream.first.ouput # => get the first upstream's ouput, also is a hash
223
+ end
224
+ ```
225
+
226
+ You have the `set/append_xxx` to modify the input and output.
227
+ ```ruby
228
+ def go(log)
229
+ set_output :some_key=>'value' # => set the output to { :some_key=> 'value'}
230
+ append_output :some_key2=>'value2' # => add { :some_key2=>'value2' } to output
231
+ end
232
+ ```
233
+
234
+ #### 4. data
235
+ Every task has its own data. After the task is done, the data would be cleanned.
236
+ ```ruby
237
+ def go(log)
238
+ puts data # => print data
239
+ puts data[:key] # => access data
240
+ set_data :key=>'value'
241
+ append_data :key=>'value'
242
+ end
243
+ ```
244
+
245
+ #### 5. relationship
246
+ In the task, you can access its upstream and downstream.
247
+ ```ruby
248
+ def go(log)
249
+ upstream.each{|task| puts task.name }
250
+ upstream.each{|task| puts task.output }
251
+ puts downstream.first.name
252
+ end
253
+ ```
254
+
255
+ #### 6. task control
256
+ ```ruby
257
+ task.resume # => resume paused task
258
+ task.wakeup(hash_data) # => wakeup suspend task with some hash data
259
+ task.wakeup # => just wakeup
260
+ task.skip # => skip paused task
261
+ ```
262
+ And, in `Taskflow::Task#go`, you can use keyword `suspend` to suspend current task, then the task result would convert to `suspend`,state would be `paused`.
263
+ ```ruby
264
+ def go(log)
265
+ log.info 'before suspend'
266
+ suspend # => the task would be suspend right now.
267
+ log.info 'never print me'
268
+ end
269
+ ```
270
+
144
271
  ## Development
145
272
 
146
273
  After checking out the repo, run `bin/setup` to install dependencies. You can also run `bin/console` for an interactive prompt that will allow you to experiment.
Binary file
@@ -1,3 +1,3 @@
1
1
  module Taskflow
2
- VERSION = "0.1.0"
2
+ VERSION = "0.1.1"
3
3
  end
@@ -1,7 +1,6 @@
1
1
  # coding: utf-8
2
2
  class Taskflow::Worker
3
3
  include ::Sidekiq::Worker
4
- sidekiq_options :retry => false
5
4
 
6
5
  def perform(task_flow_id,job_id,opts={})
7
6
  flow = Taskflow::Flow.find task_flow_id
@@ -28,63 +27,63 @@ class Taskflow::Worker
28
27
  rescue=>exception
29
28
  task.error = {
30
29
  class: exception.class.to_s,
31
- message: exception.to_s,
32
- backtrace: exception.backtrace
33
- }
34
- task.state = 'paused'
35
- task.result = 'error'
36
- task.ended_at = Time.now
37
- task.save
38
- end
39
- update_flow flow.reload
40
- flow.schedule
41
- end
30
+ message: exception.to_s,
31
+ backtrace: exception.backtrace
32
+ }
33
+ task.state = 'paused'
34
+ task.result = 'error'
35
+ task.ended_at = Time.now
36
+ task.save
37
+ end
38
+ update_flow flow.reload
39
+ flow.schedule
40
+ end
42
41
 
43
- private
44
- def check_flow_state(flow)
45
- if flow.state == 'stopped' || flow.halt_by
46
- throw :control, :flow_halt
47
- end
48
- end
49
- def check_task_state(task)
50
- case task.state
51
- when 'pending'
52
- task.update_attributes state: 'running'
53
- when 'running'
54
- throw :control, :already_running
55
- when 'paused'
56
- throw :control, :suspend if task.result == 'suspend'
57
- when 'stopped'
58
- throw :control, :already_stopped
59
- when 'skipped'
60
- throw :control,:skip
61
- else
62
- raise "Unkown task state #{task.state}"
63
- end
64
- end
42
+ private
43
+ def check_flow_state(flow)
44
+ if flow.state == 'stopped' || flow.halt_by
45
+ throw :control, :flow_halt
46
+ end
47
+ end
48
+ def check_task_state(task)
49
+ case task.state
50
+ when 'pending'
51
+ task.update_attributes state: 'running'
52
+ when 'running'
53
+ throw :control, :already_running
54
+ when 'paused'
55
+ throw :control, :suspend if task.result == 'suspend'
56
+ when 'stopped'
57
+ throw :control, :already_stopped
58
+ when 'skipped'
59
+ throw :control,:skip
60
+ else
61
+ raise "Unkown task state #{task.state}"
62
+ end
63
+ end
65
64
 
66
- def update_flow(flow)
67
- return if flow.halt_by || flow.state == 'stopped'
68
- flow.progress = flow.tasks.map(&:progress).sum / flow.tasks.size
69
- if flow.halt_by
70
- flow.state = 'stopped'
71
- elsif flow.tasks.all?{|t| %w(stopped skipped).include? t.state }
72
- flow.state = 'stopped'
73
- elsif flow.tasks.any?{|t| t.state == 'paused' }
74
- flow.state = 'paused'
75
- flow.result = flow.tasks.find_by(state: 'paused').result
76
- else
77
- flow.state = 'running'
78
- end
79
- if flow.state == 'stopped'
80
- flow.result = flow.tasks.all?{|t| t.result == 'success' } ? 'success' : 'warning'
81
- flow.ended_at = Time.now
82
- if flow.next_config
83
- logger.info "Auto boot next flow, #{flow.next_config}"
84
- Taskflow::Flow.launch flow.next_config[:name],flow.next_config[:config]
85
- end
86
- end
87
- flow.save
88
- end
65
+ def update_flow(flow)
66
+ return if flow.halt_by || flow.state == 'stopped'
67
+ flow.progress = flow.tasks.map(&:progress).sum / flow.tasks.size
68
+ if flow.halt_by
69
+ flow.state = 'stopped'
70
+ elsif flow.tasks.all?{|t| %w(stopped skipped).include? t.state }
71
+ flow.state = 'stopped'
72
+ elsif flow.tasks.any?{|t| t.state == 'paused' }
73
+ flow.state = 'paused'
74
+ flow.result = flow.tasks.find_by(state: 'paused').result
75
+ else
76
+ flow.state = 'running'
77
+ end
78
+ if flow.state == 'stopped'
79
+ flow.result = flow.tasks.all?{|t| t.result == 'success' } ? 'success' : 'warning'
80
+ flow.ended_at = Time.now
81
+ if flow.next_config
82
+ logger.info "Auto boot next flow, #{flow.next_config}"
83
+ Taskflow::Flow.launch flow.next_config[:name],flow.next_config[:config]
84
+ end
85
+ end
86
+ flow.save
87
+ end
89
88
 
90
- end
89
+ end
data/lib/taskflow.rb CHANGED
@@ -7,5 +7,14 @@ require 'taskflow/logger'
7
7
  require 'taskflow/record'
8
8
 
9
9
  module Taskflow
10
- # Your code goes here...
10
+
11
+ def self.worker_options=(opts)
12
+ orig = HashWithIndifferentAccess.new(Worker.sidekiq_options_hash || {})
13
+ Worker.sidekiq_options_hash = orig.merge(opts).merge(retry: false)
14
+ end
15
+
16
+ def self.configure
17
+ yield self
18
+ end
11
19
  end
20
+
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: taskflow-mongoid
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.0
4
+ version: 0.1.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - qujianping
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2015-07-05 00:00:00.000000000 Z
11
+ date: 2015-07-10 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler
@@ -81,6 +81,7 @@ files:
81
81
  - Rakefile
82
82
  - bin/console
83
83
  - bin/setup
84
+ - images/flow-state.png
84
85
  - lib/taskflow.rb
85
86
  - lib/taskflow/flow.rb
86
87
  - lib/taskflow/logger.rb