crono_trigger 0.4.0 → 0.5.0
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 +4 -4
- data/.travis.yml +4 -2
- data/README.md +2 -2
- data/Rakefile +2 -0
- data/crono_trigger.gemspec +1 -1
- data/lib/crono_trigger.rb +1 -0
- data/lib/crono_trigger/execution_tracker.rb +22 -0
- data/lib/crono_trigger/models/execution.rb +35 -0
- data/lib/crono_trigger/polling_thread.rb +3 -1
- data/lib/crono_trigger/schedulable.rb +55 -18
- data/lib/crono_trigger/version.rb +1 -1
- data/lib/crono_trigger/web.rb +57 -16
- data/lib/generators/crono_trigger/install/templates/install.rb +15 -0
- data/lib/generators/crono_trigger/migration/templates/create_table_migration.rb +1 -1
- data/web/app/package-lock.json +4679 -4361
- data/web/app/package.json +15 -15
- data/web/app/src/Execution.tsx +156 -0
- data/web/app/src/SchedulableRecords.tsx +56 -1
- data/web/app/src/interfaces.ts +20 -1
- data/web/public/asset-manifest.json +2 -2
- data/web/public/service-worker.js +1 -1
- data/web/public/static/js/main.a4709ab6.js +2 -0
- data/web/public/static/js/main.a4709ab6.js.map +1 -0
- data/web/views/index.erb +1 -1
- metadata +12 -10
- data/web/public/static/js/main.1413dc51.js +0 -2
- data/web/public/static/js/main.1413dc51.js.map +0 -1
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 7a1befee8d18a2c52458baa240cc2b12a8d9fea015a53647c0f098cae21d062d
|
4
|
+
data.tar.gz: c6fad9a37fdf912c88712c93b64ace75386b9c2f37cdc9bcf609de711a7b8939
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 7d383986c2c68d31dbe6fa681599816e564c07dfa3bba92c4edf9cb8b581b934293636446d97a85c2fec87f64af9cd2c81b7ec6edcfc89fe9c905dac6ce1eaf3
|
7
|
+
data.tar.gz: 4940e47e60802b4cf2caab3eee22069ba61e1f81b0178b1f696c485c330b5b5340d9d058764f70e40a608839cb2d35354ea877e3bbe32c9377d61fbbaa71233c
|
data/.travis.yml
CHANGED
@@ -2,8 +2,8 @@ sudo: false
|
|
2
2
|
language: ruby
|
3
3
|
cache: bundler
|
4
4
|
rvm:
|
5
|
-
- 2.
|
6
|
-
- 2.
|
5
|
+
- 2.6.1
|
6
|
+
- 2.5.2
|
7
7
|
gemfile:
|
8
8
|
- gemfiles/activerecord-51.gemfile
|
9
9
|
- gemfiles/activerecord-52.gemfile
|
@@ -12,3 +12,5 @@ before_install:
|
|
12
12
|
env:
|
13
13
|
- DB=sqlite
|
14
14
|
- DB=mysql MYSQL_RESTART_COMMAND="sudo service mysql restart"
|
15
|
+
- NO_TIMESTAMP=false
|
16
|
+
- NO_TIMESTAMP=true
|
data/README.md
CHANGED
@@ -70,7 +70,7 @@ class CreateMailNotifications < ActiveRecord::Migration
|
|
70
70
|
t.datetime :next_execute_at
|
71
71
|
t.datetime :last_executed_at
|
72
72
|
t.integer :execute_lock, limit: 8, default: 0, null: false
|
73
|
-
t.datetime :started_at
|
73
|
+
t.datetime :started_at
|
74
74
|
t.datetime :finished_at
|
75
75
|
t.string :last_error_name
|
76
76
|
t.string :last_error_reason
|
@@ -118,7 +118,7 @@ class MailNotification < ActiveRecord::Base
|
|
118
118
|
end
|
119
119
|
|
120
120
|
# one time schedule
|
121
|
-
MailNotification.create(
|
121
|
+
MailNotification.create.activate_schedule!(at: Time.current.since(5.minutes))
|
122
122
|
|
123
123
|
# cron schedule
|
124
124
|
MailNotification.create(cron: "0 12 * * *").activate_schedule!
|
data/Rakefile
CHANGED
@@ -10,11 +10,13 @@ pwd = File.expand_path('../', __FILE__)
|
|
10
10
|
gemfiles = Dir.glob(File.join(pwd, "gemfiles", "*.gemfile")).map { |f| File.basename(f, ".*") }
|
11
11
|
|
12
12
|
namespace :js do
|
13
|
+
desc "Cleanup built javascripts"
|
13
14
|
task :clean do
|
14
15
|
rm_r(File.join(pwd, "web", "app", "build")) if File.exist?(File.join(pwd, "web", "app", "build"))
|
15
16
|
rm_r(File.join(pwd, "web", "public"))
|
16
17
|
end
|
17
18
|
|
19
|
+
desc "build javascripts"
|
18
20
|
task build: [:clean] do
|
19
21
|
Dir.chdir(File.join(pwd, "web", "app"))
|
20
22
|
sh({"PUBLIC_URL" => "<%= URI.parse(url('/')).path.chop %>"}, "npm run build") do |ok, res|
|
data/crono_trigger.gemspec
CHANGED
@@ -31,7 +31,7 @@ Gem::Specification.new do |spec|
|
|
31
31
|
spec.add_dependency "oj"
|
32
32
|
spec.add_dependency "activerecord", ">= 4.2"
|
33
33
|
|
34
|
-
spec.add_development_dependency "sqlite3"
|
34
|
+
spec.add_development_dependency "sqlite3", "~> 1.3.6"
|
35
35
|
spec.add_development_dependency "mysql2"
|
36
36
|
spec.add_development_dependency "timecop"
|
37
37
|
spec.add_development_dependency "rollbar"
|
data/lib/crono_trigger.rb
CHANGED
@@ -6,6 +6,7 @@ require "active_record"
|
|
6
6
|
require "concurrent"
|
7
7
|
require "crono_trigger/models/worker"
|
8
8
|
require "crono_trigger/models/signal"
|
9
|
+
require "crono_trigger/models/execution"
|
9
10
|
require "crono_trigger/worker"
|
10
11
|
require "crono_trigger/polling_thread"
|
11
12
|
require "crono_trigger/schedulable"
|
@@ -0,0 +1,22 @@
|
|
1
|
+
module CronoTrigger
|
2
|
+
class ExecutionTracker
|
3
|
+
def initialize(schedulable)
|
4
|
+
@schedulable = schedulable
|
5
|
+
end
|
6
|
+
|
7
|
+
def track(&pr)
|
8
|
+
if @schedulable.track_execution
|
9
|
+
begin
|
10
|
+
execution = @schedulable.crono_trigger_executions.create_with_timestamp!
|
11
|
+
pr.call
|
12
|
+
execution.complete!
|
13
|
+
rescue => e
|
14
|
+
execution.error!(e)
|
15
|
+
raise
|
16
|
+
end
|
17
|
+
else
|
18
|
+
pr.call
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
@@ -0,0 +1,35 @@
|
|
1
|
+
module CronoTrigger
|
2
|
+
module Models
|
3
|
+
class Execution < ActiveRecord::Base
|
4
|
+
self.table_name = "crono_trigger_executions"
|
5
|
+
|
6
|
+
belongs_to :schedule, polymorphic: true, inverse_of: :crono_trigger_executions
|
7
|
+
|
8
|
+
scope :recently, ->(schedule_type:) { where(schedule_type: schedule_type).order(executed_at: :desc) }
|
9
|
+
|
10
|
+
enum status: {
|
11
|
+
executing: "executing",
|
12
|
+
completed: "completed",
|
13
|
+
failed: "failed",
|
14
|
+
}
|
15
|
+
|
16
|
+
def self.create_with_timestamp!
|
17
|
+
create!(executed_at: Time.current, status: :executing, worker_id: CronoTrigger.config.worker_id)
|
18
|
+
end
|
19
|
+
|
20
|
+
def complete!
|
21
|
+
update!(status: :completed, completed_at: Time.current)
|
22
|
+
end
|
23
|
+
|
24
|
+
def error!(exception)
|
25
|
+
update!(status: :failed, completed_at: Time.current, error_name: exception.class.to_s, error_reason: exception.message)
|
26
|
+
end
|
27
|
+
|
28
|
+
def retry!
|
29
|
+
return false if schedule.locking?
|
30
|
+
|
31
|
+
schedule.retry!
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
@@ -85,7 +85,9 @@ module CronoTrigger
|
|
85
85
|
|
86
86
|
private def unlock_overflowed_records(model, overflowed_record_ids)
|
87
87
|
model.connection_pool.with_connection do
|
88
|
-
|
88
|
+
unless overflowed_record_ids.empty?
|
89
|
+
model.where(id: overflowed_record_ids).crono_trigger_unlock_all!
|
90
|
+
end
|
89
91
|
end
|
90
92
|
rescue ActiveRecord::ConnectionNotEstablished, ActiveRecord::LockWaitTimeout, ActiveRecord::StatementTimeout, ActiveRecord::Deadlocked
|
91
93
|
sleep 1
|
@@ -4,6 +4,7 @@ require "chrono"
|
|
4
4
|
require "tzinfo"
|
5
5
|
|
6
6
|
require "crono_trigger/exception_handler"
|
7
|
+
require "crono_trigger/execution_tracker"
|
7
8
|
|
8
9
|
module CronoTrigger
|
9
10
|
module Schedulable
|
@@ -26,9 +27,12 @@ module CronoTrigger
|
|
26
27
|
|
27
28
|
included do
|
28
29
|
CronoTrigger::Schedulable.included_by << self
|
29
|
-
class_attribute :crono_trigger_options, :executable_conditions
|
30
|
+
class_attribute :crono_trigger_options, :executable_conditions, :track_execution
|
30
31
|
self.crono_trigger_options ||= {}
|
31
32
|
self.executable_conditions ||= []
|
33
|
+
self.track_execution ||= false
|
34
|
+
|
35
|
+
has_many :crono_trigger_executions, class_name: "CronoTrigger::Models::Execution", as: :schedule, inverse_of: :schedule
|
32
36
|
|
33
37
|
define_model_callbacks :execute, :retry
|
34
38
|
|
@@ -36,7 +40,7 @@ module CronoTrigger
|
|
36
40
|
t = arel_table
|
37
41
|
|
38
42
|
rel = where(t[crono_trigger_column_name(:next_execute_at)].lteq(from))
|
39
|
-
rel = rel.where(t[crono_trigger_column_name(:execute_lock)].
|
43
|
+
rel = rel.where(t[crono_trigger_column_name(:execute_lock)].lt(from.to_i - execute_lock_timeout)) unless including_locked
|
40
44
|
|
41
45
|
rel = rel.where(t[crono_trigger_column_name(:started_at)].lteq(from)) if column_names.include?(crono_trigger_column_name(:started_at))
|
42
46
|
rel = rel.where(t[crono_trigger_column_name(:finished_at)].gt(from).or(t[crono_trigger_column_name(:finished_at)].eq(nil))) if column_names.include?(crono_trigger_column_name(:finished_at))
|
@@ -61,17 +65,18 @@ module CronoTrigger
|
|
61
65
|
|
62
66
|
module ClassMethods
|
63
67
|
def executables_with_lock(limit: CronoTrigger.config.executor_thread * 3 || 100)
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
68
|
+
ids = executables(limit: limit).pluck(:id)
|
69
|
+
records = []
|
70
|
+
ids.each do |id|
|
71
|
+
transaction do
|
72
|
+
r = all.lock.find(id)
|
73
|
+
unless r.locking?
|
74
|
+
r.crono_trigger_lock!
|
75
|
+
records << r
|
76
|
+
end
|
72
77
|
end
|
73
|
-
records
|
74
78
|
end
|
79
|
+
records
|
75
80
|
end
|
76
81
|
|
77
82
|
def crono_trigger_column_name(name)
|
@@ -106,12 +111,15 @@ module CronoTrigger
|
|
106
111
|
end
|
107
112
|
|
108
113
|
def do_execute
|
114
|
+
execution_tracker = ExecutionTracker.new(self)
|
109
115
|
run_callbacks :execute do
|
110
116
|
catch(:ok_without_reset) do
|
111
117
|
catch(:ok) do
|
112
118
|
catch(:retry) do
|
113
119
|
catch(:abort) do
|
114
|
-
|
120
|
+
execution_tracker.track do
|
121
|
+
execute
|
122
|
+
end
|
115
123
|
throw :ok
|
116
124
|
end
|
117
125
|
raise AbortExecution
|
@@ -151,16 +159,23 @@ module CronoTrigger
|
|
151
159
|
if new_record?
|
152
160
|
self.attributes = attributes
|
153
161
|
else
|
162
|
+
merge_updated_at_for_crono_trigger!(attributes)
|
154
163
|
update_columns(attributes)
|
155
164
|
end
|
165
|
+
|
166
|
+
self
|
156
167
|
end
|
157
168
|
|
158
|
-
def retry!
|
169
|
+
def retry!(immediately: false)
|
159
170
|
run_callbacks :retry do
|
160
171
|
logger.info "Retry #{self.class}-#{id}" if logger
|
161
172
|
|
162
173
|
now = Time.current
|
163
|
-
|
174
|
+
if immediately
|
175
|
+
wait = 0
|
176
|
+
else
|
177
|
+
wait = crono_trigger_options[:exponential_backoff] ? retry_interval * [2 * (retry_count - 1), 1].max : retry_interval
|
178
|
+
end
|
164
179
|
attributes = {
|
165
180
|
crono_trigger_column_name(:next_execute_at) => now + wait,
|
166
181
|
crono_trigger_column_name(:execute_lock) => 0,
|
@@ -171,6 +186,7 @@ module CronoTrigger
|
|
171
186
|
attributes.merge!(retry_count: retry_count.to_i + 1)
|
172
187
|
end
|
173
188
|
|
189
|
+
merge_updated_at_for_crono_trigger!(attributes, now)
|
174
190
|
update_columns(attributes)
|
175
191
|
end
|
176
192
|
end
|
@@ -184,22 +200,36 @@ module CronoTrigger
|
|
184
200
|
crono_trigger_column_name(:locked_by) => nil,
|
185
201
|
}
|
186
202
|
|
203
|
+
now = Time.current
|
204
|
+
|
187
205
|
if update_last_executed_at && self.class.column_names.include?(crono_trigger_column_name(:last_executed_at))
|
188
|
-
attributes.merge!(crono_trigger_column_name(:last_executed_at) =>
|
206
|
+
attributes.merge!(crono_trigger_column_name(:last_executed_at) => now)
|
189
207
|
end
|
190
208
|
|
191
209
|
if self.class.column_names.include?("retry_count")
|
192
210
|
attributes.merge!(retry_count: 0)
|
193
211
|
end
|
194
212
|
|
213
|
+
merge_updated_at_for_crono_trigger!(attributes, now)
|
214
|
+
update_columns(attributes)
|
215
|
+
end
|
216
|
+
|
217
|
+
def crono_trigger_lock!
|
218
|
+
attributes = {
|
219
|
+
crono_trigger_column_name(:execute_lock) => Time.current.to_i,
|
220
|
+
crono_trigger_column_name(:locked_by) => CronoTrigger.config.worker_id
|
221
|
+
}
|
222
|
+
merge_updated_at_for_crono_trigger!(attributes)
|
195
223
|
update_columns(attributes)
|
196
224
|
end
|
197
225
|
|
198
226
|
def crono_trigger_unlock!
|
199
|
-
|
227
|
+
attributes = {
|
200
228
|
crono_trigger_column_name(:execute_lock) => 0,
|
201
229
|
crono_trigger_column_name(:locked_by) => nil,
|
202
|
-
|
230
|
+
}
|
231
|
+
merge_updated_at_for_crono_trigger!(attributes)
|
232
|
+
update_columns(attributes)
|
203
233
|
end
|
204
234
|
|
205
235
|
def crono_trigger_status
|
@@ -223,7 +253,7 @@ module CronoTrigger
|
|
223
253
|
|
224
254
|
def locking?(at: Time.now)
|
225
255
|
self[crono_trigger_column_name(:execute_lock)] > 0 &&
|
226
|
-
self[crono_trigger_column_name(:execute_lock)]
|
256
|
+
self[crono_trigger_column_name(:execute_lock)] >= at.to_f - self.class.execute_lock_timeout
|
227
257
|
end
|
228
258
|
|
229
259
|
def assume_executing?
|
@@ -298,7 +328,14 @@ module CronoTrigger
|
|
298
328
|
attributes.merge!(last_error_time: now)
|
299
329
|
end
|
300
330
|
|
331
|
+
merge_updated_at_for_crono_trigger!(attributes)
|
301
332
|
update_columns(attributes) unless attributes.empty?
|
302
333
|
end
|
334
|
+
|
335
|
+
def merge_updated_at_for_crono_trigger!(attributes, time = Time.current)
|
336
|
+
if self.class.column_names.include?("updated_at")
|
337
|
+
attributes.merge!("updated_at" => time)
|
338
|
+
end
|
339
|
+
end
|
303
340
|
end
|
304
341
|
end
|
data/lib/crono_trigger/web.rb
CHANGED
@@ -1,6 +1,7 @@
|
|
1
1
|
require "crono_trigger"
|
2
2
|
require "sinatra/base"
|
3
3
|
require "rack/contrib/post_body_content_type_parser"
|
4
|
+
require "oj"
|
4
5
|
|
5
6
|
module CronoTrigger
|
6
7
|
class Web < Sinatra::Application
|
@@ -87,6 +88,13 @@ module CronoTrigger
|
|
87
88
|
end
|
88
89
|
end
|
89
90
|
|
91
|
+
|
92
|
+
post "/models/executions/:id/retry" do
|
93
|
+
CronoTrigger::Models::Execution.find(params[:id]).retry!
|
94
|
+
status 200
|
95
|
+
body ""
|
96
|
+
end
|
97
|
+
|
90
98
|
post "/models/:name/:id/retry" do
|
91
99
|
model_class = CronoTrigger::Schedulable.included_by.find { |c| c.name == params[:name] }
|
92
100
|
if model_class
|
@@ -110,22 +118,22 @@ module CronoTrigger
|
|
110
118
|
now = Time.now
|
111
119
|
records = @scheduled_records.map do |r|
|
112
120
|
{
|
113
|
-
"crono_trigger_status" => r.crono_trigger_status,
|
114
|
-
"id" => r.id,
|
115
|
-
"cron" => r[r.crono_trigger_column_name(:cron)],
|
116
|
-
"next_execute_at" => r[r.crono_trigger_column_name(:next_execute_at)],
|
117
|
-
"last_executed_at" => r[r.crono_trigger_column_name(:last_executed_at)],
|
118
|
-
"timezone" => r[r.crono_trigger_column_name(:timezone)],
|
119
|
-
"execute_lock" => r[r.crono_trigger_column_name(:execute_lock)],
|
120
|
-
"locked_by" => r[r.crono_trigger_column_name(:locked_by)],
|
121
|
-
"started_at" => r[r.crono_trigger_column_name(:started_at)],
|
122
|
-
"finished_at" => r[r.crono_trigger_column_name(:finished_at)],
|
123
|
-
"last_error_name" => r[r.crono_trigger_column_name(:last_error_name)],
|
124
|
-
"last_error_reason" => r[r.crono_trigger_column_name(:last_error_reason)],
|
125
|
-
"last_error_time" => r[r.crono_trigger_column_name(:last_error_time)],
|
126
|
-
"retry_count" => r[r.crono_trigger_column_name(:retry_count)],
|
127
|
-
"time_to_unlock" => [(r.class.execute_lock_timeout + r[r.crono_trigger_column_name(:execute_lock)]) - now.to_i, 0].max,
|
128
|
-
"delay_sec" => r.locking?(at: now) ? 0 : (now - r[r.crono_trigger_column_name(:next_execute_at)]).to_i,
|
121
|
+
-"crono_trigger_status" => r.crono_trigger_status,
|
122
|
+
-"id" => r.id,
|
123
|
+
-"cron" => r[r.crono_trigger_column_name(:cron)],
|
124
|
+
-"next_execute_at" => r[r.crono_trigger_column_name(:next_execute_at)],
|
125
|
+
-"last_executed_at" => r[r.crono_trigger_column_name(:last_executed_at)],
|
126
|
+
-"timezone" => r[r.crono_trigger_column_name(:timezone)],
|
127
|
+
-"execute_lock" => r[r.crono_trigger_column_name(:execute_lock)],
|
128
|
+
-"locked_by" => r[r.crono_trigger_column_name(:locked_by)],
|
129
|
+
-"started_at" => r[r.crono_trigger_column_name(:started_at)],
|
130
|
+
-"finished_at" => r[r.crono_trigger_column_name(:finished_at)],
|
131
|
+
-"last_error_name" => r[r.crono_trigger_column_name(:last_error_name)],
|
132
|
+
-"last_error_reason" => r[r.crono_trigger_column_name(:last_error_reason)],
|
133
|
+
-"last_error_time" => r[r.crono_trigger_column_name(:last_error_time)],
|
134
|
+
-"retry_count" => r[r.crono_trigger_column_name(:retry_count)],
|
135
|
+
-"time_to_unlock" => [(r.class.execute_lock_timeout + r[r.crono_trigger_column_name(:execute_lock)]) - now.to_i, 0].max,
|
136
|
+
-"delay_sec" => r.locking?(at: now) ? 0 : (now - r[r.crono_trigger_column_name(:next_execute_at)]).to_i,
|
129
137
|
}
|
130
138
|
end
|
131
139
|
Oj.dump({
|
@@ -159,5 +167,38 @@ module CronoTrigger
|
|
159
167
|
get "/models" do
|
160
168
|
erb :index
|
161
169
|
end
|
170
|
+
|
171
|
+
get "/models/:name/executions.:format" do
|
172
|
+
if params[:format] == "json"
|
173
|
+
model_class = CronoTrigger::Schedulable.included_by.find { |c| c.name == params[:name] }
|
174
|
+
if model_class
|
175
|
+
rel = CronoTrigger::Models::Execution.recently(schedule_type: model_class)
|
176
|
+
rel.where!("executed_at >= ?", Time.parse(params[:from])) if params[:from]
|
177
|
+
rel.where!("executed_at <= ?", Time.parse(params[:to])) if params[:to]
|
178
|
+
rel = rel.limit(params[:limit] || 100)
|
179
|
+
records = rel.map do |r|
|
180
|
+
{
|
181
|
+
-"id" => r.id,
|
182
|
+
-"schedule_id" => r.schedule_id,
|
183
|
+
-"schedule_type" => r.schedule_type,
|
184
|
+
-"worker_id" => r.worker_id,
|
185
|
+
-"executed_at" => r.executed_at,
|
186
|
+
-"completed_at" => r.completed_at,
|
187
|
+
-"status" => r.status,
|
188
|
+
-"error_name" => r.error_name,
|
189
|
+
-"error_reason" => r.error_reason,
|
190
|
+
}
|
191
|
+
end
|
192
|
+
Oj.dump({
|
193
|
+
records: records,
|
194
|
+
}, mode: :compat)
|
195
|
+
else
|
196
|
+
status 404
|
197
|
+
"Model Class is not found"
|
198
|
+
end
|
199
|
+
else
|
200
|
+
raise "unknown format"
|
201
|
+
end
|
202
|
+
end
|
162
203
|
end
|
163
204
|
end
|
@@ -19,5 +19,20 @@ class CreateCronoTriggerSystemTables < ActiveRecord::Migration<%= Rails::VERSION
|
|
19
19
|
end
|
20
20
|
|
21
21
|
add_index :crono_trigger_signals, [:sent_at, :worker_id]
|
22
|
+
|
23
|
+
create_table :crono_trigger_executions do |t|
|
24
|
+
t.integer :schedule_id, null: false
|
25
|
+
t.string :schedule_type, null: false
|
26
|
+
t.string :worker_id, null: false
|
27
|
+
t.datetime :executed_at, null: false
|
28
|
+
t.datetime :completed_at
|
29
|
+
t.string :status, null: false, default: "executing"
|
30
|
+
t.string :error_name
|
31
|
+
t.string :error_reason
|
32
|
+
end
|
33
|
+
|
34
|
+
add_index :crono_trigger_executions, [:schedule_type, :schedule_id, :executed_at], name: "index_crono_trigger_executions_on_schtype_schid_executed_at"
|
35
|
+
add_index :crono_trigger_executions, [:schedule_type, :executed_at]
|
36
|
+
add_index :crono_trigger_executions, [:executed_at]
|
22
37
|
end
|
23
38
|
end
|