module CanvasSync module Jobs class BeginSyncChainJob < CanvasSync::Job attr_reader :globals def perform(chain_definition, globals = {}) @globals = globals if globals[:updated_after] == nil && Rails.env.development? globals[:updated_after] = false end if globals[:updated_after] == false globals[:updated_after] = nil elsif !globals[:updated_after].present? || globals[:updated_after] == true last_batch = SyncBatch.where(status: 'completed', batch_genre: genre).last globals[:full_sync_every] ||= "sunday/2" globals[:updated_after] = ((last_batch.started_at - 1.day).iso8601 rescue nil) end # Refuse to run syncs of the same genre if there is a running full sync if last_full_sync_record&.status == 'processing' && last_full_sync > 12.hours.ago Rails.logger.warn("Attempted to start a '#{genre}' sync while a full-sync is still processing.") return end if should_full_sync?(globals[:full_sync_every]) globals[:updated_after] = nil end sync_batch = SyncBatch.create!( started_at: DateTime.now, full_sync: globals[:updated_after] == nil, batch_genre: genre, status: 'processing', ) globals[:batch_genre] = genre globals[:batch_start_time] = sync_batch.started_at.iso8601 globals[:sync_batch_id] = sync_batch.id JobBatches::Batch.new.tap do |b| b.description = "CanvasSync Root Batch (SyncBatch##{sync_batch.id})" b.on(:complete, "#{self.class.to_s}.batch_completed", sync_batch_id: sync_batch.id) b.on(:success, "#{self.class.to_s}.batch_completed", sync_batch_id: sync_batch.id) b.context = globals b.jobs do JobBatches::SerialBatchJob.perform_now(chain_definition) end sync_batch.update(batch_bid: b.bid) end end def should_full_sync?(opt) return true unless last_full_sync.present? return false unless opt.is_a?(String) case opt.strip when %r{^(sunday|monday|tuesday|wednesday|thursday|friday|saturday)(?:/(\d+))?$} m = Regexp.last_match day = m[1] skip = m[2] || "1" DateTime.now.send(:"#{day}?") && last_full_sync.end_of_day <= (skip.to_i.weeks.ago.end_of_day) when %r{^(\d+)\%$} m = Regexp.last_match rand(100) < m[1].to_i when %r{^(\d+) ?days$} m = Regexp.last_match last_full_sync.end_of_day <= m[1].to_i.days.ago.end_of_day when %r{^(\d+)$} # N.days is converted to a string of seconds m = Regexp.last_match last_full_sync.end_of_day <= m[1].to_i.seconds.ago.end_of_day else false end end def last_full_sync_record @last_full_sync_record ||= SyncBatch.where(status: ['completed', 'processing'], full_sync: true, batch_genre: genre).last end def last_full_sync last_full_sync_record&.started_at end def genre globals[:batch_genre] || "default" end def self.batch_completed(status, options) sbatch = SyncBatch.find(options['sync_batch_id']) sbatch.update!( status: status.success? ? 'completed' : 'failed', completed_at: DateTime.now, ) end end end end