Module: Foobara::NestedTransactionable

Includes:
Concern
Included in:
CommandConnector::Request, CommandPatternImplementation::Concerns::Transactions, TransactionGroup
Defined in:
foobara-0.2.2/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.2.2/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
# File 'foobara-0.2.2/projects/nested_transactionable/lib/foobara/nested_transactionable.rb', line 21

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

  if entity_classes.empty?
    return yield
  end

  TransactionGroup.run(entity_classes:, &)
end

Instance Method Details

#auto_detect_current_transactionsObject



51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
# File 'foobara-0.2.2/projects/nested_transactionable/lib/foobara/nested_transactionable.rb', line 51

def auto_detect_current_transactions
  bases = nil

  if respond_to?(:relevant_entity_bases)
    bases = relevant_entity_bases

    unless bases.nil?
      return if bases.empty?
    end
  end

  unless bases
    classes = relevant_entity_classes
    return if classes.nil? || classes.empty?

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

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

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

#commit_transactionObject



128
129
130
# File 'foobara-0.2.2/projects/nested_transactionable/lib/foobara/nested_transactionable.rb', line 128

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

#commit_transaction_if_openObject



132
133
134
135
136
137
138
# File 'foobara-0.2.2/projects/nested_transactionable/lib/foobara/nested_transactionable.rb', line 132

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

#open_transactionObject



78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
# File 'foobara-0.2.2/projects/nested_transactionable/lib/foobara/nested_transactionable.rb', line 78

def open_transaction
  auto_detect_current_transactions

  bases_not_needing_transaction = transactions.map(&:entity_base)

  bases_needing_transaction = nil

  if respond_to?(:relevant_entity_bases)
    bases_needing_transaction = relevant_entity_bases

    unless bases_needing_transaction.nil?
      return if bases_needing_transaction.empty?
    end
  end

  unless bases_needing_transaction
    classes = relevant_entity_classes
    return if classes.nil? || classes.empty?

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

  bases_needing_transaction = Persistence.sort_bases(bases_needing_transaction)

  bases_needing_transaction.each do |entity_base|
    transaction_mode = if respond_to?(:transaction_mode)
                         self.transaction_mode
                       end
    transaction = entity_base.transaction(transaction_mode)
    unless transaction.currently_open?
      transaction.open!
      @opened_transactions ||= []
      @opened_transactions << transaction
    end
    transactions << transaction
  end
end

#opened_transactionsObject



46
47
48
49
# File 'foobara-0.2.2/projects/nested_transactionable/lib/foobara/nested_transactionable.rb', line 46

def opened_transactions
  @opened_transactions ||= []
  Persistence.sort_transactions(@opened_transactions)
end

#relevant_entity_classesObject



36
37
38
39
40
# File 'foobara-0.2.2/projects/nested_transactionable/lib/foobara/nested_transactionable.rb', line 36

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

#relevant_entity_classes_for_type(type) ⇒ Object



32
33
34
# File 'foobara-0.2.2/projects/nested_transactionable/lib/foobara/nested_transactionable.rb', line 32

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

#rollback_transactionObject



116
117
118
119
120
121
122
123
124
125
126
# File 'foobara-0.2.2/projects/nested_transactionable/lib/foobara/nested_transactionable.rb', line 116

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



42
43
44
# File 'foobara-0.2.2/projects/nested_transactionable/lib/foobara/nested_transactionable.rb', line 42

def transactions
  @transactions ||= []
end

#use_transactionObject



140
141
142
# File 'foobara-0.2.2/projects/nested_transactionable/lib/foobara/nested_transactionable.rb', line 140

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