Module: Foobara::NestedTransactionable

Includes:
Concern
Included in:
CommandConnector::Request, CommandPatternImplementation::Concerns::Transactions
Defined in:
foobara-0.0.130/projects/nested_transactionable/lib/foobara/nested_transactionable.rb

Class Method Summary collapse

Instance Method Summary collapse

Methods included from Concern

foobara_class_methods_module_for, foobara_concern?, included

Class Method Details

.relevant_entity_classes_for_type(type) ⇒ Object



6
7
8
9
10
11
12
13
14
15
16
17
18
19
# File 'foobara-0.0.130/projects/nested_transactionable/lib/foobara/nested_transactionable.rb', line 6

def relevant_entity_classes_for_type(type)
  entity_classes = []
  entity_classes += Entity.construct_associations(type).values.map(&:target_class)

  if type.extends?(BuiltinTypes[:entity])
    entity_classes << type.target_class
  end

  entity_classes.uniq.each do |entity_class|
    entity_classes += entity_class.deep_associations.values.map(&:target_class)
  end

  entity_classes.uniq
end

.with_needed_transactions_for_type(type) ⇒ Object



21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
# File 'foobara-0.0.130/projects/nested_transactionable/lib/foobara/nested_transactionable.rb', line 21

def with_needed_transactions_for_type(type, &)
  relevant_entity_classes = relevant_entity_classes_for_type(type)

  if relevant_entity_classes.empty?
    return yield
  end

  tx_class = Class.new
  tx_class.include NestedTransactionable

  tx_class.define_method(:relevant_entity_classes) do
    relevant_entity_classes
  end

  tx_instance = tx_class.new

  begin
    tx_instance.open_transaction
    result = Persistence::EntityBase.using_transactions(tx_instance.transactions, &)
    tx_instance.commit_transaction
    result
  rescue
    tx_instance.rollback_transaction
    raise
  end
end

Instance Method Details

#auto_detect_current_transactionsObject



67
68
69
70
71
72
73
74
75
76
77
78
79
80
# File 'foobara-0.0.130/projects/nested_transactionable/lib/foobara/nested_transactionable.rb', line 67

def auto_detect_current_transactions
  classes = relevant_entity_classes
  return if classes.nil? || classes.empty?

  bases = classes.map(&:entity_base).uniq

  bases.each do |base|
    tx = base.current_transaction

    if tx&.open?
      transactions << tx
    end
  end
end

#commit_transactionObject



109
110
111
# File 'foobara-0.0.130/projects/nested_transactionable/lib/foobara/nested_transactionable.rb', line 109

def commit_transaction
  opened_transactions.reverse.each(&:commit!)
end

#commit_transaction_if_openObject



113
114
115
116
117
118
119
# File 'foobara-0.0.130/projects/nested_transactionable/lib/foobara/nested_transactionable.rb', line 113

def commit_transaction_if_open
  opened_transactions.reverse.each do |tx|
    if tx.currently_open?
      tx.commit!
    end
  end
end

#open_transactionObject



82
83
84
85
86
87
88
89
90
91
92
93
94
95
# File 'foobara-0.0.130/projects/nested_transactionable/lib/foobara/nested_transactionable.rb', line 82

def open_transaction
  auto_detect_current_transactions

  bases_not_needing_transaction = transactions.map(&:entity_base)

  bases_needing_transaction = relevant_entity_classes.map(&:entity_base).uniq - bases_not_needing_transaction

  bases_needing_transaction.each do |entity_base|
    transaction = entity_base.transaction
    transaction.open!
    opened_transactions << transaction
    transactions << transaction
  end
end

#opened_transactionsObject



63
64
65
# File 'foobara-0.0.130/projects/nested_transactionable/lib/foobara/nested_transactionable.rb', line 63

def opened_transactions
  @opened_transactions ||= []
end

#relevant_entity_classesObject



53
54
55
56
57
# File 'foobara-0.0.130/projects/nested_transactionable/lib/foobara/nested_transactionable.rb', line 53

def relevant_entity_classes
  # :nocov:
  raise "subclass responsibility"
  # :nocov:
end

#relevant_entity_classes_for_type(type) ⇒ Object



49
50
51
# File 'foobara-0.0.130/projects/nested_transactionable/lib/foobara/nested_transactionable.rb', line 49

def relevant_entity_classes_for_type(type)
  NestedTransactionable.relevant_entity_classes_for_type(type)
end

#rollback_transactionObject



97
98
99
100
101
102
103
104
105
106
107
# File 'foobara-0.0.130/projects/nested_transactionable/lib/foobara/nested_transactionable.rb', line 97

def rollback_transaction
  opened_transactions.reverse.each do |transaction|
    if transaction.currently_open?
      # Hard to test this because halting and other exceptions rollback the transactions via
      # block form but to be safe keeping this
      # :nocov:
      transaction.rollback!
      # :nocov:
    end
  end
end

#transactionsObject



59
60
61
# File 'foobara-0.0.130/projects/nested_transactionable/lib/foobara/nested_transactionable.rb', line 59

def transactions
  @transactions ||= []
end

#use_transactionObject



121
122
123
# File 'foobara-0.0.130/projects/nested_transactionable/lib/foobara/nested_transactionable.rb', line 121

def use_transaction(&)
  Persistence::EntityBase.using_transactions(transactions, &)
end