Class: ActiveRecord::ConnectionAdapters::TransactionManager

Inherits:
Object
  • Object
show all
Defined in:
activerecord/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.


201
202
203
204
205
206
207
# File 'activerecord/lib/active_record/connection_adapters/abstract/transaction.rb', line 201

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


209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
# File 'activerecord/lib/active_record/connection_adapters/abstract/transaction.rb', line 209

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
        )
      else
        SavepointTransaction.new(
          @connection,
          "active_record_#{@stack.size}",
          @stack.last,
          isolation: isolation,
          joinable: joinable,
          run_commit_callbacks: run_commit_callbacks
        )
      end

    if @connection.supports_lazy_transactions? && lazy_transactions_enabled? && _lazy
      @has_unmaterialized_transactions = true
    else
      transaction.materialize!
    end
    @stack.push(transaction)
    transaction
  end
end

#commit_transactionObject


269
270
271
272
273
274
275
276
277
278
279
280
281
282
# File 'activerecord/lib/active_record/connection_adapters/abstract/transaction.rb', line 269

def commit_transaction
  @connection.lock.synchronize do
    transaction = @stack.last

    begin
      transaction.before_commit_records
    ensure
      @stack.pop
    end

    transaction.commit
    transaction.commit_records
  end
end

#current_transactionObject


334
335
336
# File 'activerecord/lib/active_record/connection_adapters/abstract/transaction.rb', line 334

def current_transaction
  @stack.last || NULL_TRANSACTION
end

#disable_lazy_transactions!Object


241
242
243
244
# File 'activerecord/lib/active_record/connection_adapters/abstract/transaction.rb', line 241

def disable_lazy_transactions!
  materialize_transactions
  @lazy_transactions_enabled = false
end

#enable_lazy_transactions!Object


246
247
248
# File 'activerecord/lib/active_record/connection_adapters/abstract/transaction.rb', line 246

def enable_lazy_transactions!
  @lazy_transactions_enabled = true
end

#lazy_transactions_enabled?Boolean

Returns:

  • (Boolean)

250
251
252
# File 'activerecord/lib/active_record/connection_adapters/abstract/transaction.rb', line 250

def lazy_transactions_enabled?
  @lazy_transactions_enabled
end

#materialize_transactionsObject


254
255
256
257
258
259
260
261
262
263
264
265
266
267
# File 'activerecord/lib/active_record/connection_adapters/abstract/transaction.rb', line 254

def materialize_transactions
  return if @materializing_transactions
  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_transactionsObject


330
331
332
# File 'activerecord/lib/active_record/connection_adapters/abstract/transaction.rb', line 330

def open_transactions
  @stack.size
end

#rollback_transaction(transaction = nil) ⇒ Object


284
285
286
287
288
289
290
# File 'activerecord/lib/active_record/connection_adapters/abstract/transaction.rb', line 284

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


292
293
294
295
296
297
298
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
# File 'activerecord/lib/active_record/connection_adapters/abstract/transaction.rb', line 292

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
      rollback_transaction
      after_failure_actions(transaction, error)
    end
    raise
  ensure
    if !error && transaction
      if Thread.current.status == "aborting"
        rollback_transaction
      else
        unless completed
          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 raise and rollback.
          EOW
        end
        begin
          commit_transaction
        rescue Exception
          rollback_transaction(transaction) unless transaction.state.completed?
          raise
        end
      end
    end
  end
end