class Cassandra::Protocol::CqlProtocolHandler::RequestPromise

@private

Attributes

request[R]
timeout[R]
timer[RW]

Public Class Methods

new(request, timeout, scheduler) click to toggle source
Calls superclass method
    # File lib/cassandra/protocol/cql_protocol_handler.rb
261 def initialize(request, timeout, scheduler)
262   @request = request
263   @timeout = timeout
264   @timed_out = false
265   @scheduler = scheduler
266   @lock = Mutex.new
267   @timer = nil
268   super()
269 end

Public Instance Methods

fail(cause) click to toggle source
Calls superclass method
    # File lib/cassandra/protocol/cql_protocol_handler.rb
309 def fail(cause)
310   super
311   maybe_cancel_timer
312 end
fulfill(response) click to toggle source
Calls superclass method
    # File lib/cassandra/protocol/cql_protocol_handler.rb
304 def fulfill(response)
305   super
306   maybe_cancel_timer
307 end
maybe_cancel_timer() click to toggle source
    # File lib/cassandra/protocol/cql_protocol_handler.rb
314 def maybe_cancel_timer
315   return if @timeout.nil?
316   timer = nil
317   if @timer
318     @lock.synchronize do
319       if @timer
320         timer = @timer
321         @timer = nil
322       end
323     end
324   end
325   @scheduler.cancel_timer(timer) if timer
326 end
maybe_start_timer() click to toggle source
    # File lib/cassandra/protocol/cql_protocol_handler.rb
278 def maybe_start_timer
279   # This is more complicated than one would expect. First, we want to start a timer
280   # if a timeout is set. But there is a race condition where send_request creates
281   # a fresh promise and adds it to @promises, but another thread handles a socket
282   # closure event and fails all known promises. When a promise fails, we want to cancel
283   # the timer, if set. So, we synchronize access to @timer to be sure we don't set up
284   # and cancel the timer at the same time. However, if promise.fail runs first, there
285   # will be no timer to cancel, and then when maybe_start_timer gets called in the other
286   # thread, it'll create a timer on a promise that no one is going to action on going forward.
287   # So, that leads to leaking the timer until it times out. To avoid this, we want to
288   # check that the future of the promise isn't completed before starting the timer.
289 
290   return if @timeout.nil?
291   return if @future.completed?
292 
293   if @timer.nil?
294     @lock.synchronize do
295       if @timer.nil?
296         return if @future.completed?
297         @timer = @scheduler.schedule_timer(@timeout)
298         @timer.on_value { time_out! }
299       end
300     end
301   end
302 end
time_out!() click to toggle source
    # File lib/cassandra/protocol/cql_protocol_handler.rb
271 def time_out!
272   unless future.completed?
273     @timed_out = true
274     fail(Errors::TimeoutError.new('Timed out'))
275   end
276 end