polyphony 0.50.0 → 0.53.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.
Files changed (47) hide show
  1. checksums.yaml +4 -4
  2. data/.github/workflows/test.yml +1 -1
  3. data/CHANGELOG.md +30 -0
  4. data/Gemfile.lock +7 -68
  5. data/TODO.md +37 -6
  6. data/examples/core/forking.rb +2 -2
  7. data/examples/io/echo_server.rb +1 -0
  8. data/examples/io/tcp_proxy.rb +2 -2
  9. data/ext/polyphony/backend_common.h +57 -7
  10. data/ext/polyphony/backend_io_uring.c +232 -49
  11. data/ext/polyphony/backend_io_uring_context.c +1 -0
  12. data/ext/polyphony/backend_io_uring_context.h +1 -0
  13. data/ext/polyphony/backend_libev.c +355 -34
  14. data/ext/polyphony/event.c +1 -1
  15. data/ext/polyphony/extconf.rb +9 -2
  16. data/ext/polyphony/polyphony.c +102 -0
  17. data/ext/polyphony/polyphony.h +32 -2
  18. data/ext/polyphony/polyphony_ext.c +3 -0
  19. data/ext/polyphony/queue.c +1 -1
  20. data/ext/polyphony/runqueue.c +1 -1
  21. data/ext/polyphony/socket_extensions.c +33 -0
  22. data/ext/polyphony/thread.c +8 -2
  23. data/lib/polyphony/adapters/irb.rb +1 -1
  24. data/lib/polyphony/adapters/mysql2.rb +1 -1
  25. data/lib/polyphony/adapters/postgres.rb +5 -5
  26. data/lib/polyphony/adapters/process.rb +4 -4
  27. data/lib/polyphony/core/global_api.rb +5 -5
  28. data/lib/polyphony/core/sync.rb +1 -1
  29. data/lib/polyphony/core/throttler.rb +1 -1
  30. data/lib/polyphony/core/timer.rb +2 -2
  31. data/lib/polyphony/extensions/core.rb +1 -1
  32. data/lib/polyphony/extensions/io.rb +21 -22
  33. data/lib/polyphony/extensions/openssl.rb +6 -6
  34. data/lib/polyphony/extensions/socket.rb +56 -47
  35. data/lib/polyphony/version.rb +1 -1
  36. data/polyphony.gemspec +6 -5
  37. data/test/helper.rb +1 -1
  38. data/test/stress.rb +2 -0
  39. data/test/test_backend.rb +152 -5
  40. data/test/test_global_api.rb +2 -2
  41. data/test/test_io.rb +84 -1
  42. data/test/test_kernel.rb +1 -1
  43. data/test/test_signal.rb +1 -1
  44. data/test/test_socket.rb +61 -0
  45. data/test/test_thread.rb +4 -0
  46. data/test/test_timer.rb +1 -1
  47. metadata +19 -60
@@ -160,10 +160,10 @@ class MoveOnAfterTest < MiniTest::Test
160
160
  end
161
161
  t1 = Time.now
162
162
  assert_equal 1, o
163
- assert_in_range 0.008..0.013, t1 - t0
163
+ assert_in_range 0.008..0.015, t1 - t0
164
164
 
165
165
  t0 = Time.now
166
- o = move_on_after(0.02, with_value: 1) do
166
+ o = move_on_after(0.05, with_value: 1) do
167
167
  move_on_after(0.01, with_value: 2) do
168
168
  sleep 1
169
169
  end
data/test/test_io.rb CHANGED
@@ -1,6 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  require_relative 'helper'
4
+ require 'msgpack'
4
5
 
5
6
  class IOTest < MiniTest::Test
6
7
  def setup
@@ -110,7 +111,7 @@ class IOTest < MiniTest::Test
110
111
  assert_equal [], buf
111
112
 
112
113
  o << "ulous\n"
113
- 10.times { snooze }
114
+ sleep 0.01
114
115
  assert_equal ["fabulous\n"], buf
115
116
 
116
117
  o.close
@@ -173,6 +174,88 @@ class IOTest < MiniTest::Test
173
174
 
174
175
  assert_equal 'hello: world', buf
175
176
  end
