Class: Falcon::Limiter::Wrapper

Inherits:
IO::Endpoint::Wrapper
  • Object
show all
Defined in:
lib/falcon/limiter/wrapper.rb

Overview

An endpoint wrapper that limits concurrent connections using a semaphore. This provides backpressure by limiting how many connections can be accepted simultaneously.

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(limiter) ⇒ Wrapper

Initialize the wrapper with a connection limiter.



17
18
19
20
# File 'lib/falcon/limiter/wrapper.rb', line 17

def initialize(limiter)
	super()
	@limiter = limiter
end

Instance Attribute Details

#limiterObject (readonly)

Returns the value of attribute limiter.



22
23
24
# File 'lib/falcon/limiter/wrapper.rb', line 22

def limiter
  @limiter
end

Instance Method Details

#socket_accept(server) ⇒ Object

Accept a connection from the server, limited by the per-worker (thread or process) semaphore.



55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
# File 'lib/falcon/limiter/wrapper.rb', line 55

def socket_accept(server)
	socket = nil
	address = nil
	token = nil
	
	loop do
		next unless token = wait_for_inbound_connection(server)
		
		# In principle, there is a connection ready to be accepted:
		socket, address = socket_accept_nonblock(server, token)
		
		break if socket
	end
	
	# Wrap socket with transparent token management
	return wrap_socket(socket, token), address
end

#socket_accept_nonblock(server, token) ⇒ Object

Once the server is readable and we’ve acquired the token, we can accept the connection (if it’s still there).



38
39
40
41
42
43
44
# File 'lib/falcon/limiter/wrapper.rb', line 38

def socket_accept_nonblock(server, token)
	socket = server.accept_nonblock
rescue IO::WaitReadable
	nil
ensure
	token.release unless socket
end

#wait_for_inbound_connection(server) ⇒ Object

Wait for an inbound connection to be ready to be accepted.



25
26
27
28
29
30
31
32
33
34
35
# File 'lib/falcon/limiter/wrapper.rb', line 25

def wait_for_inbound_connection(server)
	loop do
		# Wait until there is a connection ready to be accepted:
		server.wait_readable
		
		# Acquire the limiter:
		if token = Async::Limiter::Token.acquire(@limiter)
			return token
		end
	end
end

#wrap_socket(socket, token) ⇒ Object

Wrap the socket with a transparent token management.



50
51
52
# File 'lib/falcon/limiter/wrapper.rb', line 50

def wrap_socket(socket, token)
	Socket.new(socket, token)
end