level_up 0.1.0 → 0.2.0
Sign up to get free protection for your applications and to get access to all the features.
- data/CHANGELOG.txt +7 -0
- data/README.md +29 -29
- data/app/controllers/level_up/jobs_controller.rb +15 -16
- data/app/helpers/level_up/home_helper.rb +5 -1
- data/app/models/level_up/job.rb +65 -55
- data/app/models/level_up/{state → task}/cancel.rb +1 -1
- data/app/models/level_up/{state → task}/end.rb +1 -1
- data/app/models/level_up/task/start.rb +8 -0
- data/app/models/level_up/{state.rb → task.rb} +13 -13
- data/app/views/level_up/home/index.html.erb +4 -4
- data/app/views/level_up/jobs/edit.html.erb +4 -4
- data/app/views/level_up/jobs/index.html.erb +7 -7
- data/app/views/level_up/jobs/show.html.erb +6 -6
- data/db/migrate/20130212111454_create_level_up_jobs.rb +4 -4
- data/lib/level_up/configuration.rb +14 -2
- data/lib/level_up/version.rb +1 -1
- data/test/dummy/app/models/account_banish.rb +18 -0
- data/test/dummy/app/models/account_downgrade.rb +13 -0
- data/test/dummy/app/{jobs → models}/account_upgrade.rb +3 -3
- data/test/dummy/db/development.sqlite3 +0 -0
- data/test/dummy/db/migrate/{20130212113009_create_delayed_jobs.rb → 20130404201224_create_delayed_jobs.rb} +0 -0
- data/test/dummy/db/migrate/{20130215111404_create_level_up_jobs.level_up.rb → 20130404201329_create_level_up_jobs.level_up.rb} +4 -4
- data/test/dummy/db/schema.rb +9 -9
- data/test/dummy/db/test.sqlite3 +0 -0
- data/test/dummy/log/development.log +4020 -0
- data/test/dummy/log/test.log +21327 -0
- data/test/dummy/tmp/cache/assets/C2C/CE0/sprockets%2F33f519d653c9b4886c417440a0993824 +0 -0
- data/test/dummy/tmp/cache/assets/C6A/F00/sprockets%2F177385361781d5fe78d217f1f48b8566 +0 -0
- data/test/dummy/tmp/cache/assets/C6C/ED0/sprockets%2F320c25374f5ea136824c04c256e1605b +0 -0
- data/test/dummy/tmp/cache/assets/C87/110/sprockets%2Fc4428c04b8830f451f7636c2811f975d +0 -0
- data/test/dummy/tmp/cache/assets/CB9/E40/sprockets%2F43e6286ecc7751fc65d32b72c6158940 +0 -0
- data/test/dummy/tmp/cache/assets/CCE/7E0/sprockets%2F7d295633b50bfa8b04345d5e600b343a +0 -0
- data/test/dummy/tmp/cache/assets/CD5/450/sprockets%2F2ac0e7e07211a99107e0ba7e2680c885 +0 -0
- data/test/dummy/tmp/cache/assets/CE4/220/sprockets%2Ff1a78dd6750c553265fd3a242d76c277 +0 -0
- data/test/dummy/tmp/cache/assets/CF7/BA0/sprockets%2F8f9487ea6943415e46a5d895e0920ebe +0 -0
- data/test/dummy/tmp/cache/assets/D0E/2B0/sprockets%2F3e386ff8d231b92766061c4fad4ad504 +0 -0
- data/test/dummy/tmp/cache/assets/D19/660/sprockets%2F018d64588c824dd3e7e6c8d6d0d6510e +0 -0
- data/test/dummy/tmp/cache/assets/D25/E10/sprockets%2F989ec024c5db6ae875689b410f8e6d53 +0 -0
- data/test/dummy/tmp/cache/assets/D33/200/sprockets%2Fc291105cf21ca8e744c65f3d4f446aa1 +0 -0
- data/test/dummy/tmp/cache/assets/D34/610/sprockets%2Fcc081ecb5b32894151f16a144383befe +0 -0
- data/test/dummy/tmp/cache/assets/D4D/110/sprockets%2Fc16dfb491d9b98f482b4f0059dd355b8 +0 -0
- data/test/dummy/tmp/cache/assets/D4F/890/sprockets%2Fe3f96e9aa9b032c43788676c5ce066db +0 -0
- data/test/dummy/tmp/cache/assets/D53/370/sprockets%2F1cf0ca91840a1483edcac4d0c403b149 +0 -0
- data/test/dummy/tmp/cache/assets/D69/B90/sprockets%2Fdb0ee3e51128419c85616ceaca66ab58 +0 -0
- data/test/dummy/tmp/cache/assets/D75/B20/sprockets%2Fb659146edbe91be3b1b9d64cb9370c76 +0 -0
- data/test/dummy/tmp/cache/assets/D79/430/sprockets%2Fc030f9d26fab468c49dc494195d77eab +0 -0
- data/test/dummy/tmp/cache/assets/D9D/3C0/sprockets%2F3019d99c7bae1e55eb7c2bf4688b1b1a +0 -0
- data/test/dummy/tmp/cache/assets/DAA/1A0/sprockets%2Fba643993838fce8ddc1d42e6ce1fc346 +0 -0
- data/test/dummy/tmp/cache/assets/DD4/DA0/sprockets%2F17fadf3354a429c53acfe9fca6268d5d +0 -0
- data/test/dummy/tmp/cache/assets/DF8/880/sprockets%2F255d8bde2bf6681724e4ddedcc3cbc02 +0 -0
- data/test/dummy/tmp/job_1.svg +78 -0
- data/test/dummy/tmp/job_2.svg +78 -0
- data/test/dummy/tmp/job_3.svg +78 -0
- data/test/unit/level_up/job_test.rb +124 -52
- metadata +84 -19
- data/app/models/level_up/state/start.rb +0 -9
- data/app/views/level_up/home/workflow.html.erb +0 -5
- data/test/dummy/app/jobs/account_banish.rb +0 -18
- data/test/dummy/app/jobs/account_downgrade.rb +0 -13
- data/test/dummy/app/jobs/mailing_list_subscription.rb +0 -15
data/CHANGELOG.txt
CHANGED
@@ -1,2 +1,9 @@
|
|
1
|
+
== 0.2.0 Hungry Beast
|
2
|
+
* Configurable size of saved backtrace when rescuing from an error
|
3
|
+
* Renamed 'states' into 'tasks'
|
4
|
+
* Renamed 'move_to', 'retry_in' and 'manual_task' methods into 'move_to!', 'retry_in!' and 'manual_task'
|
5
|
+
* New 'class_name' option to allow overriding a task class when declaring it
|
6
|
+
* Bug fixes and improvements
|
7
|
+
|
1
8
|
== 0.1.0 Apprentice Warrior
|
2
9
|
* First release
|
data/README.md
CHANGED
@@ -5,17 +5,17 @@
|
|
5
5
|
## What ?
|
6
6
|
|
7
7
|
If you are building a web app, chances are good you have some jobs to design and execute in order to provide services to your customers.
|
8
|
-
Generally, that means handling
|
9
|
-
LevelUp lets you build all of these and compose them to create a runnable job. Concretely, you will define a
|
10
|
-
|
11
|
-
|
8
|
+
Generally, that means handling computer-based or manual tasks, calls to external services, failures, timers and retries.
|
9
|
+
LevelUp lets you build all of these and compose them to create a runnable job. Concretely, you will define a task graph, where each task contains
|
10
|
+
its own business logic implemented in ruby. Jobs can be performed synchronously in the current thread or asynchronously by background workers.
|
11
|
+
Three methods are available in each state to control the job flow: move_to!(task_name), retry_in!(delay), manual_task!(task_description).
|
12
12
|
|
13
13
|
## Why use LevelUp ?
|
14
14
|
|
15
|
-
Designing your jobs graphically with
|
15
|
+
Designing your jobs graphically with tasks and transitions can be more easier than directly writing code, especially for non-technical people.
|
16
16
|
Graphs can be drawn, printed, shared and analysed making it easier to let everyone know what the system is doing at specific points in time.
|
17
|
-
From a developers point of view, it’s clearer to separate the different parts of a job into isolated states. Class
|
18
|
-
in multiple jobs to avoid code duplication. For example, you can use the Template design pattern to implement the generic part of a
|
17
|
+
From a developers point of view, it’s clearer to separate the different parts of a job into isolated states. Class-based tasks are reusable
|
18
|
+
in multiple jobs to avoid code duplication. For example, you can use the Template design pattern to implement the generic part of a task
|
19
19
|
in a parent class and implement specialized parts in children classes.
|
20
20
|
|
21
21
|
## Requirements
|
@@ -71,13 +71,13 @@ config.level_up.http_password = "your-password"
|
|
71
71
|
## Writing Job Models
|
72
72
|
|
73
73
|
```ruby
|
74
|
-
# app/
|
74
|
+
# app/models/hard_job.rb
|
75
75
|
class HardJob < LevelUp::Job
|
76
|
-
#
|
76
|
+
# tasks and transitions
|
77
77
|
job do
|
78
|
-
|
79
|
-
|
80
|
-
|
78
|
+
task :start, transitions: :first_task
|
79
|
+
task :first_task, transitions: :second_task
|
80
|
+
task :second_task, transitions: :end
|
81
81
|
end
|
82
82
|
|
83
83
|
def first_task
|
@@ -90,14 +90,14 @@ class HardJob < LevelUp::Job
|
|
90
90
|
end
|
91
91
|
```
|
92
92
|
|
93
|
-
###
|
93
|
+
### Task classes
|
94
94
|
|
95
|
-
You can also define
|
95
|
+
You can also define task logic in a class instead of a method.
|
96
96
|
|
97
97
|
```ruby
|
98
|
-
app/
|
98
|
+
app/models/hard_job/first_task.rb
|
99
99
|
module HardJob
|
100
|
-
class FirstTask < LevelUp::
|
100
|
+
class FirstTask < LevelUp::Task
|
101
101
|
def run
|
102
102
|
# logic goes here
|
103
103
|
end
|
@@ -106,9 +106,9 @@ end
|
|
106
106
|
```
|
107
107
|
|
108
108
|
```ruby
|
109
|
-
app/
|
109
|
+
app/models/hard_job/second_task.rb
|
110
110
|
module HardJob
|
111
|
-
class SecondTask < LevelUp::
|
111
|
+
class SecondTask < LevelUp::Task
|
112
112
|
def run
|
113
113
|
# logic goes here
|
114
114
|
end
|
@@ -118,35 +118,35 @@ end
|
|
118
118
|
|
119
119
|
### Flow control
|
120
120
|
|
121
|
-
Inside a
|
121
|
+
Inside a task, you can call 3 methods to control the job flow:
|
122
122
|
|
123
|
-
#### move_to(
|
123
|
+
#### move_to!(task_name)
|
124
124
|
|
125
|
-
Leave the current
|
125
|
+
Leave the current task and run the specified one.
|
126
126
|
```ruby
|
127
127
|
# example:
|
128
|
-
move_to :second_task
|
128
|
+
move_to! :second_task
|
129
129
|
```
|
130
130
|
|
131
|
-
#### retry_in(delay)
|
131
|
+
#### retry_in!(delay)
|
132
132
|
|
133
|
-
Stop the execution and
|
133
|
+
Stop the execution and enqueue a new delayed_job to re-run the current task after the specified delay in seconds.
|
134
134
|
|
135
135
|
```ruby
|
136
136
|
# example:
|
137
|
-
retry_in 1.hour
|
137
|
+
retry_in! 1.hour
|
138
138
|
```
|
139
139
|
|
140
|
-
####
|
141
|
-
Stop the execution and set the
|
140
|
+
#### manual_task!(description)
|
141
|
+
Stop the execution and set the manual_task and manual_task_description attributes to notify that some work need to be done manually.
|
142
142
|
|
143
143
|
```ruby
|
144
144
|
# example:
|
145
|
-
|
145
|
+
manual_task! "check payment information"
|
146
146
|
```
|
147
147
|
|
148
148
|
You can also raise a StandardError (or a subclass) to stop the execution and set the error attribute.
|
149
|
-
The time, the
|
149
|
+
The time, the task and the error backtrace will be saved.
|
150
150
|
|
151
151
|
## Running Jobs
|
152
152
|
In your code:
|
@@ -68,10 +68,10 @@ module LevelUp
|
|
68
68
|
|
69
69
|
def move
|
70
70
|
job = Job.find params[:id]
|
71
|
-
if job.boot_async!(params[:
|
72
|
-
redirect_to job_path(
|
71
|
+
if job.boot_async!(params[:task])
|
72
|
+
redirect_to job_path(job), notice: "Moved to #{params[:task]}!"
|
73
73
|
else
|
74
|
-
flash[:error] = "Error while moving to #{params[:
|
74
|
+
flash[:error] = "Error while moving to #{params[:task]}"
|
75
75
|
redirect_to job_path(job)
|
76
76
|
end
|
77
77
|
end
|
@@ -91,22 +91,21 @@ module LevelUp
|
|
91
91
|
g.edge[:color] = '#000000'
|
92
92
|
g.edge[:arrowhead] = 'open'
|
93
93
|
|
94
|
-
|
95
|
-
job.
|
96
|
-
|
97
|
-
if
|
98
|
-
|
99
|
-
|
100
|
-
|
101
|
-
|
102
|
-
|
103
|
-
states[state][:color] = '#600615'
|
94
|
+
tasks = {}
|
95
|
+
job.tasks.each do |task|
|
96
|
+
tasks[task] = g.add_nodes(task.to_s.humanize.downcase)
|
97
|
+
if task == :start
|
98
|
+
tasks[task][:fillcolor] = '#5db1a4'
|
99
|
+
tasks[task][:color] = '#048282'
|
100
|
+
elsif task == :end
|
101
|
+
tasks[task][:fillcolor] = '#b40d28'
|
102
|
+
tasks[task][:color] = '#600615'
|
104
103
|
end
|
105
104
|
end
|
106
105
|
|
107
|
-
job.
|
108
|
-
job.transitions(
|
109
|
-
g.add_edges(
|
106
|
+
job.tasks.each do |task|
|
107
|
+
job.transitions(task).each do |transition|
|
108
|
+
g.add_edges(tasks[task], tasks[transition])
|
110
109
|
end
|
111
110
|
end
|
112
111
|
|
@@ -1,7 +1,11 @@
|
|
1
1
|
module LevelUp
|
2
2
|
module HomeHelper
|
3
3
|
def job_entry(job)
|
4
|
-
|
4
|
+
if job
|
5
|
+
link_to "#{job.key} @ #{I18n.l(job.created_at, format: :long)}", job_path(job)
|
6
|
+
else
|
7
|
+
'-'
|
8
|
+
end
|
5
9
|
end
|
6
10
|
end
|
7
11
|
end
|
data/app/models/level_up/job.rb
CHANGED
@@ -1,17 +1,19 @@
|
|
1
1
|
module LevelUp
|
2
|
-
class
|
2
|
+
class TaskNotFound < StandardError; end
|
3
3
|
|
4
4
|
class Job < ActiveRecord::Base
|
5
5
|
|
6
|
-
attr_accessible :key, :
|
7
|
-
|
6
|
+
attr_accessible :key, :task, :timer, :manual_task, :manual_task_description, :error,
|
7
|
+
:created_at, :updated_at, :started_at, :ended_at, :canceled_at
|
8
8
|
|
9
|
-
|
9
|
+
belongs_to :delayed_job, class_name: '::Delayed::Job'
|
10
10
|
|
11
|
-
|
11
|
+
attr_accessor :next_task
|
12
|
+
|
13
|
+
scope :queued, lambda { where('delayed_job_id is not null') }
|
12
14
|
scope :error, lambda { where(error: true) }
|
13
15
|
scope :timer, lambda { where(timer: true) }
|
14
|
-
scope :
|
16
|
+
scope :manual_task, lambda { where(manual_task: true) }
|
15
17
|
|
16
18
|
serialize :backtrace
|
17
19
|
|
@@ -20,7 +22,11 @@ module LevelUp
|
|
20
22
|
@schema ||= {}
|
21
23
|
end
|
22
24
|
|
23
|
-
def
|
25
|
+
def task_classes
|
26
|
+
@task_classes ||= {}
|
27
|
+
end
|
28
|
+
|
29
|
+
def tasks
|
24
30
|
self.schema.keys
|
25
31
|
end
|
26
32
|
|
@@ -31,17 +37,18 @@ module LevelUp
|
|
31
37
|
end
|
32
38
|
end
|
33
39
|
|
34
|
-
def
|
35
|
-
options.reverse_merge!({
|
36
|
-
transitions = options[:
|
40
|
+
def task(name, options = {})
|
41
|
+
options.reverse_merge!({transitions: []})
|
42
|
+
transitions = options[:transitions].kind_of?(Symbol) ? Array(options[:transitions]) : options[:transitions]
|
37
43
|
schema[name] = transitions
|
44
|
+
task_classes[name] = options[:class_name] if options.key?(:class_name)
|
38
45
|
end
|
39
46
|
|
40
|
-
def transitions(
|
41
|
-
if self.schema.has_key?(
|
42
|
-
self.schema[
|
47
|
+
def transitions(task_name)
|
48
|
+
if self.schema.has_key?(task_name)
|
49
|
+
self.schema[task_name]
|
43
50
|
else
|
44
|
-
raise
|
51
|
+
raise TaskNotFound, task_name
|
45
52
|
end
|
46
53
|
end
|
47
54
|
end
|
@@ -55,8 +62,8 @@ module LevelUp
|
|
55
62
|
clear!(event_name)
|
56
63
|
step!(event_name, allow_transition, allow_retry)
|
57
64
|
|
58
|
-
if
|
59
|
-
event!(
|
65
|
+
if next_task
|
66
|
+
event!(next_task, allow_transition, allow_retry)
|
60
67
|
elsif retry_at
|
61
68
|
retry!
|
62
69
|
end
|
@@ -67,15 +74,15 @@ module LevelUp
|
|
67
74
|
clear_error_attributes
|
68
75
|
clear_task_attributes
|
69
76
|
|
70
|
-
self.
|
77
|
+
self.next_task = nil
|
71
78
|
self.retry_at = nil
|
72
|
-
self.
|
79
|
+
self.task = event_name if event_name
|
73
80
|
save
|
74
81
|
end
|
75
82
|
|
76
83
|
def step!(event_name, allow_transition, allow_retry)
|
77
84
|
begin
|
78
|
-
|
85
|
+
run_task(event_name, allow_transition, allow_retry)
|
79
86
|
rescue => ex
|
80
87
|
set_error(ex)
|
81
88
|
ensure
|
@@ -89,7 +96,7 @@ module LevelUp
|
|
89
96
|
boot_async!(nil, run_at: retry_at)
|
90
97
|
end
|
91
98
|
|
92
|
-
def boot_async!(event_name
|
99
|
+
def boot_async!(event_name=nil, options={})
|
93
100
|
begin
|
94
101
|
Delayed::Job.transaction do
|
95
102
|
self.delayed_job = delay(options).event!(event_name)
|
@@ -110,8 +117,8 @@ module LevelUp
|
|
110
117
|
save
|
111
118
|
end
|
112
119
|
|
113
|
-
def
|
114
|
-
self.
|
120
|
+
def task?(name)
|
121
|
+
self.task == name.to_s
|
115
122
|
end
|
116
123
|
|
117
124
|
def cancellable?
|
@@ -122,59 +129,60 @@ module LevelUp
|
|
122
129
|
!self.delayed_job.nil?
|
123
130
|
end
|
124
131
|
|
125
|
-
def
|
126
|
-
self.class.
|
132
|
+
def tasks
|
133
|
+
self.class.tasks
|
127
134
|
end
|
128
135
|
|
129
|
-
def transitions(
|
130
|
-
self.class.transitions(
|
136
|
+
def transitions(task_name)
|
137
|
+
self.class.transitions(task_name)
|
131
138
|
end
|
132
139
|
|
133
|
-
def
|
134
|
-
self.transitions(self.
|
140
|
+
def task_transitions
|
141
|
+
self.transitions(self.task.to_sym)
|
135
142
|
end
|
136
143
|
|
137
144
|
def schema
|
138
145
|
self.class.schema
|
139
146
|
end
|
140
147
|
|
141
|
-
def move_to(
|
142
|
-
throw :move_to,
|
148
|
+
def move_to!(task_name)
|
149
|
+
throw :move_to, task_name
|
143
150
|
end
|
144
151
|
|
145
|
-
def retry_in(delay, error=nil)
|
152
|
+
def retry_in!(delay, error=nil)
|
146
153
|
throw :retry_in, delay: delay, error: error
|
147
154
|
end
|
148
155
|
|
149
|
-
def manual_task(description)
|
150
|
-
throw :
|
156
|
+
def manual_task!(description)
|
157
|
+
throw :manual_task, description
|
151
158
|
end
|
152
159
|
|
153
160
|
protected
|
154
|
-
def
|
155
|
-
|
156
|
-
|
161
|
+
def run_task(task_name, allow_transition, allow_retry)
|
162
|
+
task_name ||= self.task
|
163
|
+
|
164
|
+
if respond_to?(task_name)
|
165
|
+
Task.new(self, allow_transition, allow_retry).execute(self, task_name)
|
157
166
|
else
|
158
|
-
|
159
|
-
|
160
|
-
elsif
|
161
|
-
|
162
|
-
elsif
|
163
|
-
|
167
|
+
task_class = if self.class.task_classes.key?(task_name.to_sym)
|
168
|
+
self.class.task_classes[task_name.to_sym].constantize
|
169
|
+
elsif task?(:start)
|
170
|
+
Task::Start
|
171
|
+
elsif task?(:end)
|
172
|
+
Task::End
|
173
|
+
elsif task?(:cancel)
|
174
|
+
Task::Cancel
|
164
175
|
else
|
165
|
-
|
176
|
+
next_task_class(task_name)
|
166
177
|
end
|
167
|
-
state = state_class.new(self, allow_transition, allow_retry)
|
168
|
-
state.execute(state, :run)
|
169
|
-
end
|
170
|
-
end
|
171
178
|
|
172
|
-
|
173
|
-
|
179
|
+
task_instance = task_class.new(self, allow_transition, allow_retry)
|
180
|
+
task_instance.execute(task_instance, :run)
|
181
|
+
end
|
174
182
|
end
|
175
183
|
|
176
|
-
def
|
177
|
-
"#{self.class.name}::#{
|
184
|
+
def next_task_class(task_name)
|
185
|
+
"#{self.class.name}::#{task_name.camelize}".constantize
|
178
186
|
end
|
179
187
|
|
180
188
|
def set_error(error=nil)
|
@@ -189,8 +197,10 @@ module LevelUp
|
|
189
197
|
|
190
198
|
def set_error_details(error)
|
191
199
|
self.failed_at = DateTime.now.utc
|
192
|
-
self.failed_in =
|
193
|
-
|
200
|
+
self.failed_in = self.task
|
201
|
+
if Configuration.backtrace_size > 0
|
202
|
+
self.backtrace = [error.message] | error.backtrace.take(Configuration.backtrace_size - 1)
|
203
|
+
end
|
194
204
|
end
|
195
205
|
|
196
206
|
def clear_error_attributes
|
@@ -205,8 +215,8 @@ module LevelUp
|
|
205
215
|
end
|
206
216
|
|
207
217
|
def clear_task_attributes
|
208
|
-
self.
|
209
|
-
self.
|
218
|
+
self.manual_task = false
|
219
|
+
self.manual_task_description = nil
|
210
220
|
end
|
211
221
|
end
|
212
222
|
end
|
@@ -1,5 +1,5 @@
|
|
1
1
|
module LevelUp
|
2
|
-
class
|
2
|
+
class Task
|
3
3
|
|
4
4
|
attr_accessor :job, :allow_transition, :allow_retry
|
5
5
|
|
@@ -10,11 +10,11 @@ module LevelUp
|
|
10
10
|
end
|
11
11
|
|
12
12
|
def execute(receiver, method_name)
|
13
|
-
|
13
|
+
task_name = retry_params = task_description = nil
|
14
14
|
ActiveRecord::Base.transaction do
|
15
|
-
|
15
|
+
task_name = catch(:move_to) do
|
16
16
|
retry_params = catch(:retry_in) do
|
17
|
-
task_description = catch(:
|
17
|
+
task_description = catch(:manual_task) do
|
18
18
|
receiver.send(method_name)
|
19
19
|
nil
|
20
20
|
end
|
@@ -25,7 +25,7 @@ module LevelUp
|
|
25
25
|
end
|
26
26
|
|
27
27
|
if self.allow_transition
|
28
|
-
self.job.
|
28
|
+
self.job.next_task = task_name
|
29
29
|
end
|
30
30
|
|
31
31
|
if retry_params and self.allow_retry
|
@@ -33,21 +33,21 @@ module LevelUp
|
|
33
33
|
end
|
34
34
|
|
35
35
|
if task_description
|
36
|
-
self.job.
|
37
|
-
self.job.
|
36
|
+
self.job.manual_task = true
|
37
|
+
self.job.manual_task_description = task_description
|
38
38
|
end
|
39
39
|
end
|
40
40
|
|
41
|
-
def move_to(
|
42
|
-
self.job.move_to(
|
41
|
+
def move_to!(task_name)
|
42
|
+
self.job.move_to!(task_name)
|
43
43
|
end
|
44
44
|
|
45
|
-
def retry_in(delay, error=nil)
|
46
|
-
self.job.retry_in(delay, error)
|
45
|
+
def retry_in!(delay, error=nil)
|
46
|
+
self.job.retry_in!(delay, error)
|
47
47
|
end
|
48
48
|
|
49
|
-
def manual_task(description)
|
50
|
-
self.job.manual_task(description)
|
49
|
+
def manual_task!(description)
|
50
|
+
self.job.manual_task!(description)
|
51
51
|
end
|
52
52
|
end
|
53
53
|
end
|
@@ -27,12 +27,12 @@
|
|
27
27
|
|
28
28
|
<div class="grid-6">
|
29
29
|
<div class="job-status-stats task">
|
30
|
-
<div class="title"><h2><span class="bullet"></span>Task</h2></div>
|
31
|
-
<div class="number"><%= link_to LevelUp::Job.
|
30
|
+
<div class="title"><h2><span class="bullet"></span>Manual Task</h2></div>
|
31
|
+
<div class="number"><%= link_to LevelUp::Job.manual_task.size, jobs_path(search: {manual_task_eq: true}) %></div>
|
32
32
|
<div class="stats">
|
33
33
|
<ul>
|
34
|
-
<li><label>Most recent:</label><%= job_entry(LevelUp::Job.
|
35
|
-
<li><label>Oldest:</label><%= job_entry(LevelUp::Job.
|
34
|
+
<li><label>Most recent:</label><%= job_entry(LevelUp::Job.manual_task.first) %></li>
|
35
|
+
<li><label>Oldest:</label><%= job_entry(LevelUp::Job.manual_task.last) %></li>
|
36
36
|
</ul>
|
37
37
|
</div>
|
38
38
|
</div>
|
@@ -20,16 +20,16 @@
|
|
20
20
|
<%= f.text_field :key %>
|
21
21
|
</li>
|
22
22
|
<li>
|
23
|
-
<%= f.label :
|
24
|
-
<%= f.select :
|
23
|
+
<%= f.label :task %>
|
24
|
+
<%= f.select :task, options_for_select(@job.tasks, @job.task) %>
|
25
25
|
</li>
|
26
26
|
<li>
|
27
27
|
<%= f.label :timer %>
|
28
28
|
<%= f.check_box :timer %>
|
29
29
|
</li>
|
30
30
|
<li>
|
31
|
-
<%= f.label :
|
32
|
-
<%= f.check_box :
|
31
|
+
<%= f.label :manual_task %>
|
32
|
+
<%= f.check_box :manual_task %>
|
33
33
|
</li>
|
34
34
|
<li>
|
35
35
|
<%= f.label :error %>
|
@@ -21,9 +21,9 @@
|
|
21
21
|
<%= f.select :timer_eq,
|
22
22
|
options_for_select([["Any", nil], ["Yes", true], ["No", false]], @search_params[:timer_eq]) %>
|
23
23
|
|
24
|
-
<%= f.label :
|
25
|
-
<%= f.select :
|
26
|
-
options_for_select([["Any", nil], ["Yes", true], ["No", false]], @search_params[:
|
24
|
+
<%= f.label :manual_task_eq, "Manual Task" %>:
|
25
|
+
<%= f.select :manual_task_eq,
|
26
|
+
options_for_select([["Any", nil], ["Yes", true], ["No", false]], @search_params[:manual_task_eq]) %>
|
27
27
|
|
28
28
|
<%= f.label :error_eq, "Error" %>:
|
29
29
|
<%= f.select :error_eq,
|
@@ -40,10 +40,10 @@
|
|
40
40
|
<tr>
|
41
41
|
<th>Key</th>
|
42
42
|
<th>Type</th>
|
43
|
-
<th>
|
43
|
+
<th>Task</th>
|
44
44
|
<th>Queued</th>
|
45
45
|
<th>Timer</th>
|
46
|
-
<th>Task</th>
|
46
|
+
<th>Manual Task</th>
|
47
47
|
<th>Error</th>
|
48
48
|
<th>Created at</th>
|
49
49
|
</tr>
|
@@ -53,10 +53,10 @@
|
|
53
53
|
<tr>
|
54
54
|
<td><%= link_to job.key, job_path(job) %></td>
|
55
55
|
<td><%= job.type %></td>
|
56
|
-
<td><%= job.
|
56
|
+
<td><%= job.task.humanize.downcase %></td>
|
57
57
|
<td><%= status_tag job.delayed_job, :purple %></td>
|
58
58
|
<td><%= status_tag job.timer, :blue %></td>
|
59
|
-
<td><%= status_tag job.
|
59
|
+
<td><%= status_tag job.manual_task, :orange %></td>
|
60
60
|
<td><%= status_tag job.error, :red %></td>
|
61
61
|
<td><%= l(job.created_at, format: :long) %></td>
|
62
62
|
</tr>
|
@@ -16,10 +16,10 @@
|
|
16
16
|
<li><label>ID:</label><%= @job.id %></li>
|
17
17
|
<li><label>Key:</label><%= @job.key %></li>
|
18
18
|
<li><label>Type:</label><%= @job.type %></li>
|
19
|
-
<li><label>
|
19
|
+
<li><label>Task:</label><%= @job.task.humanize.downcase %></li>
|
20
20
|
<li><label>Queued:</label><%= status_tag @job.delayed_job, :purple %></li>
|
21
21
|
<li><label>Timer:</label><%= status_tag @job.timer, :blue %></li>
|
22
|
-
<li><label>Task:</label><%= status_tag @job.
|
22
|
+
<li><label>Manual Task:</label><%= status_tag @job.manual_task, :orange %></li>
|
23
23
|
<li><label>Error:</label><%= status_tag @job.error, :red %></li>
|
24
24
|
<li><label>Created at:</label><%= l(@job.created_at) %></li>
|
25
25
|
<li><label>Updated at:</label><%= l(@job.updated_at) %></li>
|
@@ -47,7 +47,7 @@
|
|
47
47
|
<div class="grid-4">
|
48
48
|
<div class="simple-panel job-commands">
|
49
49
|
<h2>Job commands</h2>
|
50
|
-
<% if @job.
|
50
|
+
<% if @job.task?(:end) %>
|
51
51
|
Ended
|
52
52
|
<% elsif @job.queued? %>
|
53
53
|
<div class="command">
|
@@ -58,7 +58,7 @@
|
|
58
58
|
<% else %>
|
59
59
|
<div class="command">
|
60
60
|
<%= form_tag run_job_path(@job) do %>
|
61
|
-
<%= submit_tag "Rerun the current
|
61
|
+
<%= submit_tag "Rerun the current task" %>
|
62
62
|
<% end %>
|
63
63
|
</div>
|
64
64
|
<div class="command">
|
@@ -66,9 +66,9 @@
|
|
66
66
|
<%= submit_tag "Reboot" %>
|
67
67
|
<% end %>
|
68
68
|
</div>
|
69
|
-
<% @job.
|
69
|
+
<% @job.task_transitions.each do |t| %>
|
70
70
|
<div class="command">
|
71
|
-
<%= form_tag move_job_path(@job,
|
71
|
+
<%= form_tag move_job_path(@job, task: t) do %>
|
72
72
|
<% submit_tag "Move to: #{t.to_s.titleize}" %>
|
73
73
|
<% end %>
|
74
74
|
</div>
|
@@ -4,11 +4,11 @@ class CreateLevelUpJobs < ActiveRecord::Migration
|
|
4
4
|
t.string :type
|
5
5
|
t.integer :delayed_job_id
|
6
6
|
t.string :key
|
7
|
-
t.string :
|
7
|
+
t.string :task, default: 'start'
|
8
8
|
t.boolean :error, default: false
|
9
9
|
t.boolean :timer, default: false
|
10
|
-
t.boolean :
|
11
|
-
t.text :
|
10
|
+
t.boolean :manual_task, default: false
|
11
|
+
t.text :manual_task_description
|
12
12
|
t.datetime :failed_at
|
13
13
|
t.string :failed_in
|
14
14
|
t.text :backtrace
|
@@ -21,7 +21,7 @@ class CreateLevelUpJobs < ActiveRecord::Migration
|
|
21
21
|
|
22
22
|
add_index :level_up_jobs, :type
|
23
23
|
add_index :level_up_jobs, :delayed_job_id
|
24
|
-
add_index :level_up_jobs, :
|
24
|
+
add_index :level_up_jobs, :task
|
25
25
|
add_index :level_up_jobs, :key
|
26
26
|
end
|
27
27
|
end
|