177
+
178
+ def test_feed_loop_with_block
179
+ i, o = IO.pipe
180
+ unpacker = MessagePack::Unpacker.new
181
+ buffer = []
182
+ reader = spin do
183
+ i.feed_loop(unpacker, :feed_each) { |msg| buffer << msg }
184
+ end
185
+ o << 'foo'.to_msgpack
186
+ sleep 0.01
187
+ assert_equal ['foo'], buffer
188
+
189
+ o << 'bar'.to_msgpack
190
+ sleep 0.01
191
+ assert_equal ['foo', 'bar'], buffer
192
+
193
+ o << 'baz'.to_msgpack
194
+ sleep 0.01
195
+ assert_equal ['foo', 'bar', 'baz'], buffer
196
+ end
197
+
198
+ class Receiver1
199
+ attr_reader :buffer
200
+
201
+ def initialize
202
+ @buffer = []
203
+ end
204
+
205
+ def recv(obj)
206
+ @buffer << obj
207
+ end
208
+ end
209
+
210
+ def test_feed_loop_without_block
211
+ i, o = IO.pipe
212
+ receiver = Receiver1.new
213
+ reader = spin do
214
+ i.feed_loop(receiver, :recv)
215
+ end
216
+ o << 'foo'
217
+ sleep 0.01
218
+ assert_equal ['foo'], receiver.buffer
219
+
220
+ o << 'bar'
221
+ sleep 0.01
222
+ assert_equal ['foo', 'bar'], receiver.buffer
223
+
224
+ o << 'baz'
225
+ sleep 0.01
226
+ assert_equal ['foo', 'bar', 'baz'], receiver.buffer
227
+ end
228
+
229
+ class Receiver2
230
+ attr_reader :buffer
231
+
232
+ def initialize
233
+ @buffer = []
234
+ end
235
+
236
+ def call(obj)
237
+ @buffer << obj
238
+ end
239
+ end
240
+
241
+ def test_feed_loop_without_method
242
+ i, o = IO.pipe
243
+ receiver = Receiver2.new
244
+ reader = spin do
245
+ i.feed_loop(receiver)
246
+ end
247
+ o << 'foo'
248
+ sleep 0.01
249
+ assert_equal ['foo'], receiver.buffer
250
+
251
+ o << 'bar'
252
+ sleep 0.01
253
+ assert_equal ['foo', 'bar'], receiver.buffer
254
+
255
+ o << 'baz'
256
+ sleep 0.01
257
+ assert_equal ['foo', 'bar', 'baz'], receiver.buffer
258
+ end
176
259
  end
177
260
 
178
261
  class IOClassMethodsTest < MiniTest::Test
data/test/test_kernel.rb CHANGED
@@ -21,7 +21,7 @@ class KernelTest < MiniTest::Test
21
21
 
22
22
  def test_Kernel_system_singleton_method
23
23
  assert_equal true, Kernel.system("which ruby > /dev/null 2>&1")
24
- assert_equal false, Kernel.system("which rruubbyy > /dev/null 2>&1")
24
+ assert_equal false, Kernel.system("azertyuiop > /dev/null 2>&1")
25
25
  end
26
26
 
27
27
  def patch_open3
data/test/test_signal.rb CHANGED
@@ -23,7 +23,7 @@ class SignalTrapTest < Minitest::Test
23
23
  ensure
24
24
  o.close
25
25
  end
26
- sleep 0.01
26
+ sleep 0.1
27
27
  o.close
28
28
  Process.kill('INT', pid)
29
29
  Thread.current.backend.waitpid(pid)
data/test/test_socket.rb CHANGED
@@ -2,6 +2,7 @@
2
2
 
3
3
  require_relative 'helper'
4
4
  require 'fileutils'
5
+ require 'msgpack'
5
6
 
6
7
  class SocketTest < MiniTest::Test
7
8
  def setup
@@ -33,6 +34,66 @@ class SocketTest < MiniTest::Test
33
34
  server&.close
34
35
  end
35
36
 
37
+ # sending multiple strings at once
38
+ def test_sendv
39
+ port = rand(1234..5678)
40
+ server = TCPServer.new('127.0.0.1', port)
41
+
42
+ server_fiber = spin do
43
+ while (socket = server.accept)
44
+ spin do
45
+ while (data = socket.gets(8192))
46
+ socket.write("you said ", data)
47
+ end
48
+ end
49
+ end
50
+ end
51
+
52
+ snooze
53
+ client = TCPSocket.new('127.0.0.1', port)
54
+ client.write("1234\n")
55
+ assert_equal "you said 1234\n", client.recv(8192)
56
+ client.close
57
+ ensure
58
+ server_fiber&.stop
59
+ server_fiber&.await
60
+ server&.close
61
+ end
62
+
63
+
64
+ def test_feed_loop
65
+ port = rand(1234..5678)
66
+ server = TCPServer.new('127.0.0.1', port)
67
+
68
+ server_fiber = spin do
69
+ reader = MessagePack::Unpacker.new
70
+ while (socket = server.accept)
71
+ spin do
72
+ socket.feed_loop(reader, :feed_each) do |msg|
73
+ msg = { 'result' => msg['x'] + msg['y'] }
74
+ socket << msg.to_msgpack
75
+ end
76
+ end
77
+ end
78
+ end
79
+
80
+ snooze
81
+ client = TCPSocket.new('127.0.0.1', port)
82
+ reader = MessagePack::Unpacker.new
83
+ client << { 'x' => 13, 'y' => 14 }.to_msgpack
84
+ result = nil
85
+ client.feed_loop(reader, :feed_each) do |msg|
86
+ result = msg
87
+ break
88
+ end
89
+ assert_equal({ 'result' => 27}, result)
90
+ client.close
91
+ ensure
92
+ server_fiber&.stop
93
+ server_fiber&.await
94
+ server&.close
95
+ end
96
+
36
97
  def test_unix_socket
37
98
  path = '/tmp/test_unix_socket'
38
99
  FileUtils.rm(path) rescue nil
data/test/test_thread.rb CHANGED
@@ -124,6 +124,10 @@ class ThreadTest < MiniTest::Test
124
124
  t&.join
