precompiled-raindrops 0.18.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (63) hide show
  1. checksums.yaml +7 -0
  2. data/.document +7 -0
  3. data/.gitattributes +4 -0
  4. data/.github/workflows/cibuildgem.yaml +90 -0
  5. data/.gitignore +16 -0
  6. data/.olddoc.yml +16 -0
  7. data/COPYING +165 -0
  8. data/GIT-VERSION-GEN +40 -0
  9. data/GNUmakefile +4 -0
  10. data/Gemfile +1 -0
  11. data/LICENSE +16 -0
  12. data/README +111 -0
  13. data/Rakefile +0 -0
  14. data/TODO +3 -0
  15. data/archive/.gitignore +3 -0
  16. data/archive/slrnpull.conf +4 -0
  17. data/examples/linux-listener-stats.rb +123 -0
  18. data/examples/middleware.ru +6 -0
  19. data/examples/watcher.ru +5 -0
  20. data/examples/watcher_demo.ru +14 -0
  21. data/examples/yahns.conf.rb +31 -0
  22. data/examples/zbatery.conf.rb +17 -0
  23. data/ext/raindrops/extconf.rb +164 -0
  24. data/ext/raindrops/khashl.h +444 -0
  25. data/ext/raindrops/linux_inet_diag.c +719 -0
  26. data/ext/raindrops/my_fileno.h +16 -0
  27. data/ext/raindrops/raindrops.c +487 -0
  28. data/ext/raindrops/raindrops_atomic.h +23 -0
  29. data/ext/raindrops/tcp_info.c +245 -0
  30. data/lib/raindrops/aggregate/last_data_recv.rb +95 -0
  31. data/lib/raindrops/aggregate/pmq.rb +246 -0
  32. data/lib/raindrops/aggregate.rb +9 -0
  33. data/lib/raindrops/last_data_recv.rb +103 -0
  34. data/lib/raindrops/linux.rb +78 -0
  35. data/lib/raindrops/middleware/proxy.rb +41 -0
  36. data/lib/raindrops/middleware.rb +154 -0
  37. data/lib/raindrops/struct.rb +63 -0
  38. data/lib/raindrops/watcher.rb +429 -0
  39. data/lib/raindrops.rb +79 -0
  40. data/pkg.mk +151 -0
  41. data/raindrops.gemspec +26 -0
  42. data/setup.rb +1587 -0
  43. data/test/ipv6_enabled.rb +10 -0
  44. data/test/rack_unicorn.rb +12 -0
  45. data/test/test_aggregate_pmq.rb +66 -0
  46. data/test/test_inet_diag_socket.rb +17 -0
  47. data/test/test_last_data_recv.rb +58 -0
  48. data/test/test_last_data_recv_unicorn.rb +70 -0
  49. data/test/test_linux.rb +282 -0
  50. data/test/test_linux_all_tcp_listen_stats.rb +67 -0
  51. data/test/test_linux_all_tcp_listen_stats_leak.rb +44 -0
  52. data/test/test_linux_ipv6.rb +167 -0
  53. data/test/test_linux_middleware.rb +65 -0
  54. data/test/test_linux_reuseport_tcp_listen_stats.rb +52 -0
  55. data/test/test_middleware.rb +129 -0
  56. data/test/test_middleware_unicorn.rb +38 -0
  57. data/test/test_middleware_unicorn_ipv6.rb +38 -0
  58. data/test/test_raindrops.rb +208 -0
  59. data/test/test_raindrops_gc.rb +39 -0
  60. data/test/test_struct.rb +55 -0
  61. data/test/test_tcp_info.rb +89 -0
  62. data/test/test_watcher.rb +187 -0
  63. metadata +194 -0
