Skip to content

Commit

Permalink
Refactor Reactor and Client request buffering
Browse files Browse the repository at this point in the history
Refactor Reactor into a more generic IO-with-timeout monitor,
using Queue and SortedSet to simplify the implementation.
Move request-buffering logic into Server#reactor_wakeup.
Fixes bug in managing timeouts on clients.
Move, update and rewrite documentation to match updated class structure.
  • Loading branch information
wjordan committed Jun 10, 2020
1 parent f7b09dd commit 1849516
Show file tree
Hide file tree
Showing 5 changed files with 214 additions and 465 deletions.
1 change: 1 addition & 0 deletions History.md
Expand Up @@ -59,6 +59,7 @@
* JSON parse cluster worker stats instead of regex (#2124)
* Support parallel tests in verbose progress reporting (#2223)
* Refactor error handling in server accept loop (#2239)
* Refactor Reactor and Client request buffering (#2279)

## 4.3.4/4.3.5 and 3.12.5/3.12.6 / 2020-05-22

Expand Down
19 changes: 15 additions & 4 deletions lib/puma/client.rb
Expand Up @@ -104,6 +104,15 @@ def set_timeout(val)
@timeout_at = Time.now + val
end

# Number of seconds until the timeout elapses.
def timeout
[@timeout_at - Time.now, 0].max
end

def <=>(other)
@timeout_at <=> other.timeout_at
end

def reset(fast_check=true)
@parser.reset
@read_header = true
Expand Down Expand Up @@ -251,14 +260,16 @@ def finish(timeout)
rescue ThreadPool::ForceShutdown
nil
end
unless can_read
write_error(408) if in_data_phase
raise ConnectionError
end
timeout! unless can_read
end
true
end

def timeout!
write_error(408) if in_data_phase
raise ConnectionError
end

def write_error(status_code)
begin
@io << ERROR_RESPONSE[status_code]
Expand Down
24 changes: 24 additions & 0 deletions lib/puma/queue_close.rb
@@ -0,0 +1,24 @@
# Queue#close was added in Ruby 2.3.
# Add a simple implementation for earlier Ruby versions.
unless Queue.instance_methods.include?(:close)
class ClosedQueueError < StandardError; end
module Puma
module QueueClose
def initialize
@closed = false
super
end
def close
@closed = true
end
def closed?
@closed
end
def push(object)
raise ClosedQueueError if @closed
super
end
end
Queue.prepend QueueClose
end
end

0 comments on commit 1849516

Please sign in to comment.