polyphony 0.43.10 → 0.45.2

Sign up to get free protection for your applications and to get access to all the features.
Files changed (142) hide show
  1. checksums.yaml +4 -4
  2. data/.rubocop.yml +8 -1
  3. data/CHANGELOG.md +37 -0
  4. data/Gemfile.lock +16 -6
  5. data/Rakefile +1 -1
  6. data/TODO.md +15 -10
  7. data/docs/_posts/2020-07-26-polyphony-0.44.md +77 -0
  8. data/docs/api-reference/thread.md +1 -1
  9. data/docs/getting-started/overview.md +14 -14
  10. data/docs/getting-started/tutorial.md +1 -1
  11. data/examples/adapters/redis_client.rb +3 -1
  12. data/examples/adapters/redis_pubsub_perf.rb +11 -8
  13. data/examples/adapters/sequel_mysql.rb +23 -0
  14. data/examples/adapters/sequel_mysql_pool.rb +33 -0
  15. data/examples/adapters/sequel_pg.rb +24 -0
  16. data/examples/core/{02-awaiting-fibers.rb → await.rb} +0 -0
  17. data/examples/core/{xx-channels.rb → channels.rb} +0 -0
  18. data/examples/core/deferring-an-operation.rb +16 -0
  19. data/examples/core/{xx-erlang-style-genserver.rb → erlang-style-genserver.rb} +16 -9
  20. data/examples/core/{xx-forking.rb → forking.rb} +1 -1
  21. data/examples/core/handling-signals.rb +11 -0
  22. data/examples/core/{03-interrupting.rb → interrupt.rb} +0 -0
  23. data/examples/core/{xx-pingpong.rb → pingpong.rb} +7 -5
  24. data/examples/core/{xx-recurrent-timer.rb → recurrent-timer.rb} +1 -1
  25. data/examples/core/{xx-resource_delegate.rb → resource_delegate.rb} +3 -4
  26. data/examples/core/{01-spinning-up-fibers.rb → spin.rb} +1 -1
  27. data/examples/core/{xx-spin_error_backtrace.rb → spin_error_backtrace.rb} +1 -1
  28. data/examples/core/{xx-supervise-process.rb → supervise-process.rb} +8 -5
  29. data/examples/core/supervisor.rb +20 -0
  30. data/examples/core/{xx-thread-sleep.rb → thread-sleep.rb} +0 -0
  31. data/examples/core/{xx-thread_pool.rb → thread_pool.rb} +0 -0
  32. data/examples/core/{xx-throttling.rb → throttling.rb} +0 -0
  33. data/examples/core/{xx-timeout.rb → timeout.rb} +0 -0
  34. data/examples/core/{xx-using-a-mutex.rb → using-a-mutex.rb} +0 -0
  35. data/examples/core/{xx-worker-thread.rb → worker-thread.rb} +2 -2
  36. data/examples/io/{xx-backticks.rb → backticks.rb} +0 -0
  37. data/examples/io/{xx-echo_client.rb → echo_client.rb} +1 -1
  38. data/examples/io/{xx-echo_client_from_stdin.rb → echo_client_from_stdin.rb} +2 -2
  39. data/examples/io/{xx-echo_pipe.rb → echo_pipe.rb} +1 -1
  40. data/examples/io/{xx-echo_server.rb → echo_server.rb} +0 -0
  41. data/examples/io/{xx-echo_server_with_timeout.rb → echo_server_with_timeout.rb} +1 -1
  42. data/examples/io/{xx-echo_stdin.rb → echo_stdin.rb} +0 -0
  43. data/examples/io/{xx-happy-eyeballs.rb → happy-eyeballs.rb} +0 -0
  44. data/examples/io/{xx-httparty.rb → httparty.rb} +4 -13
  45. data/examples/io/{xx-irb.rb → irb.rb} +0 -0
  46. data/examples/io/{xx-net-http.rb → net-http.rb} +0 -0
  47. data/examples/io/{xx-open.rb → open.rb} +0 -0
  48. data/examples/io/pry.rb +18 -0
  49. data/examples/io/rack_server.rb +71 -0
  50. data/examples/io/{xx-system.rb → system.rb} +1 -1
  51. data/examples/io/{xx-tcpserver.rb → tcpserver.rb} +0 -0
  52. data/examples/io/{xx-tcpsocket.rb → tcpsocket.rb} +0 -0
  53. data/examples/io/tunnel.rb +6 -1
  54. data/examples/io/{xx-zip.rb → zip.rb} +0 -0
  55. data/examples/performance/fiber_transfer.rb +2 -1
  56. data/examples/performance/fs_read.rb +5 -6
  57. data/examples/{io/xx-switch.rb → performance/switch.rb} +2 -1
  58. data/examples/performance/thread-vs-fiber/{xx-httparty_multi.rb → httparty_multi.rb} +3 -4
  59. data/examples/performance/thread-vs-fiber/{xx-httparty_threaded.rb → httparty_threaded.rb} +0 -0
  60. data/examples/performance/thread-vs-fiber/polyphony_mt_server.rb +1 -1
  61. data/examples/performance/thread-vs-fiber/polyphony_server.rb +1 -1
  62. data/examples/performance/thread-vs-fiber/polyphony_server_read_loop.rb +1 -1
  63. data/examples/performance/thread-vs-fiber/threaded_server.rb +1 -5
  64. data/examples/performance/thread_pool_perf.rb +6 -7
  65. data/ext/polyphony/backend.h +40 -0
  66. data/ext/polyphony/event.c +3 -3
  67. data/ext/polyphony/extconf.rb +1 -1
  68. data/ext/polyphony/fiber.c +66 -6
  69. data/ext/polyphony/{libev_agent.c → libev_backend.c} +239 -235
  70. data/ext/polyphony/polyphony.c +3 -3
  71. data/ext/polyphony/polyphony.h +15 -23
  72. data/ext/polyphony/polyphony_ext.c +3 -4
  73. data/ext/polyphony/queue.c +25 -12
  74. data/ext/polyphony/ring_buffer.c +0 -1
  75. data/ext/polyphony/thread.c +36 -33
  76. data/lib/polyphony.rb +25 -38
  77. data/lib/polyphony/adapters/fs.rb +1 -1
  78. data/lib/polyphony/adapters/irb.rb +2 -17
  79. data/lib/polyphony/adapters/mysql2.rb +19 -0
  80. data/lib/polyphony/adapters/postgres.rb +5 -5
  81. data/lib/polyphony/adapters/process.rb +2 -2
  82. data/lib/polyphony/adapters/readline.rb +17 -0
  83. data/lib/polyphony/adapters/redis.rb +1 -1
  84. data/lib/polyphony/adapters/sequel.rb +45 -0
  85. data/lib/polyphony/core/exceptions.rb +11 -0
  86. data/lib/polyphony/core/global_api.rb +17 -12
  87. data/lib/polyphony/core/resource_pool.rb +20 -7
  88. data/lib/polyphony/core/sync.rb +46 -8
  89. data/lib/polyphony/core/throttler.rb +1 -1
  90. data/lib/polyphony/extensions/core.rb +38 -25
  91. data/lib/polyphony/extensions/fiber.rb +12 -45
  92. data/lib/polyphony/extensions/io.rb +45 -12
  93. data/lib/polyphony/extensions/openssl.rb +6 -6
  94. data/lib/polyphony/extensions/socket.rb +22 -15
  95. data/lib/polyphony/extensions/thread.rb +6 -5
  96. data/lib/polyphony/net.rb +2 -1
  97. data/lib/polyphony/version.rb +1 -1
  98. data/polyphony.gemspec +7 -3
  99. data/test/helper.rb +1 -1
  100. data/test/{test_agent.rb → test_backend.rb} +22 -22
  101. data/test/test_fiber.rb +28 -11
  102. data/test/test_io.rb +17 -1
  103. data/test/test_kernel.rb +5 -0
  104. data/test/test_resource_pool.rb +50 -16
  105. data/test/test_signal.rb +5 -29
  106. data/test/test_socket.rb +17 -0
  107. data/test/test_sync.rb +52 -0
  108. metadata +126 -98
  109. data/.gitbook.yaml +0 -4
  110. data/examples/adapters/concurrent-ruby.rb +0 -9
  111. data/examples/core/04-handling-signals.rb +0 -19
  112. data/examples/core/xx-agent.rb +0 -102
  113. data/examples/core/xx-at_exit.rb +0 -29
  114. data/examples/core/xx-caller.rb +0 -12
  115. data/examples/core/xx-daemon.rb +0 -14
  116. data/examples/core/xx-deadlock.rb +0 -8
  117. data/examples/core/xx-deferring-an-operation.rb +0 -14
  118. data/examples/core/xx-exception-backtrace.rb +0 -40
  119. data/examples/core/xx-fork-cleanup.rb +0 -22
  120. data/examples/core/xx-fork-spin.rb +0 -42
  121. data/examples/core/xx-fork-terminate.rb +0 -27
  122. data/examples/core/xx-move_on.rb +0 -23
  123. data/examples/core/xx-queue-async.rb +0 -120
  124. data/examples/core/xx-readpartial.rb +0 -18
  125. data/examples/core/xx-signals.rb +0 -16
  126. data/examples/core/xx-sleep-forever.rb +0 -9
  127. data/examples/core/xx-sleeping.rb +0 -25
  128. data/examples/core/xx-snooze-starve.rb +0 -16
  129. data/examples/core/xx-spin-fork.rb +0 -49
  130. data/examples/core/xx-state-machine.rb +0 -51
  131. data/examples/core/xx-stop.rb +0 -20
  132. data/examples/core/xx-supervisors.rb +0 -21
  133. data/examples/core/xx-thread-selector-sleep.rb +0 -51
  134. data/examples/core/xx-thread-selector-snooze.rb +0 -46
  135. data/examples/core/xx-thread-snooze.rb +0 -34
  136. data/examples/core/xx-timer-gc.rb +0 -17
  137. data/examples/core/xx-trace.rb +0 -79
  138. data/examples/performance/xx-array.rb +0 -11
  139. data/examples/performance/xx-fiber-switch.rb +0 -9
  140. data/examples/performance/xx-snooze.rb +0 -15
  141. data/examples/xx-spin.rb +0 -32
  142. data/ext/polyphony/agent.h +0 -39
