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)]