1 # -*- encoding: binary -*-
5 # This module is used to extend TCPServer and Kgio::TCPServer objects
6 # and aggregate +last_data_recv+ times for all accepted clients. It
7 # is designed to be used with Raindrops::LastDataRecv Rack application
8 # but can be easily changed to work with other stats collection devices.
10 # Methods wrapped include:
12 # - TCPServer#accept_nonblock
13 # - Kgio::TCPServer#kgio_accept
14 # - Kgio::TCPServer#kgio_tryaccept
15 module Raindrops::Aggregate::LastDataRecv
17 TCP_Info = Raindrops::TCP_Info
20 # The integer value of +last_data_recv+ is sent to this object.
21 # This is usually a duck type compatible with the \Aggregate class,
22 # but can be *anything* that accepts the *<<* method.
23 attr_accessor :raindrops_aggregate
25 @@default_aggregate = nil
27 # By default, this is a Raindrops::Aggregate::PMQ object
28 # It may be anything that responds to *<<*
29 def self.default_aggregate
30 @@default_aggregate ||= Raindrops::Aggregate::PMQ.new
33 # Assign any object that responds to *<<*
34 def self.default_aggregate=(agg)
35 @@default_aggregate = agg
38 # automatically extends any TCPServer objects used by Unicorn
40 Unicorn::HttpServer::LISTENERS.each do |sock|
41 sock.extend(self) if TCPServer === sock
45 # each extended object needs to have TCP_DEFER_ACCEPT enabled
47 def self.extended(obj)
48 obj.raindrops_aggregate = default_aggregate
49 # obj.setsockopt Socket::SOL_TCP, tcp_defer_accept = 9, seconds = 60
50 obj.setsockopt Socket::SOL_TCP, 9, 60
55 def kgio_tryaccept(*args)
59 def kgio_accept(*args)
73 # The +last_data_recv+ member of Raindrops::TCP_Info can be used to
74 # infer the time a client spent in the listen queue before it was
77 # We require TCP_DEFER_ACCEPT on the listen socket for
78 # +last_data_recv+ to be accurate
82 @raindrops_aggregate << x.last_data_recv