@@ -7,20 +7,6 @@ require_relative '../core/exceptions'
7
7
  module Polyphony
8
8
  # Fiber control API
9
9
  module FiberControl
10
- def await
11
- if @running == false
12
- return @result.is_a?(Exception) ? (Kernel.raise @result) : @result
13
- end
14
-
15
- fiber = Fiber.current
16
- @waiting_fibers ||= {}
17
- @waiting_fibers[fiber] = true
18
- suspend
19
- ensure
20
- @waiting_fibers&.delete(fiber)
21
- end
22
- alias_method :join, :await
23
-
24
10
  def interrupt(value = nil)
25
11
  return if @running == false
26
12
 
@@ -67,6 +53,10 @@ module Polyphony
67
53
  else RuntimeError.new
68
54
  end
69
55
  end
56
+
57
+ def interject(&block)
58
+ raise Polyphony::Interjection.new(block)
59
+ end
70
60
  end
71
61
 
72
62
  # Fiber supervision
@@ -177,22 +167,6 @@ module Polyphony
177
167
  end
178
168
  end
179
169
 
180
- # Messaging functionality
181
- module FiberMessaging
182
- def <<(value)
183
- @mailbox << value
184
- end
185
- alias_method :send, :<<
186
-
187
- def receive
188
- @mailbox.shift
189
- end
190
-
191
- def receive_pending
192
- @mailbox.shift_all
193
- end
194
- end
195
-
196
170
  # Methods for controlling child fibers
