Class: Foobara::Persistence::EntityBase
- Inherits:
-
Object
- Object
- Foobara::Persistence::EntityBase
- Defined in:
- foobara-0.1.7/projects/persistence/src/entity_base.rb,
foobara-0.1.7/projects/persistence/src/entity_base/table.rb,
foobara-0.1.7/projects/persistence/src/entity_base/transaction.rb,
foobara-0.1.7/projects/persistence/src/entity_base/transaction_table.rb,
foobara-0.1.7/projects/persistence/src/entity_base/transaction/state_machine.rb,
foobara-0.1.7/projects/persistence/src/entity_base/transaction_table/concerns/queries.rb,
foobara-0.1.7/projects/persistence/src/entity_base/transaction/concerns/state_transitions.rb,
foobara-0.1.7/projects/persistence/src/entity_base/transaction/concerns/transaction_tracking.rb,
foobara-0.1.7/projects/persistence/src/entity_base/transaction_table/concerns/record_tracking.rb,
foobara-0.1.7/projects/persistence/src/entity_base/transaction/concerns/entity_callback_handling.rb
Defined Under Namespace
Classes: Table, Transaction, TransactionTable
Constant Summary collapse
- VALID_MODES =
What types of transaction scenarios are there?
-
If a transaction is already open, use it as a “nested transaction”, otherwise, open a new one. A nested transaction means that “rollback” is the same as “revert” and “commit” is the same as “flush”. For a true
-
If a transaction is already open, raise an error. otherwise, open a new one.
-
Open a new, independent transaction, no matter what.
-
If a transaction is already open, use it, otherwise, open a new one.
-
We are outside of a transaction but have a handle on one. We want to set it as the current transaction. and do some work in that transaction.
Which use cases do we probably need at the moment?
-
If we are running a command calling other commands, we will open transactions when needed but inherit any already-open transactions. Commands don’t commit or flush to the already-open transactions that they inherit. So this feels like a “use existing” situation or a situation where we don’t even bother calling open_transaction at all. This is the most important use-case. It can be helpful to raise in this situation because it is not expected that there’s an existing transaction yet we’re opening another.
-
We might have a situation where we are in one transaction but definitely want to open a new one and commit it ourselves and have its results committed and visible independent of the current transaction. So this feels like a “open new” situation where we don’t want to raise an error if a transaction is already open.
-
[ :use_existing, :open_nested, :open_new, nil ].freeze
Instance Attribute Summary collapse
-
#entity_attributes_crud_driver ⇒ Object
Returns the value of attribute entity_attributes_crud_driver.
-
#name ⇒ Object
Returns the value of attribute name.
-
#tables ⇒ Object
Returns the value of attribute tables.
Class Method Summary collapse
- .order_entity_classes(entity_classes) ⇒ Object
- .using_transactions(existing_transactions, &block) ⇒ Object
Instance Method Summary collapse
- #current_transaction ⇒ Object
-
#initialize(name, entity_attributes_crud_driver:) ⇒ EntityBase
constructor
A new instance of EntityBase.
- #register_entity_class(entity_class, table_name: entity_class.full_entity_name) ⇒ Object
- #register_table(table) ⇒ Object
- #set_current_transaction(transaction) ⇒ Object
- #transaction(mode = nil, existing_transaction: nil) ⇒ Object
- #transaction_key ⇒ Object
- #using_transaction(existing_transaction) ⇒ Object
Constructor Details
#initialize(name, entity_attributes_crud_driver:) ⇒ EntityBase
Returns a new instance of EntityBase.
65 66 67 68 69 70 |
# File 'foobara-0.1.7/projects/persistence/src/entity_base.rb', line 65 def initialize(name, entity_attributes_crud_driver:) self.entity_attributes_crud_driver = entity_attributes_crud_driver self.tables = {} self.name = name # TODO: a smell? end |
Instance Attribute Details
#entity_attributes_crud_driver ⇒ Object
Returns the value of attribute entity_attributes_crud_driver.
6 7 8 |
# File 'foobara-0.1.7/projects/persistence/src/entity_base.rb', line 6 def entity_attributes_crud_driver @entity_attributes_crud_driver end |
#name ⇒ Object
Returns the value of attribute name.
6 7 8 |
# File 'foobara-0.1.7/projects/persistence/src/entity_base.rb', line 6 def name @name end |
#tables ⇒ Object
Returns the value of attribute tables.
6 7 8 |
# File 'foobara-0.1.7/projects/persistence/src/entity_base.rb', line 6 def tables @tables end |
Class Method Details
.order_entity_classes(entity_classes) ⇒ Object
25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 |
# File 'foobara-0.1.7/projects/persistence/src/entity_base.rb', line 25 def order_entity_classes(entity_classes) return entity_classes if entity_classes.size <= 1 without_associations, with_associations = entity_classes.partition do |entity_class| entity_class.associations.empty? end if with_associations.size > 1 i = 0 end_at = with_associations.size - 1 while i < end_at entity_class = with_associations[i] associations = entity_class.associations.values.uniq changed = false j = i + 1 while j <= end_at other = with_associations[j] if associations.include?(other.) with_associations[j] = entity_class with_associations[i] = other changed = true break end j += 1 end i += 1 unless changed end end without_associations + with_associations end |
.using_transactions(existing_transactions, &block) ⇒ Object
9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 |
# File 'foobara-0.1.7/projects/persistence/src/entity_base.rb', line 9 def using_transactions(existing_transactions, &block) if existing_transactions.empty? block.call elsif existing_transactions.size == 1 existing_transaction = existing_transactions.first existing_transaction.entity_base.using_transaction(existing_transaction, &block) else existing_transactions.inject(block) do |nested_proc, existing_transaction| proc do existing_transaction.entity_base.using_transaction(existing_transaction, &nested_proc) end end.call end end |
Instance Method Details
#current_transaction ⇒ Object
86 87 88 |
# File 'foobara-0.1.7/projects/persistence/src/entity_base.rb', line 86 def current_transaction Thread.inheritable_thread_local_var_get(transaction_key) end |
#register_entity_class(entity_class, table_name: entity_class.full_entity_name) ⇒ Object
72 73 74 75 76 |
# File 'foobara-0.1.7/projects/persistence/src/entity_base.rb', line 72 def register_entity_class(entity_class, table_name: entity_class.full_entity_name) table = EntityBase::Table.new(table_name, self) register_table(table) end |
#register_table(table) ⇒ Object
78 79 80 |
# File 'foobara-0.1.7/projects/persistence/src/entity_base.rb', line 78 def register_table(table) tables[table.table_name] = table end |
#set_current_transaction(transaction) ⇒ Object
90 91 92 |
# File 'foobara-0.1.7/projects/persistence/src/entity_base.rb', line 90 def set_current_transaction(transaction) Thread.inheritable_thread_local_var_set(transaction_key, transaction) end |
#transaction(mode = nil, existing_transaction: nil) ⇒ Object
124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 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 188 189 190 191 192 193 194 195 196 197 |
# File 'foobara-0.1.7/projects/persistence/src/entity_base.rb', line 124 def transaction(mode = nil, existing_transaction: nil) unless VALID_MODES.include?(mode) # :nocov: raise ArgumentError, "Mode was #{mode} but expected one of #{VALID_MODES}" # :nocov: end old_transaction = current_transaction if old_transaction && !old_transaction.currently_open? old_transaction = nil end open_nested = false if old_transaction if mode == :use_existing || existing_transaction == old_transaction if block_given? return yield old_transaction else return old_transaction end elsif mode == :open_nested open_nested = true elsif mode == :open_new if existing_transaction # :nocov: raise ArgumentError, "Cannot use mode :open_new with existing_transaction:" # :nocov: end else # :nocov: raise "Transaction already open. " \ "Use mode :use_existing if you want to make use of the existing transaction. " \ "Use mode :open_nested if you are actually trying to nest transactions." # :nocov: end end unless block_given? return existing_transaction || Transaction.new(self) end begin if existing_transaction tx = existing_transaction else tx = Transaction.new(self) if open_nested tx.open_nested!(old_transaction) else tx.open! end end set_current_transaction(tx) result = yield tx if tx.currently_open? && !existing_transaction tx.commit! end result rescue Foobara::Persistence::EntityBase::Transaction::RolledBack # rubocop:disable Lint/SuppressedException rescue => e if tx.currently_open? tx.rollback!(e) end raise ensure set_current_transaction(old_transaction) end end |
#transaction_key ⇒ Object
82 83 84 |
# File 'foobara-0.1.7/projects/persistence/src/entity_base.rb', line 82 def transaction_key @transaction_key ||= "foobara:tx:#{name}" end |
#using_transaction(existing_transaction) ⇒ Object
120 121 122 |
# File 'foobara-0.1.7/projects/persistence/src/entity_base.rb', line 120 def using_transaction(existing_transaction, &) transaction(existing_transaction:, &) end |