Module: Sidekiq::TransactionGuard

Defined in:
lib/sidekiq/transaction_guard.rb,
lib/sidekiq/transaction_guard/version.rb,
lib/sidekiq/transaction_guard/middleware.rb,
lib/sidekiq/transaction_guard/database_cleaner.rb

Defined Under Namespace

Modules: DatabaseCleaner Classes: InsideTransactionError, Middleware

Constant Summary collapse

VALID_MODES =
[:warn, :stderr, :error, :disabled].freeze
VERSION =
File.read(File.expand_path("../../../../VERSION", __FILE__)).chomp.freeze

Class Method Summary collapse

Class Method Details

.add_connection_class(connection_class) ⇒ Object

Add a class that maintains it's own connection pool to the connections being monitored for open transactions. You don't need to add `ActiveRecord::Base` or subclasses. Only the base class that establishes a new connection pool with a call to `establish_connection` needs to be added.



58
59
60
# File 'lib/sidekiq/transaction_guard.rb', line 58

def add_connection_class(connection_class)
  @lock.synchronize{ @connection_classes << connection_class }
end

.in_transaction?Boolean

Return true if any connection is currently inside of a transaction.

Returns:

  • (Boolean)


63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
# File 'lib/sidekiq/transaction_guard.rb', line 63

def in_transaction?
  connection_classes = [ActiveRecord::Base]
  unless @connection_classes.empty?
    connection_classes.concat(@lock.synchronize{ @connection_classes.to_a })
  end
  connection_classes.any? do |connection_class|
    connection_pool = connection_class.connection_pool
    connection = connection_class.connection if connection_pool.active_connection?
    if connection
      connection.open_transactions > allowed_transaction_level(connection_class)
    else
      false
    end
  end
end

.modeObject

Return the current mode.



38
39
40
# File 'lib/sidekiq/transaction_guard.rb', line 38

def mode
  @mode
end

.mode=(symbol) ⇒ Object

Set the global mode to one of `[:warn, :stderr, :error, :disabled]`. The default mode is `:warn`. This controls the behavior of workers enqueued inside of transactions.

  • :warn - Log to Sidekiq.logger

  • :stderr - Log to $stderr

  • :error - Throw a `Sidekiq::TransactionGuard::InsideTransactionError`

  • :disabled - Allow workers inside of transactions



29
30
31
32
33
34
35
# File 'lib/sidekiq/transaction_guard.rb', line 29

def mode=(symbol)
  if VALID_MODES.include?(symbol)
    @mode = symbol
  else
    raise ArgumentError.new("mode must be one of #{VALID_MODES.inspect}")
  end
end

.notify(&block) ⇒ Object

Define the global notify block. This block will be called with a Sidekiq job hash for all jobs enqueued inside transactions if the mode is `:warn` or `:stderr`.



45
46
47
# File 'lib/sidekiq/transaction_guard.rb', line 45

def notify(&block)
  @notify = block
end

.notify_blockObject

Return the block set as the notify handler with a call to `notify`.



50
51
52
# File 'lib/sidekiq/transaction_guard.rb', line 50

def notify_block
  @notify
end

.set_allowed_transaction_level(connection_class) ⇒ Object

This method needs to be called to set the allowed transaction level for a connection class (see `add_connection_class` for more info). The current transaction level for that class' connection will be set as the zero point. This method can only be called inside a block wrapped with the `testing` method.



96
97
98
99
100
101
102
# File 'lib/sidekiq/transaction_guard.rb', line 96

def set_allowed_transaction_level(connection_class)
  connection_counts = Thread.current[:sidekiq_rails_transaction_guard]
  unless connection_counts
    raise("set_allowed_transaction_level is only allowed inside a testing block")
  end
  connection_counts[connection_class.name] = connection_class.connection.open_transactions if connection_counts
end

.testing(&block) ⇒ Object

This method call needs to be wrapped around tests that use transactional fixtures. It sets up data structures used to track the number of open transactions.



81
82
83
84
85
86
87
88
89
90
# File 'lib/sidekiq/transaction_guard.rb', line 81

def testing(&block)
  var = :sidekiq_rails_transaction_guard
  save_val = Thread.current[var]
  begin
    Thread.current[var] = (save_val ? save_val.dup : {})
    yield
  ensure
    Thread.current[var] = save_val
  end
end