@@ -0,0 +1,39 @@
1
+ # -*- encoding: binary -*-
2
+ # frozen_string_literal: false
3
+ require 'test/unit'
4
+ require 'raindrops'
5
+
6
+ class TestRaindropsGc < Test::Unit::TestCase
7
+
8
+ # we may need to create more garbage as GC may be less aggressive
9
+ # about expiring things. This is completely unrealistic code,
10
+ # though...
11
+ def test_gc
12
+ assert_nothing_raised do
13
+ 1000000.times { |i| Raindrops.new(24); [] }
14
+ end
15
+ end
16
+
17
+ def test_gc_postfork
18
+ tmp = Raindrops.new 2
19
+ pid = fork do
20
+ 1000000.times do
21
+ tmp = Raindrops.new 2
22
+ tmp.to_ary
23
+ end
24
+ end
25
+ _, status = Process.waitpid2(pid)
26
+ assert status.success?
27
+ assert_equal [ 0, 0 ], tmp.to_ary
28
+ tmp.incr 1
29
+ assert_equal [ 0, 1 ], tmp.to_ary
30
+ pid = fork do
31
+ tmp.incr 1
32
+ exit([ 0, 2 ] == tmp.to_ary)
33
+ end
34
+ _, status = Process.waitpid2(pid)
35
+ assert status.success?
36
+ assert_equal [ 0, 2 ], tmp.to_ary
37
+ end
38
+ end if !defined?(RUBY_ENGINE) || RUBY_ENGINE == "ruby" &&
39
+ ENV["STRESS"].to_i != 0
@@ -0,0 +1,55 @@
1
+ # frozen_string_literal: false
2
+ require 'test/unit'
3
+ require 'raindrops'
4
+
5
+ class TestRaindrops < Test::Unit::TestCase
6
+
7
+ def test_struct_new
8
+ @rw = Raindrops::Struct.new(:r, :w)
9
+ assert @rw.kind_of?(Class)
10
+ end
11
+
12
+ TMP = Raindrops::Struct.new(:r, :w)
13
+
14
+ def test_init_basic
15
+ tmp = TMP.new
16
+ assert_equal 0, tmp.r
17
+ assert_equal 1, tmp.incr_r
18
+ assert_equal 1, tmp.r
19
+ assert_equal({ :r => 1, :w => 0 }, tmp.to_hash)
20
+
21
+ assert_equal 1, tmp[0]
22
+ assert_equal 0, tmp[1]
23
+ assert_equal [ :r, :w ], TMP::MEMBERS
24
+ end
25
+
26
+ def test_init
27
+ tmp = TMP.new(5, 6)
28
+ assert_equal({ :r => 5, :w => 6 }, tmp.to_hash)
29
+ end
30
+
31
+ def test_dup
32
+ a = TMP.new(5, 6)
33
+ b = a.dup
34
+ assert_equal({ :r => 5, :w => 6 }, b.to_hash)
35
+ assert_nothing_raised { 4.times { b.decr_r } }
36
+ assert_equal({ :r => 1, :w => 6 }, b.to_hash)
37
+ assert_equal({ :r => 5, :w => 6 }, a.to_hash)
38
+ end
39
+
40
+ class Foo < Raindrops::Struct.new(:a, :b, :c, :d)
41
+ def to_ary
42
+ @raindrops.to_ary
43
+ end
44
+
45
+ def hello
46
+ "world"
47
+ end
48
+ end
49
+
50
+ def test_subclass
51
+ assert_equal [0, 0, 0, 0], Foo.new.to_ary
52
+ assert_equal "world", Foo.new.hello
53
+ end
54
+
55
+ end
@@ -0,0 +1,89 @@
1
+ # -*- encoding: binary -*-
2
+ # frozen_string_literal: false
3
+ require 'test/unit'
4
+ require 'tempfile'
5
+ require 'raindrops'
6
+ require 'socket'
7
+ require 'pp'
8
+ $stderr.sync = $stdout.sync = true
9
+ class TestTCP_Info < Test::Unit::TestCase
10
+
11
+ TEST_ADDR = ENV['UNICORN_TEST_ADDR'] || '127.0.0.1'
12
+
13
+ # Linux kernel commit 5ee3afba88f5a79d0bff07ddd87af45919259f91
14
+ TCP_INFO_useful_listenq = `uname -r`.strip >= '2.6.24'
15
+
16
+ def test_tcp_server_unacked
17
+ return if RUBY_PLATFORM !~ /linux/ # unacked not implemented on others...
18
+ s = TCPServer.new(TEST_ADDR, 0)
19
+ rv = Raindrops::TCP_Info.new s
20
+ c = TCPSocket.new TEST_ADDR, s.addr[1]
21
+ tmp = Raindrops::TCP_Info.new s
22
+ TCP_INFO_useful_listenq and assert_equal 1, tmp.unacked
23
+
24
+ assert_equal 0, rv.unacked
25
+ a = s.accept
26
+ tmp = Raindrops::TCP_Info.new s
27
+ assert_equal 0, tmp.unacked
28
+ before = tmp.object_id
29
+
30
+ tmp.get!(s)
31
+ assert_equal before, tmp.object_id
32
+
33
+ ensure
34
+ [ c, a, s ].compact.each(&:close)
35
+ end
36
+
37
+ def test_accessors
38
+ s = TCPServer.new TEST_ADDR, 0
39
+ tmp = Raindrops::TCP_Info.new s
40
+ tcp_info_methods = tmp.methods - Object.new.methods
41
+ assert tcp_info_methods.size >= 32
42
+ tcp_info_methods.each do |m|
43
+ next if m.to_sym == :get!
44
+ next if ! tmp.respond_to?(m)
45
+ val = tmp.__send__ m
46
+ assert_kind_of Integer, val
47
+ assert val >= 0
48
+ end
49
+ assert tmp.respond_to?(:state), 'every OS knows about TCP state, right?'
50
+ ensure
51
+ s.close
52
+ end
53
+
54
+ def test_tcp_server_delayed
55
+ delay = 0.010
56
+ delay_ms = (delay * 1000).to_i
57
+ s = TCPServer.new(TEST_ADDR, 0)
58
+ c = TCPSocket.new TEST_ADDR, s.addr[1]
59
+ c.syswrite "."
60
+ sleep(delay * 1.2)
61
+ a = s.accept
62
+ i = Raindrops::TCP_Info.new(a)
63
+ assert i.last_data_recv >= delay_ms, "#{i.last_data_recv} < #{delay_ms}"
64
+ ensure
65
+ c.close if c
66
+ a.close if a
67
+ s.close
68
+ end
69
+
70
+ def test_tcp_server_state_closed
71
+ s = TCPServer.new(TEST_ADDR, 0)
72
+ c = TCPSocket.new(TEST_ADDR, s.addr[1])
73
+ i = Raindrops::TCP_Info.allocate
74
+ a = s.accept
75
+ i.get!(a)
76
+ state = i.state
77
+ if Raindrops.const_defined?(:TCP)
78
+ assert_equal state, Raindrops::TCP[:ESTABLISHED]
79
+ end
80
+ c = c.close
81
+ sleep(0.01) # wait for kernel to update state
82
+ i.get!(a)
83
+ assert_not_equal state, i.state
84
+ ensure
85
+ s.close if s
86
+ c.close if c
87
+ a.close if a
88
+ end
89
+ end if defined? Raindrops::TCP_Info
@@ -0,0 +1,187 @@
1
+ # -*- encoding: binary -*-
2
+ # frozen_string_literal: false
3
+ require "test/unit"
4
+ require "raindrops"
5
+ begin
6
+ require 'aggregate'
7
+ require 'rack'
8
+ rescue LoadError => e
9
+ warn "W: #{e} skipping #{__FILE__}"
10
+ end
11
+
12
+ class TestWatcher < Test::Unit::TestCase
13
+ TEST_ADDR = ENV['UNICORN_TEST_ADDR'] || '127.0.0.1'
14
+ def check_headers(headers)
15
+ %w(X-Count X-Std-Dev X-Min X-Max X-Mean
16
+ X-Outliers-Low X-Outliers-Low X-Last-Reset).each { |x|
17
+ assert_kind_of String, headers[x], "#{x} missing"
18
+ }
19
+ end
20
+
21
+ def teardown
22
+ @app.shutdown
23
+ @ios.each { |io| io.close unless io.closed? }
24
+ end
25
+
26
+ def setup
27
+ @ios = []
28
+ @srv = TCPServer.new TEST_ADDR, 0
29
+ @ios << @srv
30
+ @port = @srv.addr[1]
31
+ @client = TCPSocket.new TEST_ADDR, @port
32
+ @addr = "#{TEST_ADDR}:#{@port}"
33
+ @ios << @client
34
+ @app = Raindrops::Watcher.new :delay => 0.001
35
+ @req = Rack::MockRequest.new @app
36
+ end
37
+
38
+ def test_index
39
+ resp = @req.get "/"
40
+ assert_equal 200, resp.status.to_i
41
+ t = Time.parse resp.headers["Last-Modified"]
42
+ assert_in_delta Time.now.to_f, t.to_f, 2.0
43
+ end
44
+
45
+ def test_active_txt
46
+ resp = @req.get "/active/#@addr.txt"
47
+ assert_equal 200, resp.status.to_i
48
+ assert_equal "text/plain", resp.headers["Content-Type"]
49
+ check_headers(resp.headers)
50
+ end
51
+
52
+ def test_invalid
53
+ assert_nothing_raised do
54
+ @req.get("/active/666.666.666.666%3A666.txt")
55
+ @req.get("/queued/666.666.666.666%3A666.txt")
56
+ @req.get("/active/666.666.666.666%3A666.html")
57
+ @req.get("/queued/666.666.666.666%3A666.html")
58
+ end
59
+ addr = @app.instance_eval do
60
+ @peak_active.keys + @peak_queued.keys +
61
+ @resets.keys + @active.keys + @queued.keys
62
+ end
63
+ assert addr.grep(/666\.666\.666\.666/).empty?, addr.inspect
64
+ end
65
+
66
+ def test_active_html
67
+ resp = @req.get "/active/#@addr.html"
68
+ assert_equal 200, resp.status.to_i
69
+ assert_equal "text/html", resp.headers["Content-Type"]
70
+ check_headers(resp.headers)
71
+ end
72
+
73
+ def test_queued_txt
74
+ resp = @req.get "/queued/#@addr.txt"
75
+ assert_equal 200, resp.status.to_i
76
+ assert_equal "text/plain", resp.headers["Content-Type"]
77
+ check_headers(resp.headers)
78
+ end
79
+
80
+ def test_queued_html
81
+ resp = @req.get "/queued/#@addr.html"
82
+ assert_equal 200, resp.status.to_i
83
+ assert_equal "text/html", resp.headers["Content-Type"]
84
+ check_headers(resp.headers)
85
+ end
86
+
87
+ def test_reset
88
+ resp = @req.post "/reset/#@addr"
89
+ assert_equal 302, resp.status.to_i
90
+ end
91
+
92
+ def test_tail
93
+ env = @req.class.env_for "/tail/#@addr.txt"
94
+ status, headers, body = @app.call env
95
+ assert_equal "text/plain", headers["Content-Type"]
96
+ assert_equal 200, status.to_i
97
+ tmp = []
98
+ body.each do |x|
99
+ assert_kind_of String, x
100
+ tmp << x
101
+ break if tmp.size > 1
102
+ end
103
+ end
104
+
105
+ def test_tail_queued_min
106
+ env = @req.class.env_for "/tail/#@addr.txt?queued_min=1"
107
+ status, headers, body = @app.call env
108
+ assert_equal "text/plain", headers["Content-Type"]
109
+ assert_equal 200, status.to_i
110
+ tmp = []
111
+ body.each do |x|
112
+ tmp = TCPSocket.new TEST_ADDR, @port
113
+ @ios << tmp
114
+ assert_kind_of String, x
115
+ assert_equal 1, x.strip.split(/\s+/).last.to_i
116
+ break
117
+ end
118
+ end
119
+
120
+ def test_x_current_header
121
+ env = @req.class.env_for "/active/#@addr.txt"
122
+ _status, headers, _body = @app.call(env)
123
+ assert_equal "0", headers["X-Current"], headers.inspect
124
+
125
+ env = @req.class.env_for "/queued/#@addr.txt"
126
+ _status, headers, _body = @app.call(env)
127
+ assert_equal "1", headers["X-Current"], headers.inspect
128
+
129
+ @ios << @srv.accept
130
+ sleep 0.1
131
+
132
+ env = @req.class.env_for "/queued/#@addr.txt"
133
+ _status, headers, _body = @app.call(env)
134
+ assert_equal "0", headers["X-Current"], headers.inspect
135
+
136
+ env = @req.class.env_for "/active/#@addr.txt"
137
+ _status, headers, _body = @app.call(env)
138
+ assert_equal "1", headers["X-Current"], headers.inspect
139
+ end
140
+
141
+ def test_peaks
142
+ env = @req.class.env_for "/active/#@addr.txt"
143
+ _status, headers, _body = @app.call(env.dup)
144
+ start = headers["X-First-Peak-At"]
145
+ assert headers["X-First-Peak-At"], headers.inspect
146
+ assert headers["X-Last-Peak-At"], headers.inspect
147
+ assert_nothing_raised { Time.parse(headers["X-First-Peak-At"]) }
148
+ assert_nothing_raised { Time.parse(headers["X-Last-Peak-At"]) }
149
+ before = headers["X-Last-Peak-At"]
150
+
151
+ env = @req.class.env_for "/queued/#@addr.txt"
152
+ _status, headers, _body = @app.call(env)
153
+ assert_nothing_raised { Time.parse(headers["X-First-Peak-At"]) }
154
+ assert_nothing_raised { Time.parse(headers["X-Last-Peak-At"]) }
155
+ assert_equal before, headers["X-Last-Peak-At"], "should not change"
156
+
157
+ sleep 2
158
+ env = @req.class.env_for "/active/#@addr.txt"
159
+ _status, headers, _body = @app.call(env.dup)
160
+ assert_equal before, headers["X-Last-Peak-At"], headers.inspect
161
+
162
+ @ios << @srv.accept
163
+ begin
164
+ @srv.accept_nonblock
165
+ assert false, "we should not get here"
166
+ rescue => e
167
+ assert_kind_of Errno::EAGAIN, e
168
+ end
169
+ sleep 0.1
170
+ env = @req.class.env_for "/queued/#@addr.txt"
171
+ _status, headers, _body = @app.call(env.dup)
172
+ assert headers["X-Last-Peak-At"], headers.inspect
173
+ assert_nothing_raised { Time.parse(headers["X-Last-Peak-At"]) }
174
+ assert before != headers["X-Last-Peak-At"]
175
+
176
+ queued_before = headers["X-Last-Peak-At"]
177
+
178
+ sleep 2
179
+
180
+ env = @req.class.env_for "/queued/#@addr.txt"
181
+ _status, headers, _body = @app.call(env)
182
+ assert_equal "0", headers["X-Current"]
183
+ assert_nothing_raised { Time.parse(headers["X-Last-Peak-At"]) }
184
+ assert_equal queued_before, headers["X-Last-Peak-At"], "should not change"
185
+ assert_equal start, headers["X-First-Peak-At"]
186
+ end
187
+ end if RUBY_PLATFORM =~ /linux/ && defined?(Aggregate) && defined?(Rack)
metadata ADDED
@@ -0,0 +1,194 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: precompiled-raindrops
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.18.0
5
+ platform: ruby
6
+ authors:
7
+ - raindrops hackers
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2026-02-16 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: aggregate
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: '0.2'
20
+ type: :development
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - "~>"
25
+ - !ruby/object:Gem::Version
26
+ version: '0.2'
27
+ - !ruby/object:Gem::Dependency
28
+ name: test-unit
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - "~>"
32
+ - !ruby/object:Gem::Version
33
+ version: '3.0'
34
+ type: :development
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - "~>"
39
+ - !ruby/object:Gem::Version
40
+ version: '3.0'
41
+ - !ruby/object:Gem::Dependency
42
+ name: posix_mq
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - "~>"
46
+ - !ruby/object:Gem::Version
47
+ version: '2.0'
48
+ type: :development
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - "~>"
53
+ - !ruby/object:Gem::Version
54
+ version: '2.0'
55
+ - !ruby/object:Gem::Dependency
56
+ name: rack
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - ">="
60
+ - !ruby/object:Gem::Version
61
+ version: '1.2'
62
+ - - "<"
63
+ - !ruby/object:Gem::Version
64
+ version: '4'
65
+ type: :development
66
+ prerelease: false
67
+ version_requirements: !ruby/object:Gem::Requirement
68
+ requirements:
69
+ - - ">="
70
+ - !ruby/object:Gem::Version
71
+ version: '1.2'
72
+ - - "<"
73
+ - !ruby/object:Gem::Version
74
+ version: '4'
75
+ description: |-
76
+ raindrops is a real-time stats toolkit to show statistics for Rack HTTP
77
+ servers. It is designed for preforking servers such as unicorn, but
78
+ should support any Rack HTTP server on platforms supporting POSIX shared
79
+ memory. It may also be used as a generic scoreboard for sharing atomic
80
+ counters across multiple processes.
81
+ email: raindrops-public@yhbt.net
82
+ executables: []
83
+ extensions:
84
+ - ext/raindrops/extconf.rb
85
+ extra_rdoc_files:
86
+ - README
87
+ - LICENSE
88
+ - ext/raindrops/raindrops.c
89
+ - ext/raindrops/linux_inet_diag.c
90
+ - ext/raindrops/tcp_info.c
91
+ files:
92
+ - ".document"
93
+ - ".gitattributes"
94
+ - ".github/workflows/cibuildgem.yaml"
95
+ - ".gitignore"
96
+ - ".olddoc.yml"
97
+ - COPYING
98
+ - GIT-VERSION-GEN
99
+ - GNUmakefile
100
+ - Gemfile
101
+ - LICENSE
102
+ - README
103
+ - Rakefile
104
+ - TODO
105
+ - archive/.gitignore
106
+ - archive/slrnpull.conf
107
+ - examples/linux-listener-stats.rb
108
+ - examples/middleware.ru
109
+ - examples/watcher.ru
110
+ - examples/watcher_demo.ru
111
+ - examples/yahns.conf.rb
112
+ - examples/zbatery.conf.rb
113
+ - ext/raindrops/extconf.rb
114
+ - ext/raindrops/khashl.h
115
+ - ext/raindrops/linux_inet_diag.c
116
+ - ext/raindrops/my_fileno.h
117
+ - ext/raindrops/raindrops.c
118
+ - ext/raindrops/raindrops_atomic.h
119
+ - ext/raindrops/tcp_info.c
120
+ - lib/raindrops.rb
121
+ - lib/raindrops/aggregate.rb
122
+ - lib/raindrops/aggregate/last_data_recv.rb
123
+ - lib/raindrops/aggregate/pmq.rb
124
+ - lib/raindrops/last_data_recv.rb
125
+ - lib/raindrops/linux.rb
126
+ - lib/raindrops/middleware.rb
127
+ - lib/raindrops/middleware/proxy.rb
128
+ - lib/raindrops/struct.rb
129
+ - lib/raindrops/watcher.rb
130
+ - pkg.mk
131
+ - raindrops.gemspec
132
+ - setup.rb
133
+ - test/ipv6_enabled.rb
134
+ - test/rack_unicorn.rb
135
+ - test/test_aggregate_pmq.rb
136
+ - test/test_inet_diag_socket.rb
137
+ - test/test_last_data_recv.rb
138
+ - test/test_last_data_recv_unicorn.rb
139
+ - test/test_linux.rb
140
+ - test/test_linux_all_tcp_listen_stats.rb
141
+ - test/test_linux_all_tcp_listen_stats_leak.rb
142
+ - test/test_linux_ipv6.rb
143
+ - test/test_linux_middleware.rb
144
+ - test/test_linux_reuseport_tcp_listen_stats.rb
145
+ - test/test_middleware.rb
146
+ - test/test_middleware_unicorn.rb
147
+ - test/test_middleware_unicorn_ipv6.rb
148
+ - test/test_raindrops.rb
149
+ - test/test_raindrops_gc.rb
150
+ - test/test_struct.rb
151
+ - test/test_tcp_info.rb
152
+ - test/test_watcher.rb
153
+ homepage: https://yhbt.net/raindrops/
154
+ licenses:
155
+ - LGPL-2.1+
156
+ metadata: {}
157
+ post_install_message:
158
+ rdoc_options: []
159
+ require_paths:
160
+ - lib
161
+ required_ruby_version: !ruby/object:Gem::Requirement
162
+ requirements:
163
+ - - ">="
164
+ - !ruby/object:Gem::Version
165
+ version: 1.9.3
166
+ required_rubygems_version: !ruby/object:Gem::Requirement
167
+ requirements:
168
+ - - ">="
169
+ - !ruby/object:Gem::Version
170
+ version: '0'
171
+ requirements: []
172
+ rubygems_version: 3.3.27
173
+ signing_key:
174
+ specification_version: 4
175
+ summary: real-time stats for preforking Rack servers
176
+ test_files:
177
+ - test/test_aggregate_pmq.rb
178
+ - test/test_inet_diag_socket.rb
179
+ - test/test_last_data_recv.rb
180
+ - test/test_last_data_recv_unicorn.rb
181
+ - test/test_linux.rb
182
+ - test/test_linux_all_tcp_listen_stats.rb
183
+ - test/test_linux_all_tcp_listen_stats_leak.rb
184
+ - test/test_linux_ipv6.rb
185
+ - test/test_linux_middleware.rb
186
+ - test/test_linux_reuseport_tcp_listen_stats.rb
187
+ - test/test_middleware.rb
188
+ - test/test_middleware_unicorn.rb
189
+ - test/test_middleware_unicorn_ipv6.rb
190
+ - test/test_raindrops.rb
191
+ - test/test_raindrops_gc.rb
192
+ - test/test_struct.rb
193
+ - test/test_tcp_info.rb
194
+ - test/test_watcher.rb