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