125
125
  end
126
126
 
127
+ def test_backend_class_method
128
+ assert_equal Thread.current.backend, Thread.backend
129
+ end
130
+
127
131
  def test_that_suspend_returns_immediately_if_no_watchers
128
132
  records = []
129
133
  t = Polyphony::Trace.new(:fiber_all) do |r|
data/test/test_timer.rb CHANGED
@@ -82,7 +82,7 @@ class TimerCancelAfterTest < MiniTest::Test
82
82
  sleep 0.007
83
83
  end
84
84
  t1 = Time.now
85
- assert_in_range 0.013..0.024, t1 - t0
85
+ assert_in_range 0.012..0.024, t1 - t0
86
86
  end
87
87
 
88
88
  class CustomException < Exception
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: polyphony
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.50.0
4
+ version: 0.53.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Sharon Rosner
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2021-01-28 00:00:00.000000000 Z
11
+ date: 2021-05-10 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rake-compiler
@@ -30,14 +30,14 @@ dependencies:
30
30
  requirements:
31
31
  - - '='
32
32
  - !ruby/object:Gem::Version
33
- version: 5.13.0
33
+ version: 5.14.4
34
34
  type: :development
35
35
  prerelease: false
36
36
  version_requirements: !ruby/object:Gem::Requirement
37
37
  requirements:
38
38
  - - '='
39
39
  - !ruby/object:Gem::Version
40
- version: 5.13.0
40
+ version: 5.14.4
41
41
  - !ruby/object:Gem::Dependency
42
42
  name: minitest-reporters
43
43
  requirement: !ruby/object:Gem::Requirement
@@ -94,6 +94,20 @@ dependencies:
94
94
  - - '='
95
95
  - !ruby/object:Gem::Version
96
96
  version: 0.13.1
97
+ - !ruby/object:Gem::Dependency
98
+ name: msgpack
99
+ requirement: !ruby/object:Gem::Requirement
100
+ requirements:
101
+ - - '='
102
+ - !ruby/object:Gem::Version
103
+ version: 1.4.2
104
+ type: :development
105
+ prerelease: false
106
+ version_requirements: !ruby/object:Gem::Requirement
107
+ requirements:
108
+ - - '='
109
+ - !ruby/object:Gem::Version
110
+ version: 1.4.2
97
111
  - !ruby/object:Gem::Dependency
98
112
  name: pg
99
113
  requirement: !ruby/object:Gem::Requirement
@@ -212,62 +226,6 @@ dependencies:
212
226
  - - '='
213
227
  - !ruby/object:Gem::Version
214
228
  version: 0.17.1
215
- - !ruby/object:Gem::Dependency
216
- name: jekyll
217
- requirement: !ruby/object:Gem::Requirement
218
- requirements:
219
- - - "~>"
220
- - !ruby/object:Gem::Version
221
- version: 3.8.6
222
- type: :development
223
- prerelease: false
224
- version_requirements: !ruby/object:Gem::Requirement
225
- requirements:
226
- - - "~>"
227
- - !ruby/object:Gem::Version
228
- version: 3.8.6
229
- - !ruby/object:Gem::Dependency
230
- name: jekyll-remote-theme
231
- requirement: !ruby/object:Gem::Requirement
232
- requirements:
233
- - - "~>"
234
- - !ruby/object:Gem::Version
235
- version: 0.4.1
236
- type: :development
237
- prerelease: false
238
- version_requirements: !ruby/object:Gem::Requirement
239
- requirements:
240
- - - "~>"
241
- - !ruby/object:Gem::Version
242
- version: 0.4.1
243
- - !ruby/object:Gem::Dependency
244
- name: jekyll-seo-tag
245
- requirement: !ruby/object:Gem::Requirement
246
- requirements:
247
- - - "~>"
248
- - !ruby/object:Gem::Version
249
- version: 2.6.1
250
- type: :development
251
- prerelease: false
252
- version_requirements: !ruby/object:Gem::Requirement
253
- requirements:
254
- - - "~>"
255
- - !ruby/object:Gem::Version
256
- version: 2.6.1
257
- - !ruby/object:Gem::Dependency
258
- name: just-the-docs
259
- requirement: !ruby/object:Gem::Requirement
260
- requirements:
261
- - - "~>"
262
- - !ruby/object:Gem::Version
263
- version: 0.3.0
264
- type: :development
265
- prerelease: false
266
- version_requirements: !ruby/object:Gem::Requirement
267
- requirements:
268
- - - "~>"
269
- - !ruby/object:Gem::Version
270
- version: 0.3.0
271
229
  description:
272
230
  email: sharon@noteflakes.com
273
231
  executables: []
@@ -460,6 +418,7 @@ files:
460
418
  - ext/polyphony/runqueue.c
461
419
  - ext/polyphony/runqueue_ring_buffer.c
462
420
  - ext/polyphony/runqueue_ring_buffer.h
421
+ - ext/polyphony/socket_extensions.c
463
422
  - ext/polyphony/thread.c
464
423
  - ext/polyphony/tracing.c
465
424
  - lib/polyphony.rb