Class: ActiveRecord::ConnectionAdapters::TransactionManager

Inherits:
Object
  • Object
show all
Defined in:
lib/active_record/connection_adapters/abstract/transaction.rb

Overview

:nodoc:

Instance Method Summary collapse

Constructor Details

#initialize(connection) ⇒ TransactionManager

Returns a new instance of TransactionManager.



519
520
521
522
523
524
525
# File 'lib/active_record/connection_adapters/abstract/transaction.rb', line 519

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



527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
# File 'lib/active_record/connection_adapters/abstract/transaction.rb', line 527

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_transactionObject



614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
# File 'lib/active_record/connection_adapters/abstract/transaction.rb', line 614

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?

    transaction.commit
    transaction.commit_records
  end
end

#current_transactionObject



683
684
685
# File 'lib/active_record/connection_adapters/abstract/transaction.rb', line 683

def current_transaction
  @stack.last || NULL_TRANSACTION
end

#dirty_current_transactionObject



582
583
584
# File 'lib/active_record/connection_adapters/abstract/transaction.rb', line 582

def dirty_current_transaction
  current_transaction.dirty!
end

#disable_lazy_transactions!Object



569
570
571
572
# File 'lib/active_record/connection_adapters/abstract/transaction.rb', line 569

def disable_lazy_transactions!
  materialize_transactions
  @lazy_transactions_enabled = false
end

#enable_lazy_transactions!Object



574
575
576
# File 'lib/active_record/connection_adapters/abstract/transaction.rb', line 574

def enable_lazy_transactions!
  @lazy_transactions_enabled = true
end

#lazy_transactions_enabled?Boolean

Returns:

  • (Boolean)


578
579
580
# File 'lib/active_record/connection_adapters/abstract/transaction.rb', line 578

def lazy_transactions_enabled?
  @lazy_transactions_enabled
end

#materialize_transactionsObject



598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
# File 'lib/active_record/connection_adapters/abstract/transaction.rb', line 598

def materialize_transactions
  return if @materializing_transactions

  if @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
end

#open_transactionsObject



679
680
681
# File 'lib/active_record/connection_adapters/abstract/transaction.rb', line 679

def open_transactions
  @stack.size
end

#restorable?Boolean

Returns:

  • (Boolean)


594
595
596
# File 'lib/active_record/connection_adapters/abstract/transaction.rb', line 594

def restorable?
  @stack.none?(&:dirty?)
end

#restore_transactionsObject



586
587
588
589
590
591
592
# File 'lib/active_record/connection_adapters/abstract/transaction.rb', line 586

def restore_transactions
  return false unless restorable?

  @stack.each(&:restore!)

  true
end

#rollback_transaction(transaction = nil) ⇒ Object



631
632
633
634
635
636
637
638
639
640
641
# File 'lib/active_record/connection_adapters/abstract/transaction.rb', line 631

def rollback_transaction(transaction = nil)
  @connection.lock.synchronize do
    transaction ||= @stack.last
    begin
      transaction.rollback
    ensure
      @stack.pop if @stack.last == transaction
    end
    transaction.rollback_records
  end
end

#within_new_transaction(isolation: nil, joinable: true) ⇒ Object



643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
# File 'lib/active_record/connection_adapters/abstract/transaction.rb', line 643

def within_new_transaction(isolation: nil, joinable: true)
  isolation ||= @connection.pool.pool_transaction_isolation_level
  @connection.lock.synchronize do
    transaction = begin_transaction(isolation: isolation, joinable: joinable)
    begin
      yield transaction.user_transaction
    rescue Exception => error
      rollback_transaction
      after_failure_actions(transaction, error)

      raise
    ensure
      unless error
        if Thread.current.status == "aborting"
          rollback_transaction
        else
          begin
            commit_transaction
          rescue ActiveRecord::ConnectionFailed
            transaction.invalidate! unless transaction.state.completed?
            raise
          rescue Exception
            rollback_transaction(transaction) unless transaction.state.completed?
            raise
          end
        end
      end
    end
  ensure
    unless transaction&.state&.completed?
      @connection.throw_away!
      transaction&.incomplete!
    end
  end
end