197
171
  module ChildFiberControl
198
172
  def children
@@ -221,14 +195,14 @@ module Polyphony
221
195
  def await_all_children
222
196
  return unless @children && !@children.empty?
223
197
 
224
- @results = @children.dup
198
+ results = @children.dup
225
199
  @on_child_done = proc do |c, r|
226
- @results[c] = r
227
- self.schedule if @children.empty?
200
+ results[c] = r
201
+ schedule if @children.empty?
228
202
  end
229
203
  suspend
230
204
  @on_child_done = nil
231
- @results.values
205
+ results.values
232
206
  end
233
207
 
234
208
  def shutdown_all_children
@@ -245,7 +219,6 @@ module Polyphony
245
219
  @parent = parent
246
220
  @caller = caller
247
221
  @block = block
248
- @mailbox = Polyphony::Queue.new
249
222
  __fiber_trace__(:fiber_create, self)
250
223
  schedule
251
224
  end
@@ -275,7 +248,6 @@ module Polyphony
275
248
  # allows the fiber to be scheduled and to receive messages.
276
249
  def setup_raw
277
250
  @thread = Thread.current
278
- @mailbox = Polyphony::Queue.new
279
251
  end
280
252
 
281
253
  def setup_main_fiber
@@ -284,11 +256,10 @@ module Polyphony
284
256
  @thread = Thread.current
