Sha256: 92daf2bc7b4ffb1174eab161842f7ac774d85d4d1f4a3c3d2e153a9ec08b4cf4

Contents?: true

Size: 1.68 KB

Versions: 1

Compression:

Stored size: 1.68 KB

Contents

# frozen_string_literal: true

module FutureRecords
  module FutureMethod
    def future
      extend FutureFeature
      exec_queries
      self
    end
  end

  module FutureFeature
    private def exec_queries(&block)
      @query_thread = Thread.new do
        connection_pool.with_connection do
          super
        end
      end
    end

    def records
      @query_thread.join
      @records
    rescue ::ActiveRecord::ConnectionTimeoutError
      logger.info 'FutureRecords: Failed to obtain a connection. Falling back to non-threaded query'
      method(:exec_queries).super_method.call
      super
    end
  end

  class << self
    def future(&block)
      Result.new(&block)
    end
  end

  class Result
    def initialize(&block)
      @block = block
      @thread = Thread.new do
        @records = yield
        if Thread.current[:child_thread_connections]
          Thread.current[:child_thread_connections].map {|conn| conn.pool}.uniq.each do |pool|
            pool.release_connection
          end
        end
      end
    end

    def records
      @thread.join
      @records
    rescue ::ActiveRecord::ConnectionTimeoutError
      ActiveRecord::Base.logger.info 'FutureRecords: Failed to obtain a connection. Falling back to non-threaded query'
      @block.call
    end
  end

  module ThreadedConnectionRecorder
    def new_connection
      conn = super
      (Thread.current[:child_thread_connections] ||= []) << conn unless Thread.current == Thread.main
      conn
    end
  end
end

ActiveSupport.on_load :active_record do
  ActiveRecord::Relation.include FutureRecords::FutureMethod
  ActiveRecord::ConnectionAdapters::ConnectionPool.prepend FutureRecords::ThreadedConnectionRecorder
end

Version data entries

1 entries across 1 versions & 1 rubygems

Version Path
future_records-0.1.0 lib/future_records.rb