Class: Naf::ApplicationSchedule

Inherits:
NafBase
  • Object
show all
Includes:
PgAdvisoryLocker
Defined in:
app/models/naf/application_schedule.rb

Constant Summary collapse

SCHEDULES_LOCK_ID =
0

Class Method Summary collapse

Instance Method Summary collapse

Methods inherited from NafBase

full_table_name_prefix

Class Method Details

.application_not_deletedObject



159
160
161
162
163
164
165
166
167
168
# File 'app/models/naf/application_schedule.rb', line 159

def self.application_not_deleted
  where("
    NOT EXISTS (
      SELECT 1
      FROM #{Naf.schema_name}.applications AS app
      WHERE app.id = #{Naf.schema_name}.application_schedules.application_id AND
        app.deleted = true
    )
  ")
end

.constant_schedulesObject



148
149
150
151
152
153
# File 'app/models/naf/application_schedule.rb', line 148

def self.constant_schedules
  ::Naf::ApplicationSchedule.
    joins(:run_interval_style).
    where("#{Naf.schema_name}.run_interval_styles.name = ?", 'keep running').
    enabled.application_not_deleted
end

.enabledObject



155
156
157
# File 'app/models/naf/application_schedule.rb', line 155

def self.enabled
  where(enabled: true)
end

.exact_schedules(time, not_finished_applications, application_last_runs) ⇒ Object

find the exact based schedules that should be queued select anything that

isn't currently running (or queued) AND
hasn't run since run_interval AND
should have been run by now


104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
# File 'app/models/naf/application_schedule.rb', line 104

def self.exact_schedules(time, not_finished_applications, application_last_runs)
  custom_current_time = time.to_date + time.strftime('%H').to_i.hours + time.strftime('%M').to_i.minutes
  schedules = ::Naf::ApplicationSchedule.
    joins(:run_interval_style).
    where("#{Naf.schema_name}.run_interval_styles.name IN (?)", ['at beginning of day', 'at beginning of hour']).
    enabled.application_not_deleted.select do |schedule|

    interval_time = time.to_date
    if schedule.run_interval_style.name == 'at beginning of day'
      interval_time += schedule.run_interval.minutes
    elsif schedule.run_interval_style.name == 'at beginning of hour'
      interval_time += time.strftime('%H').to_i.hours + schedule.run_interval.minutes
    end

    (not_finished_applications[schedule.id].nil? &&
      (application_last_runs[schedule.id].nil? ||
        (interval_time >= application_last_runs[schedule.id].finished_at)
      ) &&
      (custom_current_time - interval_time) == 0.seconds
    )
  end

  schedules
end

.pickleablesObject



203
204
205
206
# File 'app/models/naf/application_schedule.rb', line 203

def self.pickleables
  # check the application is deleted
  self.where(deleted: false)
end

.relative_schedules(time, not_finished_applications, application_last_runs) ⇒ Object

find the interval based schedules that should be queued select anything that isn’t currently running and completed running more than run_interval minutes ago



132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
# File 'app/models/naf/application_schedule.rb', line 132

def self.relative_schedules(time, not_finished_applications, application_last_runs)
  schedules = ::Naf::ApplicationSchedule.
    joins(:run_interval_style).
    where("#{Naf.schema_name}.run_interval_styles.name = ?", 'after previous run').
    enabled.application_not_deleted.select do |schedule|

    (not_finished_applications[schedule.id].nil? &&
      (application_last_runs[schedule.id].nil? ||
        (time - application_last_runs[schedule.id].finished_at) > schedule.run_interval.minutes
      )
    )
  end

  schedules
end

.should_be_queuedObject



170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
# File 'app/models/naf/application_schedule.rb', line 170

def self.should_be_queued
  current_time = Time.zone.now
  # Applications that are still running
  not_finished_applications = ::Naf::HistoricalJob.
    queued_between(current_time - Naf::HistoricalJob::JOB_STALE_TIME, current_time).
    where("finished_at IS NULL AND request_to_terminate = false").
    find_all{ |job| job.application_schedule_id.present? }.
    index_by{ |job| job.application_schedule_id }

  # Last ran job for each application
  application_last_runs = ::Naf::HistoricalJob.application_last_runs.
    index_by{ |job| job.application_schedule_id }

  relative_schedules = ::Naf::ApplicationSchedule.
    relative_schedules(current_time, not_finished_applications, application_last_runs)
  exact_schedules = ::Naf::ApplicationSchedule.
    exact_schedules(current_time, not_finished_applications, application_last_runs)
  constant_schedules = ::Naf::ApplicationSchedule.constant_schedules

  foreman = ::Logical::Naf::ConstructionZone::Foreman.new
  return (relative_schedules + exact_schedules + constant_schedules).select do |schedule|
    affinities = []
    schedule.affinities.each do |affinity|
      affinities << { affinity_id: affinity.id }
    end

    schedule.enqueue_backlogs || !foreman.limited_by_run_group?(schedule.application_run_group_restriction,
                                                                schedule.application_run_group_name,
                                                                schedule.application_run_group_limit,
                                                                affinities)
  end
end

.try_lock_schedulesObject


*** Class Methods *** ++++++++++++++++++++++



91
92
93
# File 'app/models/naf/application_schedule.rb', line 91

def self.try_lock_schedules
  try_lock_record(SCHEDULES_LOCK_ID)
end

.unlock_schedulesObject



95
96
97
# File 'app/models/naf/application_schedule.rb', line 95

def self.unlock_schedules
  unlock_record(SCHEDULES_LOCK_ID)
end

Instance Method Details

#run_interval_checkObject

When rolling back from Naf v2.1 to v2.0, check whether run_interval or run_start_minute is nil. Otherwise, just check the presence of run_interval.



240
241
242
243
244
245
246
247
248
249
250
251
# File 'app/models/naf/application_schedule.rb', line 240

def run_interval_check
  if self.attributes.keys.include?('run_start_minute')
    if !run_start_minute.present? && !run_interval.present?
      errors.add(:run_interval, "or run_start_minute must be nil")
      errors.add(:run_start_minute, "or run_interval must be nil")
    end
  else
    if !run_interval.present?
      errors.add(:run_interval, "must be present")
    end
  end
end

#to_sObject


*** Instance Methods *** +++++++++++++++++++++++++



212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
# File 'app/models/naf/application_schedule.rb', line 212

def to_s
  components = []
  if enabled
    components << "ENABLED"
  else
    if visible
      components << "DISABLED"
    else
      components << "HIDDEN|DISABLED"
    end
  end
  components << "id: #{id}"
  components << "\"#{application.title}\""
  components << ::Logical::Naf::ApplicationSchedule.new(self).display

  return "::Naf::ApplicationSchedule<#{components.join(', ')}>"
end

#visible_enabled_checkObject



230
231
232
233
234
235
# File 'app/models/naf/application_schedule.rb', line 230

def visible_enabled_check
  unless visible or !enabled
    errors.add(:visible, "must be true, or set enabled to false")
    errors.add(:enabled, "must be false, if visible is set to false")
  end
end