Module: Dalliance

Extended by:
ActiveSupport::Concern
Defined in:
lib/dalliance.rb,
lib/dalliance/engine.rb,
lib/dalliance/schema.rb,
lib/dalliance/version.rb,
lib/dalliance/workers.rb,
lib/dalliance/progress_meter.rb,
lib/dalliance/workers/resque.rb,
lib/dalliance/workers/delayed_job.rb,
lib/generators/dalliance/update/update_generator.rb,
lib/generators/dalliance/progress_meter/progress_meter_generator.rb

Defined Under Namespace

Modules: ClassMethods, Glue, Schema, VERSION, Workers Classes: Engine, ProgressMeter, ProgressMeterGenerator, UpdateGenerator

Class Method Summary collapse

Instance Method Summary collapse

Class Method Details

.background_processing=(value) ⇒ Object



31
32
33
# File 'lib/dalliance.rb', line 31

def background_processing=(value)
  options[:background_processing] = value
end

.configure {|_self| ... } ⇒ Object

Yields:

  • (_self)

Yield Parameters:

  • _self (Dalliance)

    the object that the method was called on



63
64
65
# File 'lib/dalliance.rb', line 63

def configure
  yield(self) if block_given?
end

.dalliance_progress_meter=(value) ⇒ Object



35
36
37
# File 'lib/dalliance.rb', line 35

def dalliance_progress_meter=(value)
  options[:dalliance_progress_meter] = value
end

.dalliance_progress_meter_total_count_method=(value) ⇒ Object



39
40
41
# File 'lib/dalliance.rb', line 39

def dalliance_progress_meter_total_count_method=(value)
  options[:dalliance_progress_meter_total_count_method] = value
end

.detect_loggerObject



72
73
74
75
76
77
78
79
80
# File 'lib/dalliance.rb', line 72

def detect_logger
  if defined?(ActiveRecord)
    ActiveRecord::Base.logger
  elsif defined?(Rails)
    Rails.logger
  else
    ::Logger.new(STDOUT)
  end
end

.detect_worker_classObject



67
68
69
70
# File 'lib/dalliance.rb', line 67

def detect_worker_class
  return Dalliance::Workers::DelayedJob if defined? ::Delayed::Job
  return Dalliance::Workers::Resque     if defined? ::Resque
end

.duration_column=(value) ⇒ Object



55
56
57
# File 'lib/dalliance.rb', line 55

def duration_column=(value)
  options[:duration_column] = value
end

.error_notifier=(value) ⇒ Object



59
60
61
# File 'lib/dalliance.rb', line 59

def error_notifier=(value)
  options[:error_notifier] = value
end

.logger=(value) ⇒ Object



51
52
53
# File 'lib/dalliance.rb', line 51

def logger=(value)
  options[:logger] = value
end

.optionsObject



18
19
20
21
22
23
24
25
26
27
28
29
# File 'lib/dalliance.rb', line 18

def options
  @options ||= {
    :background_processing => (defined?(Rails) ? (Rails.env.production? || Rails.env.staging?) : true),
    :dalliance_progress_meter => true,
    :dalliance_progress_meter_total_count_method => :dalliance_progress_meter_total_count,
    :worker_class => detect_worker_class,
    :queue => 'dalliance',
    :logger => detect_logger,
    :duration_column => 'dalliance_duration',
    :error_notifier => ->(e){}
  }
end

.queue=(value) ⇒ Object



47
48
49
# File 'lib/dalliance.rb', line 47

def queue=(value)
  options[:queue] = value
end

.worker_class=(value) ⇒ Object



43
44
45
# File 'lib/dalliance.rb', line 43

def worker_class=(value)
  options[:worker_class] = value
end

Instance Method Details

#calculate_dalliance_progress_meter_total_countObject

If the progress_meter_total_count_method is not implemented or raises and error just use 1…



331
332
333
334
335
336
337
338
339
340
341
# File 'lib/dalliance.rb', line 331

def calculate_dalliance_progress_meter_total_count
  begin
    if respond_to?(self.class.dalliance_options[:dalliance_progress_meter_total_count_method])
      self.send(self.class.dalliance_options[:dalliance_progress_meter_total_count_method])
    else
      1
    end
  rescue
    1
  end
end

#dalliance_background_process(background_processing = nil) ⇒ Object

Force background_processing w/ true



223
224
225
226
227
228
229
# File 'lib/dalliance.rb', line 223

def dalliance_background_process(background_processing = nil)
  if background_processing || (background_processing.nil? && self.class.dalliance_options[:background_processing])
    self.class.dalliance_options[:worker_class].enqueue(self, processing_queue, :dalliance_process)
  else
    dalliance_process(false)
  end
end

#dalliance_background_reprocess(background_processing = nil) ⇒ Object



238
239
240
241
242
243
244
245
246
247
248
249
# File 'lib/dalliance.rb', line 238

def dalliance_background_reprocess(background_processing = nil)
  # Reset state to 'pending' before queueing up
  # Otherwise the model will stay on completed/processing_error until the job
  # is taken by a worker, which could be a long time after this method is
  # called.
  reprocess_dalliance!
  if background_processing || (background_processing.nil? && self.class.dalliance_options[:background_processing])
    self.class.dalliance_options[:worker_class].enqueue(self, processing_queue, :do_dalliance_reprocess)
  else
    do_dalliance_reprocess(false)
  end
end

#dalliance_log(message) ⇒ Object



153
154
155
156
157
# File 'lib/dalliance.rb', line 153

def dalliance_log(message)
  if self.class.dalliance_options[:logger]
    self.class.dalliance_options[:logger].info(message)
  end
