module Semian::ActiveRecordTrilogyAdapter
def active?
def active? acquire_semian_resource(adapter: :trilogy_adapter, scope: :ping) do super end rescue ResourceBusyError, CircuitOpenError false end
def connect(*args)
def connect(*args) acquire_semian_resource(adapter: :trilogy_adapter, scope: :connection) do super end end
def initialize(*options)
def initialize(*options) *, config = options config = config.dup @raw_semian_options = config.delete(:semian) @semian_identifier = begin name = semian_options && semian_options[:name] unless name host = config[:host] || "localhost" port = config[:port] || 3306 name = "#{host}:#{port}" end :"mysql_#{name}" end super end
def query_allowlisted?(sql, *)
def query_allowlisted?(sql, *) # COMMIT, ROLLBACK tx_command_statement = sql.end_with?("T") || sql.end_with?("K") # RELEASE SAVEPOINT. Nesting past _3 levels won't get bypassed. # Active Record does not send trailing spaces or `;`, so we are in the realm of hand crafted queries here. savepoint_statement = sql.end_with?("_1") || sql.end_with?("_2") unclear = sql.end_with?(" ") || sql.end_with?(";") if !tx_command_statement && !savepoint_statement && !unclear false else QUERY_ALLOWLIST.match?(sql) end rescue ArgumentError return false unless sql.valid_encoding? raise end
def raw_execute(sql, *)
def raw_execute(sql, *) if Semian::ActiveRecordTrilogyAdapter.query_allowlisted?(sql) super else acquire_semian_resource(adapter: :trilogy_adapter, scope: :query) do super end end end
def resource_exceptions
def resource_exceptions [ ActiveRecord::AdapterTimeout, ActiveRecord::ConnectionFailed, ActiveRecord::ConnectionNotEstablished, ] end
def with_resource_timeout(temp_timeout)
def with_resource_timeout(temp_timeout) if @raw_connection.nil? prev_read_timeout = @config[:read_timeout] || 0 @config.merge!(read_timeout: temp_timeout) # Create new client with temp_timeout for read timeout else prev_read_timeout = @raw_connection.read_timeout @raw_connection.read_timeout = temp_timeout end yield ensure @config.merge!(read_timeout: prev_read_timeout) @raw_connection&.read_timeout = prev_read_timeout end