285
257
  @running = true
286
258
  @children&.clear
287
- @mailbox = Polyphony::Queue.new
288
259
  end
289
260
 
290
261
  def restart_self(first_value)
291
- @mailbox = Polyphony::Queue.new
262
+ @mailbox = nil
292
263
  @when_done_procs = nil
293
264
  @waiting_fibers = nil
294
265
  run(first_value)
@@ -320,13 +291,10 @@ module Polyphony
320
291
  def inform_dependants(result, uncaught_exception)
321
292
  @parent&.child_done(self, result)
322
293
  @when_done_procs&.each { |p| p.(result) }
323
- @waiting_fibers&.each_key do |f|
324
- f.schedule(result)
325
- end
326
- return unless uncaught_exception && !@waiting_fibers
327
-
294
+ @waiting_fibers&.each_key { |f| f.schedule(result) }
295
+
328
296
  # propagate unaught exception to parent
329
- @parent&.schedule(result)
297
+ @parent&.schedule(result) if uncaught_exception && !@waiting_fibers
330
298
  end
331
299
 
332
300
  def when_done(&block)
@@ -340,7 +308,6 @@ end
340
308
  class ::Fiber
341
309
  prepend Polyphony::FiberControl
342
310
  include Polyphony::FiberSupervision
343
- include Polyphony::FiberMessaging
344
311
  include Polyphony::ChildFiberControl
345
312
  include Polyphony::FiberLifeCycle
346
313
 
@@ -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.agent.read(self, @read_buffer, len, true)
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.agent.read(self, @read_buffer, len, false)
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.agent.write(self, str, *args)
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.agent.write(self, str)
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 "\n"
172
+ write LINEFEED
170
173
  return
171
174
  end
172
175
 
173
- strs = args.inject([]) do |m, a|
174
- a = a.to_s
175
- m << a
176
- m << "\n" unless a =~ /\n$/
177
- m
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
- write *strs
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.agent.read_loop(self, &block)
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.agent.wait_io(io, false)
32
- when :wait_writable then Thread.current.agent.wait_io(io, true)
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.agent.wait_io(io, false)
44
- when :wait_writable then Thread.current.agent.wait_io(io, true)
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.agent.wait_io(io, false)
55
- when :wait_writable then Thread.current.agent.wait_io(io, true)
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,26 +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.agent.accept(self)
11
+ Thread.current.backend.accept(self)
22
12
  end
23
13
 
24
14
  NO_EXCEPTION = { exception: false }.freeze
25
15
 
26
- def connect(remotesockaddr)
27
- Thread.current.agent.connect(self, remotesockaddr.ip_address, remotesockaddr.ip_port)
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)
28
19
  end
29
20
 
30
21
  def recv(maxlen, flags = 0, outbuf = nil)
@@ -33,7 +24,7 @@ class ::Socket
33
24
  result = recv_nonblock(maxlen, flags, outbuf, **NO_EXCEPTION)
34
25
  case result
