class ESA::BlockingProcessor

Public Class Methods

create_and_process_events(accountable) click to toggle source
# File lib/esa/blocking_processor.rb, line 19
def self.create_and_process_events(accountable)
  events_created = create_events(accountable)

  if events_created
    unprocessed_events(accountable).each do |event|
      event.processed = process_event(event)
      event.save if event.changed?

      # do not process later events if one fails
      return false if not event.processed
    end

    true
  else
    false
  end
end
create_events(accountable) click to toggle source
# File lib/esa/blocking_processor.rb, line 43
def self.create_events(accountable)
  produce_events(accountable).map(&:save).all?
end
create_flags(event) click to toggle source
# File lib/esa/blocking_processor.rb, line 106
def self.create_flags(event)
  if not event.processed and not event.processed_was
    produce_flags(event).map(&:save).all?
  else
    true
  end
end
create_transactions(flag) click to toggle source
# File lib/esa/blocking_processor.rb, line 176
def self.create_transactions(flag)
  if not flag.processed and not flag.processed_was
    if flag.transition.present? and flag.transition.in? [-1, 0, 1]
      produce_transactions(flag).map(&:save).all?
    else
      false
    end
  else
    true
  end
end
enqueue(accountable) click to toggle source
# File lib/esa/blocking_processor.rb, line 3
def self.enqueue(accountable)
  if accountable.present? and accountable.class.ancestors.include? ESA::Traits::Accountable
    process_accountable(accountable)
  end
end
event_attrs_with_adjustment(ruleset, accountable, events) click to toggle source
# File lib/esa/blocking_processor.rb, line 59
def self.event_attrs_with_adjustment(ruleset, accountable, events)
  if ruleset.is_adjustment_event_needed?(accountable)
    events.unshift({
      accountable: accountable,
      ruleset: ruleset,
      nature: :adjustment,
      time: [events.map{|e| e[:time]}.min, Time.zone.now].compact.min,
    })
  else
    events
  end
end
initialize_adjustment_flag(event, flag) click to toggle source
# File lib/esa/blocking_processor.rb, line 140
def self.initialize_adjustment_flag(event, flag)
  attrs = {
    :accountable => event.accountable,
    :nature => flag.nature,
    :state => flag.state,
    :event => event,
  }

  event.accountable.esa_flags.new(attrs)
end
missing_transactions(flag) click to toggle source
# File lib/esa/blocking_processor.rb, line 194
def self.missing_transactions(flag)
  if flag.ruleset.present? and flag.transition.present? and flag.transition.in? [-1, 0, 1]
    existing = flag.transactions.all
    required = flag.ruleset.flag_transactions_as_attributes(flag)

    required.reject do |attrs|
      existing.find{|tx| tx.matches_spec?(attrs)}.present?
    end
  else
    []
  end
end
process_accountable(accountable) click to toggle source
# File lib/esa/blocking_processor.rb, line 9
def self.process_accountable(accountable)
  processed = create_and_process_events(accountable)

  state = ESA::State.where(accountable_id: accountable.id, accountable_type: accountable.class).first_or_create
  state.processed_at = Time.now
  state.unprocessed = processed ? 0 : accountable.esa_events.where(processed: false).count

  state.save
end
process_event(event) click to toggle source
# File lib/esa/blocking_processor.rb, line 72
def self.process_event(event)
  flags_created = create_flags(event)

  if flags_created
    unprocessed_flags(event).map do |flag|
      flag.processed = process_flag(flag)

      if flag.changed?
        flag.save and flag.processed
      else
        flag.processed
      end
    end.all?
  else
    false
  end
end
process_flag(flag) click to toggle source
# File lib/esa/blocking_processor.rb, line 171
def self.process_flag(flag)
  flag.transition ||= flag.accountable.esa_flags.transition_for(flag)
  create_transactions(flag)
end
produce_events(accountable) click to toggle source
# File lib/esa/blocking_processor.rb, line 47
def self.produce_events(accountable)
  ruleset = Ruleset.extension_instance(accountable)

  if ruleset.present?
    events = ruleset.addable_unrecorded_events_as_attributes(accountable)
    adjusted_events = event_attrs_with_adjustment(ruleset, accountable, events)
    accountable.esa_events.new(adjusted_events)
  else
    []
  end
end
produce_flags(event) click to toggle source
# File lib/esa/blocking_processor.rb, line 114
def self.produce_flags(event)
  if event.nature.adjustment?
    produce_flags_for_adjustment(event)
  else
    produce_flags_for_regular(event)
  end
end
produce_flags_for_adjustment(event) click to toggle source
# File lib/esa/blocking_processor.rb, line 122
def self.produce_flags_for_adjustment(event)
  if event.ruleset.present?
    adjusted_flags = event.ruleset.flags_needing_adjustment(event.accountable)
    adjusted_flags.map do |flag|
      flag.processed = false
      flag.adjusted = true
      flag.adjustment_time = event.time

      adjustment = initialize_adjustment_flag(event, flag)
      event.flags << adjustment

      [flag, adjustment]
    end.flatten
  else
    []
  end
end
produce_flags_for_regular(event) click to toggle source
# File lib/esa/blocking_processor.rb, line 151
def self.produce_flags_for_regular(event)
  if event.ruleset.present?
    existing_flags = event.flags.all
    required_flags = event.ruleset.event_flags_as_attributes(event)

    required_flags.map do |attrs|
      flag = existing_flags.find{|flag| flag.matches_spec?(attrs)}

      if flag.nil?
        flag = event.accountable.esa_flags.new(attrs)
        event.flags << flag
      end

      flag
    end
  else
    []
  end
end
produce_transactions(flag) click to toggle source
# File lib/esa/blocking_processor.rb, line 188
def self.produce_transactions(flag)
  txs = flag.accountable.esa_transactions.new(missing_transactions(flag))
  flag.transactions += txs
  txs
end
unprocessed_events(accountable) click to toggle source
# File lib/esa/blocking_processor.rb, line 37
def self.unprocessed_events(accountable)
  accountable.esa_events.
      where(processed: false).
      order(:time, :created_at, :id)
end
unprocessed_flags(event) click to toggle source
# File lib/esa/blocking_processor.rb, line 90
def self.unprocessed_flags(event)
  flags = []

  if event.nature.adjustment?
    flags += event.accountable.esa_flags.
        where(adjusted: true, processed: false).
        order(:time, :created_at, :id)
  end

  flags += event.flags.
      where(processed: false).
      order(:time, :created_at, :id)

  flags
end