end

#dalliance_process(background_processing = false) ⇒ Object



231
232
233
234
235
236
# File 'lib/dalliance.rb', line 231

def dalliance_process(background_processing = false)
  do_dalliance_process(
    perform_method: self.class.dalliance_options[:dalliance_method],
    background_processing: background_processing
  )
end

#dalliance_progressObject



318
319
320
321
322
323
324
325
326
327
328
# File 'lib/dalliance.rb', line 318

def dalliance_progress
  if completed?
    100
  else
    if self.class.dalliance_options[:dalliance_progress_meter] && dalliance_progress_meter
      dalliance_progress_meter.progress
    else
      0
    end
  end
end

#dalliance_reprocess(background_processing = false) ⇒ Object



251
252
253
254
# File 'lib/dalliance.rb', line 251

def dalliance_reprocess(background_processing = false)
  reprocess_dalliance!
  do_dalliance_reprocess(background_processing)
end

#do_dalliance_process(perform_method:, background_processing: false) ⇒ Object



256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
# File 'lib/dalliance.rb', line 256

def do_dalliance_process(perform_method:, background_processing: false)
  start_time = Time.now

  begin
    start_dalliance!

    if self.class.dalliance_options[:dalliance_progress_meter]
      build_dalliance_progress_meter(:total_count => calculate_dalliance_progress_meter_total_count).save!
    end

    self.send(perform_method)

    finish_dalliance! unless validation_error?
  rescue StandardError => e
    #Save the error for future analysis...
    self.dalliance_error_hash = {:error => e.class.name, :message => e.message, :backtrace => e.backtrace}

    begin
      error_dalliance!
    rescue
      begin
        self.dalliance_status = 'processing_error'

        dalliance_log("[dalliance] #{self.class.name}(#{id}) - #{dalliance_status} #{dalliance_error_hash}")

        self.dalliance_error_hash = { error: 'Persistance Failure: See Logs' }

        if defined?(Rails) && ::Rails::VERSION::MAJOR > 3
          self.class.where(id: self.id).update_all(dalliance_status: dalliance_status, dalliance_error_hash: dalliance_error_hash )
        else
          self.class.where(id: self.id).update_all(dalliance_status: dalliance_status, dalliance_error_hash: dalliance_error_hash.to_yaml )
        end
      # rubocop:disable Lint/SuppressedException
      rescue
      # rubocop:enable Lint/SuppressedException
      end
    end

    error_notifier.call(e)

    # Don't raise the error if we're background processing...
    raise e unless background_processing && self.class.dalliance_options[:worker_class].rescue_error?
  ensure
    if self.class.dalliance_options[:dalliance_progress_meter] && dalliance_progress_meter
      #Works with optimistic locking...
      Dalliance::ProgressMeter.delete(dalliance_progress_meter.id)
      self.dalliance_progress_meter = nil
    end

    duration = Time.now - start_time

    dalliance_log("[dalliance] #{self.class.name}(#{id}) - #{dalliance_status} #{duration.to_i}")

    duration_column = self.class.dalliance_options[:duration_column]
    if duration_column.present?
      current_duration = self.send(duration_column) || 0
      self.class.where(id: self.id)
        .update_all(duration_column => current_duration + duration.to_f)
    end
  end
end

#error_notifierObject



189
190
191
# File 'lib/dalliance.rb', line 189

def error_notifier
  self.dalliance_options[:error_notifier]
end

#error_or_completed?Boolean

Returns:

  • (Boolean)


193
194
195
# File 'lib/dalliance.rb', line 193

def error_or_completed?
  validation_error? || processing_error? || completed?
end

#pending_or_processing?Boolean

Returns:

  • (Boolean)


210
211
212
# File 'lib/dalliance.rb', line 210

def pending_or_processing?
  pending? || processing?
end

#processing_queueObject



214
215
216
217
218
219
220
# File 'lib/dalliance.rb', line 214

def processing_queue
  if self.class.dalliance_options[:queue].respond_to?(:call)
    self.class.instance_exec self, &dalliance_options[:queue]
  else
    self.class.dalliance_options[:queue]
  end
end

#store_dalliance_validation_error!Object



159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
# File 'lib/dalliance.rb', line 159

def store_dalliance_validation_error!
  self.dalliance_error_hash = {}

  self.errors.each do |attribute, error|
    self.dalliance_error_hash[attribute] ||= []
    self.dalliance_error_hash[attribute] << error
  end

  begin
    validation_error_dalliance!
  rescue
    begin
      self.dalliance_status = 'validation_error'

      dalliance_log("[dalliance] #{self.class.name}(#{id}) - #{dalliance_status} #{self.dalliance_error_hash}")

      self.dalliance_error_hash = { error: 'Persistance Failure: See Logs' }

      if defined?(Rails) && ::Rails::VERSION::MAJOR > 3
        self.class.where(id: self.id).update_all(dalliance_status: dalliance_status, dalliance_error_hash: dalliance_error_hash )
      else
        self.class.where(id: self.id).update_all(dalliance_status: dalliance_status, dalliance_error_hash: dalliance_error_hash.to_yaml )
      end
    # rubocop:disable Lint/SuppressedException
    rescue
    # rubocop:enable Lint/SuppressedException
    end
  end
end

#validate_dalliance_statusObject



197
198
199
200
201
202
203
204
205
206
207
208
# File 'lib/dalliance.rb', line 197

def validate_dalliance_status
  unless error_or_completed?
    errors.add(:dalliance_status, :invalid)
    if defined?(Rails)
      throw(:abort)
    else
      return false
    end
  end

  true
end