polyphony 0.43.9 → 0.45.1
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.
- checksums.yaml +4 -4
- data/.rubocop.yml +8 -1
- data/CHANGELOG.md +40 -0
- data/Gemfile.lock +16 -6
- data/Rakefile +1 -1
- data/TODO.md +14 -13
- data/docs/_posts/2020-07-26-polyphony-0.44.md +77 -0
- data/docs/api-reference/thread.md +1 -1
- data/docs/getting-started/overview.md +14 -14
- data/docs/getting-started/tutorial.md +1 -1
- data/examples/adapters/redis_client.rb +3 -1
- data/examples/adapters/redis_pubsub_perf.rb +11 -8
- data/examples/adapters/sequel_mysql.rb +23 -0
- data/examples/adapters/sequel_mysql_pool.rb +33 -0
- data/examples/adapters/sequel_pg.rb +24 -0
- data/examples/core/{02-awaiting-fibers.rb → await.rb} +0 -0
- data/examples/core/{xx-channels.rb → channels.rb} +0 -0
- data/examples/core/deferring-an-operation.rb +16 -0
- data/examples/core/{xx-erlang-style-genserver.rb → erlang-style-genserver.rb} +16 -9
- data/examples/core/{xx-forking.rb → forking.rb} +1 -1
- data/examples/core/handling-signals.rb +11 -0
- data/examples/core/{03-interrupting.rb → interrupt.rb} +0 -0
- data/examples/core/{xx-pingpong.rb → pingpong.rb} +7 -5
- data/examples/core/{xx-recurrent-timer.rb → recurrent-timer.rb} +1 -1
- data/examples/core/{xx-resource_delegate.rb → resource_delegate.rb} +3 -4
- data/examples/core/{01-spinning-up-fibers.rb → spin.rb} +1 -1
- data/examples/core/{xx-spin_error_backtrace.rb → spin_error_backtrace.rb} +1 -1
- data/examples/core/{xx-supervise-process.rb → supervise-process.rb} +8 -5
- data/examples/core/supervisor.rb +20 -0
- data/examples/core/{xx-thread-sleep.rb → thread-sleep.rb} +0 -0
- data/examples/core/{xx-thread_pool.rb → thread_pool.rb} +0 -0
- data/examples/core/{xx-throttling.rb → throttling.rb} +0 -0
- data/examples/core/{xx-timeout.rb → timeout.rb} +0 -0
- data/examples/core/{xx-using-a-mutex.rb → using-a-mutex.rb} +0 -0
- data/examples/core/{xx-worker-thread.rb → worker-thread.rb} +2 -2
- data/examples/io/{xx-backticks.rb → backticks.rb} +0 -0
- data/examples/io/{xx-echo_client.rb → echo_client.rb} +1 -1
- data/examples/io/{xx-echo_client_from_stdin.rb → echo_client_from_stdin.rb} +2 -2
- data/examples/io/{xx-echo_pipe.rb → echo_pipe.rb} +1 -1
- data/examples/io/{xx-echo_server.rb → echo_server.rb} +0 -0
- data/examples/io/{xx-echo_server_with_timeout.rb → echo_server_with_timeout.rb} +1 -1
- data/examples/io/{xx-echo_stdin.rb → echo_stdin.rb} +0 -0
- data/examples/io/{xx-happy-eyeballs.rb → happy-eyeballs.rb} +0 -0
- data/examples/io/{xx-httparty.rb → httparty.rb} +4 -13
- data/examples/io/{xx-irb.rb → irb.rb} +0 -0
- data/examples/io/{xx-net-http.rb → net-http.rb} +0 -0
- data/examples/io/{xx-open.rb → open.rb} +0 -0
- data/examples/io/pry.rb +18 -0
- data/examples/io/rack_server.rb +71 -0
- data/examples/io/{xx-system.rb → system.rb} +1 -1
- data/examples/io/{xx-tcpserver.rb → tcpserver.rb} +0 -0
- data/examples/io/{xx-tcpsocket.rb → tcpsocket.rb} +0 -0
- data/examples/io/tunnel.rb +6 -1
- data/examples/io/{xx-zip.rb → zip.rb} +0 -0
- data/examples/performance/fiber_transfer.rb +2 -1
- data/examples/performance/fs_read.rb +5 -6
- data/examples/{io/xx-switch.rb → performance/switch.rb} +2 -1
- data/examples/performance/thread-vs-fiber/{xx-httparty_multi.rb → httparty_multi.rb} +3 -4
- data/examples/performance/thread-vs-fiber/{xx-httparty_threaded.rb → httparty_threaded.rb} +0 -0
- data/examples/performance/thread-vs-fiber/polyphony_mt_server.rb +1 -1
- data/examples/performance/thread-vs-fiber/polyphony_server.rb +1 -1
- data/examples/performance/thread-vs-fiber/polyphony_server_read_loop.rb +1 -1
- data/examples/performance/thread-vs-fiber/threaded_server.rb +1 -5
- data/examples/performance/thread_pool_perf.rb +6 -7
- data/ext/polyphony/backend.h +40 -0
- data/ext/polyphony/event.c +3 -3
- data/ext/polyphony/extconf.rb +1 -1
- data/ext/polyphony/{libev_agent.c → libev_backend.c} +272 -265
- data/ext/polyphony/polyphony.c +4 -2
- data/ext/polyphony/polyphony.h +15 -28
- data/ext/polyphony/polyphony_ext.c +3 -4
- data/ext/polyphony/queue.c +32 -12
- data/ext/polyphony/ring_buffer.c +0 -1
- data/ext/polyphony/thread.c +58 -44
- data/lib/polyphony.rb +25 -38
- data/lib/polyphony/adapters/fs.rb +1 -1
- data/lib/polyphony/adapters/irb.rb +2 -17
- data/lib/polyphony/adapters/mysql2.rb +19 -0
- data/lib/polyphony/adapters/postgres.rb +5 -5
- data/lib/polyphony/adapters/process.rb +2 -2
- data/lib/polyphony/adapters/readline.rb +17 -0
- data/lib/polyphony/adapters/redis.rb +1 -1
- data/lib/polyphony/adapters/sequel.rb +45 -0
- data/lib/polyphony/core/exceptions.rb +11 -0
- data/lib/polyphony/core/global_api.rb +15 -10
- data/lib/polyphony/core/resource_pool.rb +20 -7
- data/lib/polyphony/core/sync.rb +46 -8
- data/lib/polyphony/core/throttler.rb +1 -1
- data/lib/polyphony/extensions/core.rb +38 -25
- data/lib/polyphony/extensions/fiber.rb +5 -1
- data/lib/polyphony/extensions/io.rb +45 -12
- data/lib/polyphony/extensions/openssl.rb +6 -6
- data/lib/polyphony/extensions/socket.rb +22 -23
- data/lib/polyphony/extensions/thread.rb +6 -5
- data/lib/polyphony/net.rb +2 -1
- data/lib/polyphony/version.rb +1 -1
- data/polyphony.gemspec +7 -3
- data/test/helper.rb +1 -1
- data/test/{test_agent.rb → test_backend.rb} +22 -22
- data/test/test_fiber.rb +21 -5
- data/test/test_io.rb +17 -1
- data/test/test_kernel.rb +5 -0
- data/test/test_resource_pool.rb +50 -16
- data/test/test_signal.rb +5 -29
- data/test/test_socket.rb +17 -0
- data/test/test_sync.rb +52 -0
- data/test/test_throttler.rb +1 -0
- metadata +125 -96
- data/.gitbook.yaml +0 -4
- data/examples/adapters/concurrent-ruby.rb +0 -9
- data/examples/core/04-handling-signals.rb +0 -19
- data/examples/core/xx-agent.rb +0 -102
- data/examples/core/xx-at_exit.rb +0 -29
- data/examples/core/xx-caller.rb +0 -12
- data/examples/core/xx-daemon.rb +0 -14
- data/examples/core/xx-deadlock.rb +0 -8
- data/examples/core/xx-deferring-an-operation.rb +0 -14
- data/examples/core/xx-exception-backtrace.rb +0 -40
- data/examples/core/xx-fork-cleanup.rb +0 -22
- data/examples/core/xx-fork-spin.rb +0 -42
- data/examples/core/xx-fork-terminate.rb +0 -27
- data/examples/core/xx-move_on.rb +0 -23
- data/examples/core/xx-queue-async.rb +0 -120
- data/examples/core/xx-readpartial.rb +0 -18
- data/examples/core/xx-signals.rb +0 -16
- data/examples/core/xx-sleep-forever.rb +0 -9
- data/examples/core/xx-sleeping.rb +0 -25
- data/examples/core/xx-snooze-starve.rb +0 -16
- data/examples/core/xx-spin-fork.rb +0 -49
- data/examples/core/xx-state-machine.rb +0 -51
- data/examples/core/xx-stop.rb +0 -20
- data/examples/core/xx-supervisors.rb +0 -21
- data/examples/core/xx-thread-selector-sleep.rb +0 -51
- data/examples/core/xx-thread-selector-snooze.rb +0 -46
- data/examples/core/xx-thread-snooze.rb +0 -34
- data/examples/core/xx-timer-gc.rb +0 -17
- data/examples/core/xx-trace.rb +0 -79
- data/examples/performance/xx-array.rb +0 -11
- data/examples/performance/xx-fiber-switch.rb +0 -9
- data/examples/performance/xx-snooze.rb +0 -15
- data/examples/xx-spin.rb +0 -32
|
@@ -67,6 +67,10 @@ module Polyphony
|
|
|
67
67
|
else RuntimeError.new
|
|
68
68
|
end
|
|
69
69
|
end
|
|
70
|
+
|
|
71
|
+
def interject(&block)
|
|
72
|
+
raise Polyphony::Interjection.new(block)
|
|
73
|
+
end
|
|
70
74
|
end
|
|
71
75
|
|
|
72
76
|
# Fiber supervision
|
|
@@ -224,7 +228,7 @@ module Polyphony
|
|
|
224
228
|
@results = @children.dup
|
|
225
229
|
@on_child_done = proc do |c, r|
|
|
226
230
|
@results[c] = r
|
|
227
|
-
|
|
231
|
+
schedule if @children.empty?
|
|
228
232
|
end
|
|
229
233
|
suspend
|
|
230
234
|
@on_child_done = nil
|
|
@@ -99,7 +99,7 @@ class ::IO
|
|
|
99
99
|
alias_method :orig_read, :read
|
|
100
100
|
def read(len = nil)
|
|
101
101
|
@read_buffer ||= +''
|
|
102
|
-
result = Thread.current.
|
|
102
|
+
result = Thread.current.backend.read(self, @read_buffer, len, true)
|
|
103
103
|
return nil unless result
|
|
104
104
|
|
|
105
105
|
already_read = @read_buffer
|
|
@@ -110,7 +110,7 @@ class ::IO
|
|
|
110
110
|
alias_method :orig_readpartial, :read
|
|
111
111
|
def readpartial(len, str = nil)
|
|
112
112
|
@read_buffer ||= +''
|
|
113
|
-
result = Thread.current.
|
|
113
|
+
result = Thread.current.backend.read(self, @read_buffer, len, false)
|
|
114
114
|
raise EOFError unless result
|
|
115
115
|
|
|
116
116
|
if str
|
|
@@ -124,12 +124,12 @@ class ::IO
|
|
|
124
124
|
|
|
125
125
|
alias_method :orig_write, :write
|
|
126
126
|
def write(str, *args)
|
|
127
|
-
Thread.current.
|
|
127
|
+
Thread.current.backend.write(self, str, *args)
|
|
128
128
|
end
|
|
129
129
|
|
|
130
130
|
alias_method :orig_write_chevron, :<<
|
|
131
131
|
def <<(str)
|
|
132
|
-
Thread.current.
|
|
132
|
+
Thread.current.backend.write(self, str)
|
|
133
133
|
self
|
|
134
134
|
end
|
|
135
135
|
|
|
@@ -163,20 +163,29 @@ class ::IO
|
|
|
163
163
|
# def putc(obj)
|
|
164
164
|
# end
|
|
165
165
|
|
|
166
|
+
LINEFEED = "\n"
|
|
167
|
+
LINEFEED_RE = /\n$/.freeze
|
|
168
|
+
|
|
166
169
|
alias_method :orig_puts, :puts
|
|
167
170
|
def puts(*args)
|
|
168
171
|
if args.empty?
|
|
169
|
-
write
|
|
172
|
+
write LINEFEED
|
|
170
173
|
return
|
|
171
174
|
end
|
|
172
175
|
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
176
|
+
idx = 0
|
|
177
|
+
while idx < args.size
|
|
178
|
+
arg = args[idx]
|
|
179
|
+
args[idx] = arg = arg.to_s unless arg.is_a?(String)
|
|
180
|
+
if arg =~ LINEFEED_RE
|
|
181
|
+
idx += 1
|
|
182
|
+
else
|
|
183
|
+
args.insert(idx + 1, LINEFEED)
|
|
184
|
+
idx += 2
|
|
185
|
+
end
|
|
178
186
|
end
|
|
179
|
-
|
|
187
|
+
|
|
188
|
+
write(*args)
|
|
180
189
|
nil
|
|
181
190
|
end
|
|
182
191
|
|
|
@@ -203,7 +212,7 @@ class ::IO
|
|
|
203
212
|
end
|
|
204
213
|
|
|
205
214
|
def read_loop(&block)
|
|
206
|
-
Thread.current.
|
|
215
|
+
Thread.current.backend.read_loop(self, &block)
|
|
207
216
|
end
|
|
208
217
|
|
|
209
218
|
# alias_method :orig_read, :read
|
|
@@ -218,4 +227,28 @@ class ::IO
|
|
|
218
227
|
# end
|
|
219
228
|
# outbuf
|
|
220
229
|
# end
|
|
230
|
+
|
|
231
|
+
def wait_readable(timeout = nil)
|
|
232
|
+
if timeout
|
|
233
|
+
move_on_after(timeout) do
|
|
234
|
+
Thread.current.backend.wait_io(self, false)
|
|
235
|
+
self
|
|
236
|
+
end
|
|
237
|
+
else
|
|
238
|
+
Thread.current.backend.wait_io(self, false)
|
|
239
|
+
self
|
|
240
|
+
end
|
|
241
|
+
end
|
|
242
|
+
|
|
243
|
+
def wait_writable(timeout = nil)
|
|
244
|
+
if timeout
|
|
245
|
+
move_on_after(timeout) do
|
|
246
|
+
Thread.current.backend.wait_io(self, true)
|
|
247
|
+
self
|
|
248
|
+
end
|
|
249
|
+
else
|
|
250
|
+
Thread.current.backend.wait_io(self, true)
|
|
251
|
+
self
|
|
252
|
+
end
|
|
253
|
+
end
|
|
221
254
|
end
|
|
@@ -28,8 +28,8 @@ class ::OpenSSL::SSL::SSLSocket
|
|
|
28
28
|
loop do
|
|
29
29
|
result = accept_nonblock(exception: false)
|
|
30
30
|
case result
|
|
31
|
-
when :wait_readable then Thread.current.
|
|
32
|
-
when :wait_writable then Thread.current.
|
|
31
|
+
when :wait_readable then Thread.current.backend.wait_io(io, false)
|
|
32
|
+
when :wait_writable then Thread.current.backend.wait_io(io, true)
|
|
33
33
|
else
|
|
34
34
|
return result
|
|
35
35
|
end
|
|
@@ -40,8 +40,8 @@ class ::OpenSSL::SSL::SSLSocket
|
|
|
40
40
|
def sysread(maxlen, buf = +'')
|
|
41
41
|
loop do
|
|
42
42
|
case (result = read_nonblock(maxlen, buf, exception: false))
|
|
43
|
-
when :wait_readable then Thread.current.
|
|
44
|
-
when :wait_writable then Thread.current.
|
|
43
|
+
when :wait_readable then Thread.current.backend.wait_io(io, false)
|
|
44
|
+
when :wait_writable then Thread.current.backend.wait_io(io, true)
|
|
45
45
|
else return result
|
|
46
46
|
end
|
|
47
47
|
end
|
|
@@ -51,8 +51,8 @@ class ::OpenSSL::SSL::SSLSocket
|
|
|
51
51
|
def syswrite(buf)
|
|
52
52
|
loop do
|
|
53
53
|
case (result = write_nonblock(buf, exception: false))
|
|
54
|
-
when :wait_readable then Thread.current.
|
|
55
|
-
when :wait_writable then Thread.current.
|
|
54
|
+
when :wait_readable then Thread.current.backend.wait_io(io, false)
|
|
55
|
+
when :wait_writable then Thread.current.backend.wait_io(io, true)
|
|
56
56
|
else
|
|
57
57
|
return result
|
|
58
58
|
end
|
|
@@ -5,34 +5,17 @@ require 'socket'
|
|
|
5
5
|
require_relative './io'
|
|
6
6
|
require_relative '../core/thread_pool'
|
|
7
7
|
|
|
8
|
-
class ::BasicSocket
|
|
9
|
-
def write_nonblock(string, _options = {})
|
|
10
|
-
write(string)
|
|
11
|
-
end
|
|
12
|
-
|
|
13
|
-
def read_nonblock(maxlen, str = nil, _options = {})
|
|
14
|
-
readpartial(maxlen, str)
|
|
15
|
-
end
|
|
16
|
-
end
|
|
17
|
-
|
|
18
8
|
# Socket overrides (eventually rewritten in C)
|
|
19
9
|
class ::Socket
|
|
20
10
|
def accept
|
|
21
|
-
Thread.current.
|
|
11
|
+
Thread.current.backend.accept(self)
|
|
22
12
|
end
|
|
23
13
|
|
|
24
14
|
NO_EXCEPTION = { exception: false }.freeze
|
|
25
15
|
|
|
26
|
-
def connect(
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
case result
|
|
30
|
-
when 0 then return
|
|
31
|
-
when :wait_writable then Thread.current.agent.wait_io(self, true)
|
|
32
|
-
else
|
|
33
|
-
raise IOError
|
|
34
|
-
end
|
|
35
|
-
end
|
|
16
|
+
def connect(addr)
|
|
17
|
+
addr = Addrinfo.new(addr) if addr.is_a?(String)
|
|
18
|
+
Thread.current.backend.connect(self, addr.ip_address, addr.ip_port)
|
|
36
19
|
end
|
|
37
20
|
|
|
38
21
|
def recv(maxlen, flags = 0, outbuf = nil)
|
|
@@ -41,7 +24,7 @@ class ::Socket
|
|
|
41
24
|
result = recv_nonblock(maxlen, flags, outbuf, **NO_EXCEPTION)
|
|
42
25
|
case result
|
|
43
26
|
when nil then raise IOError
|
|
44
|
-
when :wait_readable then Thread.current.
|
|
27
|
+
when :wait_readable then Thread.current.backend.wait_io(self, false)
|
|
45
28
|
else
|
|
46
29
|
return result
|
|
47
30
|
end
|
|
@@ -54,7 +37,7 @@ class ::Socket
|
|
|
54
37
|
result = recvfrom_nonblock(maxlen, flags, @read_buffer, **NO_EXCEPTION)
|
|
55
38
|
case result
|
|
56
39
|
when nil then raise IOError
|
|
57
|
-
when :wait_readable then Thread.current.
|
|
40
|
+
when :wait_readable then Thread.current.backend.wait_io(self, false)
|
|
58
41
|
else
|
|
59
42
|
return result
|
|
60
43
|
end
|
|
@@ -75,6 +58,10 @@ class ::Socket
|
|
|
75
58
|
setsockopt(Socket::SOL_SOCKET, Socket::SO_REUSEADDR, 1)
|
|
76
59
|
end
|
|
77
60
|
|
|
61
|
+
def reuse_port
|
|
62
|
+
setsockopt(::Socket::SOL_SOCKET, ::Socket::SO_REUSEPORT, 1)
|
|
63
|
+
end
|
|
64
|
+
|
|
78
65
|
class << self
|
|
79
66
|
alias_method :orig_getaddrinfo, :getaddrinfo
|
|
80
67
|
def getaddrinfo(*args)
|
|
@@ -128,6 +115,18 @@ class ::TCPSocket
|
|
|
128
115
|
def reuse_addr
|
|
129
116
|
setsockopt(::Socket::SOL_SOCKET, ::Socket::SO_REUSEADDR, 1)
|
|
130
117
|
end
|
|
118
|
+
|
|
119
|
+
def reuse_port
|
|
120
|
+
setsockopt(::Socket::SOL_SOCKET, ::Socket::SO_REUSEPORT, 1)
|
|
121
|
+
end
|
|
122
|
+
|
|
123
|
+
def read_nonblock(len, str = nil, exception: true)
|
|
124
|
+
@io.read_nonblock(len, str, exception: exception)
|
|
125
|
+
end
|
|
126
|
+
|
|
127
|
+
def write_nonblock(buf, exception: true)
|
|
128
|
+
@io.write_nonblock(buf, exception: exception)
|
|
129
|
+
end
|
|
131
130
|
end
|
|
132
131
|
|
|
133
132
|
# Override stock TCPServer code by encapsulating a Socket instance.
|
|
@@ -16,21 +16,22 @@ class ::Thread
|
|
|
16
16
|
end
|
|
17
17
|
|
|
18
18
|
def execute
|
|
19
|
-
#
|
|
19
|
+
# backend must be created in the context of the new thread, therefore it
|
|
20
20
|
# cannot be created in Thread#initialize
|
|
21
|
-
@
|
|
21
|
+
@backend = Polyphony::Backend.new
|
|
22
22
|
setup
|
|
23
23
|
@ready = true
|
|
24
24
|
result = @block.(*@args)
|
|
25
25
|
rescue Polyphony::MoveOn, Polyphony::Terminate => e
|
|
26
26
|
result = e.value
|
|
27
|
-
rescue Exception =>
|
|
27
|
+
rescue Exception => e
|
|
28
|
+
result = e
|
|
28
29
|
ensure
|
|
29
30
|
@ready = true
|
|
30
31
|
finalize(result)
|
|
31
32
|
end
|
|
32
33
|
|
|
33
|
-
attr_accessor :
|
|
34
|
+
attr_accessor :backend
|
|
34
35
|
|
|
35
36
|
def setup
|
|
36
37
|
@main_fiber = Fiber.current
|
|
@@ -48,7 +49,7 @@ class ::Thread
|
|
|
48
49
|
@result = result
|
|
49
50
|
signal_waiters(result)
|
|
50
51
|
end
|
|
51
|
-
@
|
|
52
|
+
@backend.finalize
|
|
52
53
|
end
|
|
53
54
|
|
|
54
55
|
def signal_waiters(result)
|
data/lib/polyphony/net.rb
CHANGED
|
@@ -35,9 +35,10 @@ module Polyphony
|
|
|
35
35
|
::Socket.new(:INET, :STREAM).tap do |s|
|
|
36
36
|
s.reuse_addr if opts[:reuse_addr]
|
|
37
37
|
s.dont_linger if opts[:dont_linger]
|
|
38
|
+
s.reuse_port if opts[:reuse_port]
|
|
38
39
|
addr = ::Socket.sockaddr_in(port, host)
|
|
39
40
|
s.bind(addr)
|
|
40
|
-
s.listen(
|
|
41
|
+
s.listen(opts[:backlog] || Socket::SOMAXCONN)
|
|
41
42
|
end
|
|
42
43
|
end
|
|
43
44
|
|
data/lib/polyphony/version.rb
CHANGED
data/polyphony.gemspec
CHANGED
|
@@ -21,17 +21,21 @@ Gem::Specification.new do |s|
|
|
|
21
21
|
s.require_paths = ["lib"]
|
|
22
22
|
s.required_ruby_version = '>= 2.6'
|
|
23
23
|
|
|
24
|
-
s.add_development_dependency '
|
|
25
|
-
s.add_development_dependency 'localhost', '1.1.4'
|
|
24
|
+
s.add_development_dependency 'rake-compiler', '1.0.5'
|
|
26
25
|
s.add_development_dependency 'minitest', '5.13.0'
|
|
27
26
|
s.add_development_dependency 'minitest-reporters', '1.4.2'
|
|
28
27
|
s.add_development_dependency 'simplecov', '0.17.1'
|
|
29
28
|
s.add_development_dependency 'rubocop', '0.85.1'
|
|
29
|
+
s.add_development_dependency 'pry', '0.13.1'
|
|
30
|
+
|
|
30
31
|
s.add_development_dependency 'pg', '1.1.4'
|
|
31
|
-
s.add_development_dependency 'rake-compiler', '1.0.5'
|
|
32
32
|
s.add_development_dependency 'redis', '4.1.0'
|
|
33
33
|
s.add_development_dependency 'hiredis', '0.6.3'
|
|
34
34
|
s.add_development_dependency 'http_parser.rb', '~>0.6.0'
|
|
35
|
+
s.add_development_dependency 'rack', '>=2.0.8', '<2.3.0'
|
|
36
|
+
s.add_development_dependency 'mysql2', '0.5.3'
|
|
37
|
+
s.add_development_dependency 'sequel', '5.34.0'
|
|
38
|
+
s.add_development_dependency 'httparty', '0.17.1'
|
|
35
39
|
|
|
36
40
|
s.add_development_dependency 'jekyll', '~>3.8.6'
|
|
37
41
|
s.add_development_dependency 'jekyll-remote-theme', '~>0.4.1'
|
data/test/helper.rb
CHANGED
|
@@ -31,7 +31,7 @@ class MiniTest::Test
|
|
|
31
31
|
end
|
|
32
32
|
Fiber.current.setup_main_fiber
|
|
33
33
|
Fiber.current.instance_variable_set(:@auto_watcher, nil)
|
|
34
|
-
Thread.current.
|
|
34
|
+
Thread.current.backend = Polyphony::Backend.new
|
|
35
35
|
sleep 0 # apparently this helps with timer accuracy
|
|
36
36
|
end
|
|
37
37
|
|
|
@@ -2,39 +2,39 @@
|
|
|
2
2
|
|
|
3
3
|
require_relative 'helper'
|
|
4
4
|
|
|
5
|
-
class
|
|
5
|
+
class BackendTest < MiniTest::Test
|
|
6
6
|
def setup
|
|
7
7
|
super
|
|
8
|
-
@
|
|
9
|
-
@
|
|
10
|
-
Thread.current.
|
|
8
|
+
@prev_backend = Thread.current.backend
|
|
9
|
+
@backend = Polyphony::Backend.new
|
|
10
|
+
Thread.current.backend = @backend
|
|
11
11
|
end
|
|
12
12
|
|
|
13
13
|
def teardown
|
|
14
|
-
@
|
|
15
|
-
Thread.current.
|
|
14
|
+
@backend.finalize
|
|
15
|
+
Thread.current.backend = @prev_backend
|
|
16
16
|
end
|
|
17
17
|
|
|
18
18
|
def test_sleep
|
|
19
19
|
count = 0
|
|
20
20
|
t0 = Time.now
|
|
21
21
|
spin {
|
|
22
|
-
@
|
|
22
|
+
@backend.sleep 0.01
|
|
23
23
|
count += 1
|
|
24
|
-
@
|
|
24
|
+
@backend.sleep 0.01
|
|
25
25
|
count += 1
|
|
26
|
-
@
|
|
26
|
+
@backend.sleep 0.01
|
|
27
27
|
count += 1
|
|
28
28
|
}.await
|
|
29
|
-
|
|
29
|
+
assert_in_delta 0.03, Time.now - t0, 0.005
|
|
30
30
|
assert_equal 3, count
|
|
31
31
|
end
|
|
32
32
|
|
|
33
33
|
def test_write_read_partial
|
|
34
34
|
i, o = IO.pipe
|
|
35
35
|
buf = +''
|
|
36
|
-
f = spin { @
|
|
37
|
-
@
|
|
36
|
+
f = spin { @backend.read(i, buf, 5, false) }
|
|
37
|
+
@backend.write(o, 'Hello world')
|
|
38
38
|
return_value = f.await
|
|
39
39
|
|
|
40
40
|
assert_equal 'Hello', buf
|
|
@@ -44,10 +44,10 @@ class AgentTest < MiniTest::Test
|
|
|
44
44
|
def test_write_read_to_eof_limited_buffer
|
|
45
45
|
i, o = IO.pipe
|
|
46
46
|
buf = +''
|
|
47
|
-
f = spin { @
|
|
48
|
-
@
|
|
47
|
+
f = spin { @backend.read(i, buf, 5, true) }
|
|
48
|
+
@backend.write(o, 'Hello')
|
|
49
49
|
snooze
|
|
50
|
-
@
|
|
50
|
+
@backend.write(o, ' world')
|
|
51
51
|
snooze
|
|
52
52
|
o.close
|
|
53
53
|
return_value = f.await
|
|
@@ -59,10 +59,10 @@ class AgentTest < MiniTest::Test
|
|
|
59
59
|
def test_write_read_to_eof
|
|
60
60
|
i, o = IO.pipe
|
|
61
61
|
buf = +''
|
|
62
|
-
f = spin { @
|
|
63
|
-
@
|
|
62
|
+
f = spin { @backend.read(i, buf, 10**6, true) }
|
|
63
|
+
@backend.write(o, 'Hello')
|
|
64
64
|
snooze
|
|
65
|
-
@
|
|
65
|
+
@backend.write(o, ' world')
|
|
66
66
|
snooze
|
|
67
67
|
o.close
|
|
68
68
|
return_value = f.await
|
|
@@ -73,11 +73,11 @@ class AgentTest < MiniTest::Test
|
|
|
73
73
|
|
|
74
74
|
def test_waitpid
|
|
75
75
|
pid = fork do
|
|
76
|
-
@
|
|
76
|
+
@backend.post_fork
|
|
77
77
|
exit(42)
|
|
78
78
|
end
|
|
79
79
|
|
|
80
|
-
result = @
|
|
80
|
+
result = @backend.waitpid(pid)
|
|
81
81
|
assert_equal [pid, 42], result
|
|
82
82
|
end
|
|
83
83
|
|
|
@@ -87,7 +87,7 @@ class AgentTest < MiniTest::Test
|
|
|
87
87
|
buf = []
|
|
88
88
|
spin do
|
|
89
89
|
buf << :ready
|
|
90
|
-
@
|
|
90
|
+
@backend.read_loop(i) { |d| buf << d }
|
|
91
91
|
buf << :done
|
|
92
92
|
end
|
|
93
93
|
|
|
@@ -107,7 +107,7 @@ class AgentTest < MiniTest::Test
|
|
|
107
107
|
|
|
108
108
|
clients = []
|
|
109
109
|
server_fiber = spin do
|
|
110
|
-
@
|
|
110
|
+
@backend.accept_loop(server) { |c| clients << c }
|
|
111
111
|
end
|
|
112
112
|
|
|
113
113
|
c1 = TCPSocket.new('127.0.0.1', 1234)
|
data/test/test_fiber.rb
CHANGED
|
@@ -352,7 +352,7 @@ class FiberTest < MiniTest::Test
|
|
|
352
352
|
result = []
|
|
353
353
|
f = Fiber.current.spin do
|
|
354
354
|
result << :start
|
|
355
|
-
result << Thread.current.
|
|
355
|
+
result << Thread.current.backend.sleep(1)
|
|
356
356
|
end
|
|
357
357
|
snooze
|
|
358
358
|
f.interrupt
|
|
@@ -413,6 +413,22 @@ class FiberTest < MiniTest::Test
|
|
|
413
413
|
f2&.stop
|
|
414
414
|
end
|
|
415
415
|
|
|
416
|
+
def test_interject
|
|
417
|
+
buf = []
|
|
418
|
+
f = spin_loop { sleep }
|
|
419
|
+
snooze
|
|
420
|
+
f.interject { buf << Fiber.current }
|
|
421
|
+
snooze
|
|
422
|
+
assert_equal [f], buf
|
|
423
|
+
assert_equal :waiting, f.state
|
|
424
|
+
|
|
425
|
+
f.interject { buf << :foo; raise Polyphony::MoveOn }
|
|
426
|
+
snooze
|
|
427
|
+
|
|
428
|
+
assert_equal [f, :foo], buf
|
|
429
|
+
assert_equal :dead, f.state
|
|
430
|
+
end
|
|
431
|
+
|
|
416
432
|
def test_state
|
|
417
433
|
counter = 0
|
|
418
434
|
f = spin do
|
|
@@ -625,7 +641,7 @@ class FiberTest < MiniTest::Test
|
|
|
625
641
|
end
|
|
626
642
|
end
|
|
627
643
|
sleep 0.1
|
|
628
|
-
f = spin { Thread.current.
|
|
644
|
+
f = spin { Thread.current.backend.waitpid(pid) }
|
|
629
645
|
o.close
|
|
630
646
|
Process.kill('INT', pid)
|
|
631
647
|
f.await
|
|
@@ -647,7 +663,7 @@ class FiberTest < MiniTest::Test
|
|
|
647
663
|
end
|
|
648
664
|
end
|
|
649
665
|
sleep 0.2
|
|
650
|
-
f = spin { Thread.current.
|
|
666
|
+
f = spin { Thread.current.backend.waitpid(pid) }
|
|
651
667
|
o.close
|
|
652
668
|
Process.kill('TERM', pid)
|
|
653
669
|
f.await
|
|
@@ -674,7 +690,7 @@ class FiberTest < MiniTest::Test
|
|
|
674
690
|
sleep 0.2
|
|
675
691
|
Process.kill('TERM', pid)
|
|
676
692
|
end
|
|
677
|
-
Thread.current.
|
|
693
|
+
Thread.current.backend.waitpid(pid)
|
|
678
694
|
klass = i.read
|
|
679
695
|
i.close
|
|
680
696
|
assert_equal 'Polyphony::Terminate', klass
|
|
@@ -692,7 +708,7 @@ class FiberTest < MiniTest::Test
|
|
|
692
708
|
|
|
693
709
|
f.schedule
|
|
694
710
|
f << 'bar'
|
|
695
|
-
snooze
|
|
711
|
+
2.times { snooze }
|
|
696
712
|
assert_equal ['bar'], buffer
|
|
697
713
|
end
|
|
698
714
|
end
|