Class: Karst::Access::DatabaseIsolation

Inherits:
Object
  • Object
show all
Defined in:
lib/karst/access/database_isolation.rb

Overview

Runs application-authored discovery code in a rollback-only transaction and observes the same mutating SQL evidence used by Access::Sweep. This is same-connection database containment, not general side-effect isolation: jobs, mail, network calls, files, Redis, and writes through other connections remain outside this boundary.

Constant Summary collapse

MUTATION =
%r{\A\s*(?:/\*.*?\*/\s*)*(INSERT|UPDATE|DELETE)\b}im
Result =
Value.define(:value, :exception, :write_count, :database_rollback_attempted)

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(connection_class, callable) ⇒ DatabaseIsolation

Returns a new instance of DatabaseIsolation.



26
27
28
29
30
# File 'lib/karst/access/database_isolation.rb', line 26

def initialize(connection_class, callable)
  @connection_class = connection_class
  @callable = callable
  @writes = 0
end

Class Method Details

.call(connection_class:, &block) ⇒ Object



18
19
20
# File 'lib/karst/access/database_isolation.rb', line 18

def self.call(connection_class:, &block)
  new(connection_class, block).call
end

.mutation?(sql) ⇒ Boolean

Returns:

  • (Boolean)


22
23
24
# File 'lib/karst/access/database_isolation.rb', line 22

def self.mutation?(sql)
  sql.to_s.match?(MUTATION)
end

Instance Method Details

#callObject



32
33
34
35
36
37
38
39
40
41
42
# File 'lib/karst/access/database_isolation.rb', line 32

def call
  @connection_class.transaction(requires_new: true) do
    ActiveSupport::Notifications.subscribed(method(:observe), "sql.active_record") { capture }
    raise ActiveRecord::Rollback
  end

  result(rollback_attempted: true)
rescue StandardError => e
  @exception ||= e
  result(rollback_attempted: false)
end