Sha256: 001821ac35afb1d9fae378e84e9291ad0a1bce55509313bac86e6d4dee75b986

Contents?: true

Size: 1.43 KB

Versions: 5

Compression:

Stored size: 1.43 KB

Contents

# frozen_string_literal: true

module Isolator
  # ActiveSupport notifications listener
  # Used for ActiveRecord and ROM::SQL (when instrumentation is available)
  module ActiveSupportSubscriber
    START_PATTERN = %r{(\ABEGIN|\ASAVEPOINT)}xi
    FINISH_PATTERN = %r{(\ACOMMIT|\AROLLBACK|\ARELEASE|\AEND TRANSACTION)}xi

    class Subscriber
      def start(event, id, payload)
        return unless start_event?(payload[:sql])

        connection_id = extract_connection_id(payload)

        Isolator.incr_transactions!(connection_id)
      end

      def finish(event, id, payload)
        return unless finish_event?(payload[:sql])

        connection_id = extract_connection_id(payload)

        Isolator.decr_transactions!(connection_id)
      end

      private

      def start_event?(sql)
        START_PATTERN.match?(sanitize_query(sql))
      end

      def finish_event?(sql)
        FINISH_PATTERN.match?(sanitize_query(sql))
      end

      # Prevents "ArgumentError: invalid byte sequence in UTF-8" by replacing invalid byte sequence with "?"
      def sanitize_query(sql)
        sql.encode("UTF-8", "binary", invalid: :replace, undef: :replace, replace: "?")
      end

      def extract_connection_id(payload)
        payload[:connection_id] || payload[:connection]&.object_id || 0
      end
    end

    def self.subscribe!(event)
      subscriber = Subscriber.new
      ::ActiveSupport::Notifications.subscribe(event, subscriber)
    end
  end
end

Version data entries

5 entries across 5 versions & 1 rubygems

Version Path
isolator-1.1.1 lib/isolator/orm_adapters/active_support_subscriber.rb
isolator-1.1.0 lib/isolator/orm_adapters/active_support_subscriber.rb
isolator-1.0.1 lib/isolator/orm_adapters/active_support_subscriber.rb
isolator-1.0.0 lib/isolator/orm_adapters/active_support_subscriber.rb
isolator-0.11.0 lib/isolator/orm_adapters/active_support_subscriber.rb