lib/crono_trigger/schedulable.rb in crono_trigger-0.5.4 vs lib/crono_trigger/schedulable.rb in crono_trigger-0.6.0
- old
+ new
@@ -18,13 +18,10 @@
def self.included_by
@included_by
end
- class AbortExecution < StandardError; end
- class RetryExecution < StandardError; end
-
extend ActiveSupport::Concern
include ActiveSupport::Callbacks
included do
CronoTrigger::Schedulable.included_by << self
@@ -57,10 +54,11 @@
end
rel
end
+ before_create :set_current_cyctle_id
before_update :update_next_execute_at_if_update_cron
validate :validate_cron_format
end
@@ -110,41 +108,38 @@
self.executable_conditions.clear
end
end
def do_execute
- execution_tracker = ExecutionTracker.new(self)
- run_callbacks :execute do
- execution_tracker.track do
- catch(:ok_without_reset) do
- catch(:ok) do
- catch(:retry) do
- catch(:abort) do
- execute
- throw :ok
- end
- raise AbortExecution
- end
- retry!
- raise RetryExecution
- end
- reset!
- end
- end
+ ExecutionTracker.track(self) do
+ do_execute_with_catch
end
- rescue AbortExecution => ex
- save_last_error_info(ex)
- reset!(false)
-
- raise
- rescue RetryExecution => ex
- save_last_error_info(ex)
rescue Exception => ex
+ logger.error(ex) if logger
save_last_error_info(ex)
retry_or_reset!(ex)
+ end
- raise
+ private def do_execute_with_catch
+ catch(:ok_without_reset) do
+ catch(:ok) do
+ catch(:retry) do
+ catch(:abort) do
+ run_callbacks :execute do
+ execute
+ end
+ throw :ok
+ end
+ abort_execution!
+ return :abort
+ end
+ retry!
+ return :retry
+ end
+ reset!
+ return :ok
+ end
end
def activate_schedule!(at: Time.current)
time = calculate_next_execute_at || at
@@ -211,14 +206,22 @@
if self.class.column_names.include?("retry_count")
attributes.merge!(retry_count: 0)
end
+ if self.class.column_names.include?(crono_trigger_column_name(:current_cycle_id))
+ attributes.merge!(crono_trigger_column_name(:current_cycle_id) => SecureRandom.uuid)
+ end
+
merge_updated_at_for_crono_trigger!(attributes, now)
update_columns(attributes)
end
+ def abort_execution!
+ reset!(false)
+ end
+
def crono_trigger_lock!(**attributes)
attributes = {
crono_trigger_column_name(:execute_lock) => Time.current.to_i,
crono_trigger_column_name(:locked_by) => CronoTrigger.config.worker_id
}.merge(attributes)
@@ -257,11 +260,11 @@
def not_scheduled?
self[crono_trigger_column_name(:next_execute_at)].nil? && last_executed_at.nil?
end
def locking?(at: Time.now)
- self[crono_trigger_column_name(:execute_lock)] > 0 &&
+ self[crono_trigger_column_name(:execute_lock)] > 0 &&
self[crono_trigger_column_name(:execute_lock)] >= at.to_f - self.class.execute_lock_timeout
end
def assume_executing?
locking?
@@ -291,10 +294,22 @@
def calculate_next_execute_at(now = Time.current)
if self[crono_trigger_column_name(:cron)]
tz = self[crono_trigger_column_name(:timezone)].try { |zn| TZInfo::Timezone.get(zn) }
base = [now, self[crono_trigger_column_name(:started_at)]].compact.max
cron_now = tz ? base.in_time_zone(tz) : base
- Chrono::NextTime.new(now: cron_now, source: self[crono_trigger_column_name(:cron)]).to_time
+ calculated = Chrono::NextTime.new(now: cron_now, source: self[crono_trigger_column_name(:cron)]).to_time
+
+ return calculated unless self[crono_trigger_column_name(:finished_at)]
+ return if calculated > self[crono_trigger_column_name(:finished_at)]
+
+ calculated
+ end
+ end
+
+ def set_current_cyctle_id
+ if self.class.column_names.include?(crono_trigger_column_name(:current_cycle_id)) &&
+ self[crono_trigger_column_name(:current_cycle_id)].nil?
+ self[crono_trigger_column_name(:current_cycle_id)] = SecureRandom.uuid
end
end
def update_next_execute_at_if_update_cron
if changes[crono_trigger_column_name(:cron)] || changes[crono_trigger_column_name(:timezone)]