mirror of
https://github.com/mperham/connection_pool
synced 2023-03-27 23:22:21 -04:00
Monotonic clock for more accurate timeouts.
This commit is contained in:
parent
84f6eeeaf9
commit
9f295f49a2
2 changed files with 69 additions and 2 deletions
66
lib/connection_pool/monotonic_time.rb
Normal file
66
lib/connection_pool/monotonic_time.rb
Normal file
|
@ -0,0 +1,66 @@
|
|||
# Global monotonic clock from Concurrent Ruby 1.0.
|
||||
# Copyright (c) Jerry D'Antonio -- released under the MIT license.
|
||||
# Slightly modified; used with permission.
|
||||
# https://github.com/ruby-concurrency/concurrent-ruby
|
||||
|
||||
require 'thread'
|
||||
|
||||
class ConnectionPool
|
||||
|
||||
class_definition = Class.new do
|
||||
|
||||
if defined?(Process::CLOCK_MONOTONIC)
|
||||
|
||||
# @!visibility private
|
||||
def get_time
|
||||
Process.clock_gettime(Process::CLOCK_MONOTONIC)
|
||||
end
|
||||
|
||||
elsif defined?(RUBY_ENGINE) && RUBY_ENGINE == 'jruby'
|
||||
|
||||
# @!visibility private
|
||||
def get_time
|
||||
java.lang.System.nanoTime() / 1_000_000_000.0
|
||||
end
|
||||
|
||||
else
|
||||
|
||||
# @!visibility private
|
||||
def initialize
|
||||
@mutex = Mutex.new
|
||||
@last_time = Time.now.to_f
|
||||
end
|
||||
|
||||
# @!visibility private
|
||||
def get_time
|
||||
@mutex.synchronize do
|
||||
now = Time.now.to_f
|
||||
if @last_time < now
|
||||
@last_time = now
|
||||
else # clock has moved back in time
|
||||
@last_time += 0.000_001
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
##
|
||||
# Clock that cannot be set and represents monotonic time since
|
||||
# some unspecified starting point.
|
||||
#
|
||||
# @!visibility private
|
||||
GLOBAL_MONOTONIC_CLOCK = class_definition.new
|
||||
private_constant :GLOBAL_MONOTONIC_CLOCK
|
||||
|
||||
class << self
|
||||
##
|
||||
# Returns the current time a tracked by the application monotonic clock.
|
||||
#
|
||||
# @return [Float] The current monotonic time when `since` not given else
|
||||
# the elapsed monotonic time between `since` and the current time
|
||||
def monotonic_time
|
||||
GLOBAL_MONOTONIC_CLOCK.get_time
|
||||
end
|
||||
end
|
||||
end
|
|
@ -1,5 +1,6 @@
|
|||
require 'thread'
|
||||
require 'timeout'
|
||||
require_relative 'monotonic_time'
|
||||
|
||||
##
|
||||
# Raised when you attempt to retrieve a connection from a pool that has been
|
||||
|
@ -72,7 +73,7 @@ class ConnectionPool::TimedStack
|
|||
options, timeout = timeout, 0.5 if Hash === timeout
|
||||
timeout = options.fetch :timeout, timeout
|
||||
|
||||
deadline = Time.now + timeout
|
||||
deadline = ConnectionPool.monotonic_time + timeout
|
||||
@mutex.synchronize do
|
||||
loop do
|
||||
raise ConnectionPool::PoolShuttingDownError if @shutdown_block
|
||||
|
@ -81,7 +82,7 @@ class ConnectionPool::TimedStack
|
|||
connection = try_create(options)
|
||||
return connection if connection
|
||||
|
||||
to_wait = deadline - Time.now
|
||||
to_wait = deadline - ConnectionPool.monotonic_time
|
||||
raise Timeout::Error, "Waited #{timeout} sec" if to_wait <= 0
|
||||
@resource.wait(@mutex, to_wait)
|
||||
end
|
||||
|
|
Loading…
Reference in a new issue