taskflow-mongoid 0.1.0 → 0.1.1

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.
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