Class: Stepped::Performance

Inherits:
ActiveRecord::Base
  • Object
show all
Defined in:
app/models/stepped/performance.rb

Class Method Summary collapse

Instance Method Summary collapse

Class Method Details

.complete_action(action, status) ⇒ Object



29
30
31
32
33
# File 'app/models/stepped/performance.rb', line 29

def complete_action(action, status)
  transaction(requires_new: true) do
    lock.find_by(concurrency_key: action.concurrency_key)&.forward(action, status:)
  end
end

.obtain_for(action) ⇒ Object



12
13
14
15
16
17
18
19
# File 'app/models/stepped/performance.rb', line 12

def obtain_for(action)
  transaction(requires_new: true) do
    lock.
      create_with(action:).
      find_or_create_by!(concurrency_key: action.concurrency_key).
      share_with(action)
  end
end

.outbound_complete(actor, name, status = :succeeded) ⇒ Object



21
22
23
24
25
26
27
# File 'app/models/stepped/performance.rb', line 21

def outbound_complete(actor, name, status = :succeeded)
  outbound_complete_key = actor.stepped_action_tenancy_key name

  transaction(requires_new: true) do
    lock.find_by(outbound_complete_key:)&.forward(status:)
  end
end

Instance Method Details

#forward(completing_action = self.action, status: :succeeded) ⇒ Object



36
37
38
39
40
41
42
43
44
45
46
47
# File 'app/models/stepped/performance.rb', line 36

def forward(completing_action = self.action, status: :succeeded)
  completing_action.finalize_complete status

  return unless completing_action == action

  if next_action = actions.incomplete.first
    update!(action: next_action)
    next_action.perform if next_action.pending?
  else
    destroy!
  end
end

#share_with(candidate) ⇒ Object



49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
# File 'app/models/stepped/performance.rb', line 49

def share_with(candidate)
  # Secondary check of this kind here within a performance lock
  # prevents race conditions between the first check and obtaining the lock,
  # while the first check in Action#obtain_lock_and_perform speeds things up.
  Stepped::Achievement.raise_if_exists_for?(candidate)

  if candidate.descendant_of?(action)
    return candidate.tap(&:deadlock!)
  end

  if candidate.checksum.present?
    actions.excluding(candidate).each do |action|
      if action.achieves?(candidate)
        candidate.copy_parent_steps_to action
        return action
      end
    end
  end

  other_pending_actions.each { _1.supersede_with(candidate) }
  candidate.tap { _1.update_performance(self) }
end