Class: ActiveRecord::ConnectionAdapters::TransactionManager
- Defined in:
- activerecord/lib/active_record/connection_adapters/abstract/transaction.rb
Overview
:nodoc:
Instance Method Summary collapse
- #begin_transaction(isolation: nil, joinable: true, _lazy: true) ⇒ Object
- #commit_transaction ⇒ Object
- #current_transaction ⇒ Object
- #dirty_current_transaction ⇒ Object
- #disable_lazy_transactions! ⇒ Object
- #enable_lazy_transactions! ⇒ Object
-
#initialize(connection) ⇒ TransactionManager
constructor
A new instance of TransactionManager.
- #lazy_transactions_enabled? ⇒ Boolean
- #materialize_transactions ⇒ Object
- #open_transactions ⇒ Object
- #restorable? ⇒ Boolean
- #restore_transactions ⇒ Object
- #rollback_transaction(transaction = nil) ⇒ Object
- #within_new_transaction(isolation: nil, joinable: true) ⇒ Object
Constructor Details
#initialize(connection) ⇒ TransactionManager
Returns a new instance of TransactionManager.
291 292 293 294 295 296 297 |
# File 'activerecord/lib/active_record/connection_adapters/abstract/transaction.rb', line 291 def initialize(connection) @stack = [] @connection = connection @has_unmaterialized_transactions = false @materializing_transactions = false @lazy_transactions_enabled = true end |
Instance Method Details
#begin_transaction(isolation: nil, joinable: true, _lazy: true) ⇒ Object
299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 |
# File 'activerecord/lib/active_record/connection_adapters/abstract/transaction.rb', line 299 def begin_transaction(isolation: nil, joinable: true, _lazy: true) @connection.lock.synchronize do run_commit_callbacks = !current_transaction.joinable? transaction = if @stack.empty? RealTransaction.new( @connection, isolation: isolation, joinable: joinable, run_commit_callbacks: run_commit_callbacks ) elsif current_transaction.restartable? RestartParentTransaction.new( @connection, current_transaction, isolation: isolation, joinable: joinable, run_commit_callbacks: run_commit_callbacks ) else SavepointTransaction.new( @connection, "active_record_#{@stack.size}", current_transaction, isolation: isolation, joinable: joinable, run_commit_callbacks: run_commit_callbacks ) end unless transaction.materialized? if @connection.supports_lazy_transactions? && lazy_transactions_enabled? && _lazy @has_unmaterialized_transactions = true else transaction.materialize! end end @stack.push(transaction) transaction end end |
#commit_transaction ⇒ Object
395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 |
# File 'activerecord/lib/active_record/connection_adapters/abstract/transaction.rb', line 395 def commit_transaction @connection.lock.synchronize do transaction = @stack.last begin transaction.before_commit_records ensure @stack.pop end dirty_current_transaction if transaction.dirty? if current_transaction.open? current_transaction.written_indirectly ||= transaction.written || transaction.written_indirectly end transaction.commit transaction.commit_records end end |
#current_transaction ⇒ Object
488 489 490 |
# File 'activerecord/lib/active_record/connection_adapters/abstract/transaction.rb', line 488 def current_transaction @stack.last || NULL_TRANSACTION end |
#dirty_current_transaction ⇒ Object
354 355 356 |
# File 'activerecord/lib/active_record/connection_adapters/abstract/transaction.rb', line 354 def dirty_current_transaction current_transaction.dirty! end |
#disable_lazy_transactions! ⇒ Object
341 342 343 344 |
# File 'activerecord/lib/active_record/connection_adapters/abstract/transaction.rb', line 341 def disable_lazy_transactions! materialize_transactions @lazy_transactions_enabled = false end |
#enable_lazy_transactions! ⇒ Object
346 347 348 |
# File 'activerecord/lib/active_record/connection_adapters/abstract/transaction.rb', line 346 def enable_lazy_transactions! @lazy_transactions_enabled = true end |
#lazy_transactions_enabled? ⇒ Boolean
350 351 352 |
# File 'activerecord/lib/active_record/connection_adapters/abstract/transaction.rb', line 350 def lazy_transactions_enabled? @lazy_transactions_enabled end |
#materialize_transactions ⇒ Object
372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 |
# File 'activerecord/lib/active_record/connection_adapters/abstract/transaction.rb', line 372 def materialize_transactions return if @materializing_transactions # As a logical simplification for now, we assume anything that requests # materialization is about to dirty the transaction. Note this is just # an assumption about the caller, not a direct property of this method. # It can go away later when callers are able to handle dirtiness for # themselves. dirty_current_transaction return unless @has_unmaterialized_transactions @connection.lock.synchronize do begin @materializing_transactions = true @stack.each { |t| t.materialize! unless t.materialized? } ensure @materializing_transactions = false end @has_unmaterialized_transactions = false end end |
#open_transactions ⇒ Object
484 485 486 |
# File 'activerecord/lib/active_record/connection_adapters/abstract/transaction.rb', line 484 def open_transactions @stack.size end |
#restorable? ⇒ Boolean
368 369 370 |
# File 'activerecord/lib/active_record/connection_adapters/abstract/transaction.rb', line 368 def restorable? @stack.none?(&:dirty?) end |
#restore_transactions ⇒ Object
358 359 360 361 362 363 364 365 366 |
# File 'activerecord/lib/active_record/connection_adapters/abstract/transaction.rb', line 358 def restore_transactions return false unless restorable? @stack.each(&:restore!) materialize_transactions unless @lazy_transactions_enabled true end |
#rollback_transaction(transaction = nil) ⇒ Object
416 417 418 419 420 421 422 |
# File 'activerecord/lib/active_record/connection_adapters/abstract/transaction.rb', line 416 def rollback_transaction(transaction = nil) @connection.lock.synchronize do transaction ||= @stack.pop transaction.rollback transaction.rollback_records end end |
#within_new_transaction(isolation: nil, joinable: true) ⇒ Object
424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 |
# File 'activerecord/lib/active_record/connection_adapters/abstract/transaction.rb', line 424 def within_new_transaction(isolation: nil, joinable: true) @connection.lock.synchronize do transaction = begin_transaction(isolation: isolation, joinable: joinable) ret = yield completed = true ret rescue Exception => error if transaction if error.is_a?(ActiveRecord::TransactionRollbackError) && @connection.savepoint_errors_invalidate_transactions? transaction.state.invalidate! end rollback_transaction after_failure_actions(transaction, error) end raise ensure if transaction if error # @connection still holds an open or invalid transaction, so we must not # put it back in the pool for reuse. @connection.throw_away! unless transaction.state.rolledback? else if Thread.current.status == "aborting" rollback_transaction elsif !completed && transaction.written # This was deprecated in 6.1, and has now changed to a rollback rollback_transaction elsif !completed && !transaction.written_indirectly # This was a silent commit in 6.1, but now becomes a rollback; we skipped # the warning because (having not been written) the change generally won't # have any effect rollback_transaction else if !completed && transaction.written_indirectly # This is the case that was missed in the 6.1 deprecation, so we have to # do it now ActiveSupport::Deprecation.warn(<<~EOW) Using `return`, `break` or `throw` to exit a transaction block is deprecated without replacement. If the `throw` came from `Timeout.timeout(duration)`, pass an exception class as a second argument so it doesn't use `throw` to abort its block. This results in the transaction being committed, but in the next release of Rails it will rollback. EOW end begin commit_transaction rescue Exception rollback_transaction(transaction) unless transaction.state.completed? raise end end end end end end |