35
26
  when nil then raise IOError
36
- when :wait_readable then Thread.current.agent.wait_io(self, false)
27
+ when :wait_readable then Thread.current.backend.wait_io(self, false)
37
28
  else
38
29
  return result
39
30
  end
@@ -46,7 +37,7 @@ class ::Socket
46
37
  result = recvfrom_nonblock(maxlen, flags, @read_buffer, **NO_EXCEPTION)
47
38
  case result
48
39
  when nil then raise IOError
49
- when :wait_readable then Thread.current.agent.wait_io(self, false)
40
+ when :wait_readable then Thread.current.backend.wait_io(self, false)
50
41
  else
51
42
  return result
52
43
  end
@@ -67,6 +58,10 @@ class ::Socket
67
58
  setsockopt(Socket::SOL_SOCKET, Socket::SO_REUSEADDR, 1)
68
59
  end
69
60
 
61
+ def reuse_port
62
+ setsockopt(::Socket::SOL_SOCKET, ::Socket::SO_REUSEPORT, 1)
63
+ end
64
+
70
65
  class << self
71
66
  alias_method :orig_getaddrinfo, :getaddrinfo
72
67
  def getaddrinfo(*args)
@@ -120,6 +115,18 @@ class ::TCPSocket
120
115
  def reuse_addr
121
116
  setsockopt(::Socket::SOL_SOCKET, ::Socket::SO_REUSEADDR, 1)
122
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
123
130
  end
124
131
 
125
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
- # agent must be created in the context of the new thread, therefore it
19
+ # backend must be created in the context of the new thread, therefore it
20
20
  # cannot be created in Thread#initialize
21
- @agent = Polyphony::Agent.new
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 => result
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 :agent
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
- @agent.finalize
52
+ @backend.finalize
52
53
  end
53
54
 
54
55
  def signal_waiters(result)
@@ -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(0)
41
+ s.listen(opts[:backlog] || Socket::SOMAXCONN)
41
42
  end
42
43
  end
43
44
 
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Polyphony
4
- VERSION = '0.43.10'
4
+ VERSION = '0.45.2'
5
5
  end
@@ -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 'httparty', '0.17.0'
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'
@@ -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.agent = Polyphony::Agent.new
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 AgentTest < MiniTest::Test
5
+ class BackendTest < MiniTest::Test
6
6
  def setup
7
7
  super
8
- @prev_agent = Thread.current.agent
9
- @agent = Polyphony::Agent.new
10
- Thread.current.agent = @agent
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
- @agent.finalize
15
- Thread.current.agent = @prev_agent
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
- @agent.sleep 0.01
22
+ @backend.sleep 0.01
23
23
  count += 1
24
- @agent.sleep 0.01
24
+ @backend.sleep 0.01
25
25
  count += 1
26
- @agent.sleep 0.01
26
+ @backend.sleep 0.01
27
27
  count += 1
28
28
  }.await
29
- assert Time.now - t0 >= 0.03
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 { @agent.read(i, buf, 5, false) }
37
- @agent.write(o, 'Hello world')
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 { @agent.read(i, buf, 5, true) }
48
- @agent.write(o, 'Hello')
47
+ f = spin { @backend.read(i, buf, 5, true) }
48
+ @backend.write(o, 'Hello')
49
49
  snooze
50
- @agent.write(o, ' world')
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 { @agent.read(i, buf, 10**6, true) }
63
- @agent.write(o, 'Hello')
62
+ f = spin { @backend.read(i, buf, 10**6, true) }
63
+ @backend.write(o, 'Hello')
64
64
  snooze
65
- @agent.write(o, ' world')
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
- @agent.post_fork
76
+ @backend.post_fork
77
77
  exit(42)
78
78
  end
79
79
 
80
- result = @agent.waitpid(pid)
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
- @agent.read_loop(i) { |d| buf << d }
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
- @agent.accept_loop(server) { |c| clients << c }
110
+ @backend.accept_loop(server) { |c| clients << c }
111
111
  end
112
112
 
113
113
  c1 = TCPSocket.new('127.0.0.1', 1234)