polyphony 0.47.5.1 → 0.50.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.
- checksums.yaml +4 -4
- data/CHANGELOG.md +29 -0
- data/Gemfile.lock +1 -1
- data/LICENSE +1 -1
- data/TODO.md +37 -17
- data/examples/core/nested.rb +21 -0
- data/examples/core/suspend.rb +13 -0
- data/examples/core/terminate_main_fiber.rb +12 -0
- data/examples/io/tcp_proxy.rb +32 -0
- data/examples/performance/line_splitting.rb +34 -0
- data/examples/performance/loop.rb +32 -0
- data/examples/performance/thread-vs-fiber/polyphony_server.rb +6 -2
- data/ext/polyphony/backend_common.h +3 -3
- data/ext/polyphony/backend_io_uring.c +29 -68
- data/ext/polyphony/backend_libev.c +18 -59
- data/ext/polyphony/event.c +1 -1
- data/ext/polyphony/fiber.c +2 -1
- data/ext/polyphony/polyphony.c +0 -2
- data/ext/polyphony/polyphony.h +6 -4
- data/ext/polyphony/queue.c +2 -2
- data/ext/polyphony/runqueue.c +6 -0
- data/ext/polyphony/runqueue_ring_buffer.c +9 -0
- data/ext/polyphony/runqueue_ring_buffer.h +1 -0
- data/ext/polyphony/thread.c +23 -28
- data/lib/polyphony.rb +2 -1
- data/lib/polyphony/adapters/postgres.rb +3 -3
- data/lib/polyphony/adapters/process.rb +2 -0
- data/lib/polyphony/core/exceptions.rb +1 -0
- data/lib/polyphony/core/global_api.rb +15 -3
- data/lib/polyphony/core/thread_pool.rb +3 -1
- data/lib/polyphony/core/throttler.rb +1 -1
- data/lib/polyphony/core/timer.rb +115 -0
- data/lib/polyphony/extensions/core.rb +4 -4
- data/lib/polyphony/extensions/fiber.rb +30 -13
- data/lib/polyphony/extensions/io.rb +8 -14
- data/lib/polyphony/extensions/openssl.rb +4 -4
- data/lib/polyphony/extensions/socket.rb +1 -1
- data/lib/polyphony/extensions/thread.rb +1 -2
- data/lib/polyphony/net.rb +3 -6
- data/lib/polyphony/version.rb +1 -1
- data/polyphony.gemspec +1 -1
- data/test/helper.rb +2 -2
- data/test/test_backend.rb +26 -1
- data/test/test_fiber.rb +95 -1
- data/test/test_global_api.rb +30 -0
- data/test/test_io.rb +26 -0
- data/test/test_signal.rb +1 -2
- data/test/test_socket.rb +5 -5
- data/test/test_supervise.rb +1 -1
- data/test/test_timer.rb +157 -0
- metadata +11 -4
- data/ext/polyphony/backend.h +0 -26
data/test/test_fiber.rb
CHANGED
@@ -349,6 +349,22 @@ class FiberTest < MiniTest::Test
|
|
349
349
|
assert_equal [:foo, :terminate], buffer
|
350
350
|
end
|
351
351
|
|
352
|
+
CMD_TERMINATE_MAIN_FIBER = <<~BASH
|
353
|
+
ruby -rbundler/setup -rpolyphony -e"spin { sleep 0.1; Thread.current.main_fiber.terminate }; begin; sleep; rescue Polyphony::Terminate; STDOUT << 'terminated'; end" 2>&1
|
354
|
+
BASH
|
355
|
+
|
356
|
+
CMD_TERMINATE_CHILD_FIBER = <<~BASH
|
357
|
+
ruby -rbundler/setup -rpolyphony -e"f = spin { sleep }; spin { sleep 0.1; f.terminate }; f.await" 2>&1
|
358
|
+
BASH
|
359
|
+
|
360
|
+
def test_terminate_main_fiber
|
361
|
+
output = `#{CMD_TERMINATE_CHILD_FIBER}`
|
362
|
+
assert_equal '', output
|
363
|
+
|
364
|
+
output = `#{CMD_TERMINATE_MAIN_FIBER}`
|
365
|
+
assert_equal 'terminated', output
|
366
|
+
end
|
367
|
+
|
352
368
|
def test_interrupt_timer
|
353
369
|
result = []
|
354
370
|
f = Fiber.current.spin do
|
@@ -639,7 +655,6 @@ class FiberTest < MiniTest::Test
|
|
639
655
|
i.close
|
640
656
|
f.await
|
641
657
|
rescue Exception => e
|
642
|
-
trace e
|
643
658
|
o << e.class.name
|
644
659
|
o.close
|
645
660
|
end
|
@@ -1038,3 +1053,82 @@ class RestartTest < MiniTest::Test
|
|
1038
1053
|
assert_equal [f, 'foo', 'bar', :done, f2, 'baz', 42, :done], buffer
|
1039
1054
|
end
|
1040
1055
|
end
|
1056
|
+
|
1057
|
+
class ChildrenTerminationTest < MiniTest::Test
|
1058
|
+
def test_shutdown_all_children
|
1059
|
+
f = spin do
|
1060
|
+
1000.times { spin { suspend } }
|
1061
|
+
suspend
|
1062
|
+
end
|
1063
|
+
|
1064
|
+
snooze
|
1065
|
+
assert_equal 1000, f.children.size
|
1066
|
+
|
1067
|
+
f.shutdown_all_children
|
1068
|
+
assert_equal 0, f.children.size
|
1069
|
+
end
|
1070
|
+
end
|
1071
|
+
|
1072
|
+
class GracefulTerminationTest < MiniTest::Test
|
1073
|
+
def test_graceful_termination
|
1074
|
+
buffer = []
|
1075
|
+
f = spin do
|
1076
|
+
buffer << 1
|
1077
|
+
snooze
|
1078
|
+
buffer << 2
|
1079
|
+
sleep 3
|
1080
|
+
buffer << 3
|
1081
|
+
ensure
|
1082
|
+
buffer << 4 if Fiber.current.graceful_shutdown?
|
1083
|
+
end
|
1084
|
+
|
1085
|
+
3.times { snooze }
|
1086
|
+
f.terminate(false)
|
1087
|
+
f.await
|
1088
|
+
assert_equal [1, 2], buffer
|
1089
|
+
|
1090
|
+
buffer = []
|
1091
|
+
f = spin do
|
1092
|
+
buffer << 1
|
1093
|
+
snooze
|
1094
|
+
buffer << 2
|
1095
|
+
sleep 3
|
1096
|
+
buffer << 3
|
1097
|
+
ensure
|
1098
|
+
buffer << 4 if Fiber.current.graceful_shutdown?
|
1099
|
+
end
|
1100
|
+
|
1101
|
+
3.times { snooze }
|
1102
|
+
f.terminate(true)
|
1103
|
+
f.await
|
1104
|
+
assert_equal [1, 2, 4], buffer
|
1105
|
+
end
|
1106
|
+
|
1107
|
+
def test_graceful_child_shutdown
|
1108
|
+
buffer = []
|
1109
|
+
f0 = spin do
|
1110
|
+
f1 = spin do
|
1111
|
+
sleep
|
1112
|
+
ensure
|
1113
|
+
buffer << 1 if Fiber.current.graceful_shutdown?
|
1114
|
+
end
|
1115
|
+
|
1116
|
+
f2 = spin do
|
1117
|
+
sleep
|
1118
|
+
ensure
|
1119
|
+
buffer << 2 if Fiber.current.graceful_shutdown?
|
1120
|
+
end
|
1121
|
+
|
1122
|
+
sleep
|
1123
|
+
ensure
|
1124
|
+
Fiber.current.terminate_all_children(true) if Fiber.current.graceful_shutdown?
|
1125
|
+
Fiber.current.await_all_children
|
1126
|
+
end
|
1127
|
+
|
1128
|
+
3.times { snooze }
|
1129
|
+
f0.terminate(true)
|
1130
|
+
f0.await
|
1131
|
+
|
1132
|
+
assert_equal [1, 2], buffer
|
1133
|
+
end
|
1134
|
+
end
|
data/test/test_global_api.rb
CHANGED
@@ -307,6 +307,36 @@ class SpinLoopTest < MiniTest::Test
|
|
307
307
|
f.stop
|
308
308
|
assert_in_range 1..3, counter
|
309
309
|
end
|
310
|
+
|
311
|
+
def test_spin_loop_break
|
312
|
+
i = 0
|
313
|
+
f = spin_loop do
|
314
|
+
i += 1
|
315
|
+
snooze
|
316
|
+
break if i >= 5
|
317
|
+
end
|
318
|
+
f.await
|
319
|
+
assert_equal 5, i
|
320
|
+
|
321
|
+
i = 0
|
322
|
+
f = spin_loop do
|
323
|
+
i += 1
|
324
|
+
snooze
|
325
|
+
raise StopIteration if i >= 5
|
326
|
+
end
|
327
|
+
f.await
|
328
|
+
assert_equal 5, i
|
329
|
+
end
|
330
|
+
|
331
|
+
def test_throttled_spin_loop_break
|
332
|
+
i = 0
|
333
|
+
f = spin_loop(rate: 100) do
|
334
|
+
i += 1
|
335
|
+
break if i >= 5
|
336
|
+
end
|
337
|
+
f.await
|
338
|
+
assert_equal 5, i
|
339
|
+
end
|
310
340
|
end
|
311
341
|
|
312
342
|
class SpinScopeTest < MiniTest::Test
|
data/test/test_io.rb
CHANGED
@@ -92,6 +92,32 @@ class IOTest < MiniTest::Test
|
|
92
92
|
assert_raises(EOFError) { i.readpartial(1) }
|
93
93
|
end
|
94
94
|
|
95
|
+
def test_gets
|
96
|
+
i, o = IO.pipe
|
97
|
+
|
98
|
+
buf = []
|
99
|
+
f = spin do
|
100
|
+
while (l = i.gets)
|
101
|
+
buf << l
|
102
|
+
end
|
103
|
+
end
|
104
|
+
|
105
|
+
snooze
|
106
|
+
assert_equal [], buf
|
107
|
+
|
108
|
+
o << 'fab'
|
109
|
+
snooze
|
110
|
+
assert_equal [], buf
|
111
|
+
|
112
|
+
o << "ulous\n"
|
113
|
+
10.times { snooze }
|
114
|
+
assert_equal ["fabulous\n"], buf
|
115
|
+
|
116
|
+
o.close
|
117
|
+
f.await
|
118
|
+
assert_equal ["fabulous\n"], buf
|
119
|
+
end
|
120
|
+
|
95
121
|
def test_getc
|
96
122
|
i, o = IO.pipe
|
97
123
|
|
data/test/test_signal.rb
CHANGED
data/test/test_socket.rb
CHANGED
@@ -60,18 +60,18 @@ class SocketTest < MiniTest::Test
|
|
60
60
|
end
|
61
61
|
|
62
62
|
class HTTPClientTest < MiniTest::Test
|
63
|
-
require 'httparty'
|
64
63
|
require 'json'
|
65
64
|
|
66
65
|
def test_http
|
67
|
-
res = HTTParty.get('http://
|
66
|
+
res = HTTParty.get('http://ipinfo.io/')
|
67
|
+
|
68
68
|
response = JSON.load(res.body)
|
69
|
-
assert_equal
|
69
|
+
assert_equal 'https://ipinfo.io/missingauth', response['readme']
|
70
70
|
end
|
71
71
|
|
72
72
|
def test_https
|
73
|
-
res = HTTParty.get('https://
|
73
|
+
res = HTTParty.get('https://ipinfo.io/')
|
74
74
|
response = JSON.load(res.body)
|
75
|
-
assert_equal
|
75
|
+
assert_equal 'https://ipinfo.io/missingauth', response['readme']
|
76
76
|
end
|
77
77
|
end
|
data/test/test_supervise.rb
CHANGED
data/test/test_timer.rb
ADDED
@@ -0,0 +1,157 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require_relative 'helper'
|
4
|
+
|
5
|
+
class TimerMoveOnAfterTest < MiniTest::Test
|
6
|
+
def setup
|
7
|
+
@timer = Polyphony::Timer.new(resolution: 0.01)
|
8
|
+
end
|
9
|
+
|
10
|
+
def teardown
|
11
|
+
@timer.stop
|
12
|
+
end
|
13
|
+
|
14
|
+
def test_timer_move_on_after
|
15
|
+
t0 = Time.now
|
16
|
+
v = @timer.move_on_after(0.1) do
|
17
|
+
sleep 1
|
18
|
+
:foo
|
19
|
+
end
|
20
|
+
t1 = Time.now
|
21
|
+
|
22
|
+
assert_in_range 0.1..0.15, t1 - t0
|
23
|
+
assert_nil v
|
24
|
+
end
|
25
|
+
|
26
|
+
def test_timer_move_on_after_with_value
|
27
|
+
t0 = Time.now
|
28
|
+
v = @timer.move_on_after(0.01, with_value: :bar) do
|
29
|
+
sleep 1
|
30
|
+
:foo
|
31
|
+
end
|
32
|
+
t1 = Time.now
|
33
|
+
|
34
|
+
assert_in_range 0.01..0.025, t1 - t0
|
35
|
+
assert_equal :bar, v
|
36
|
+
end
|
37
|
+
|
38
|
+
def test_timer_move_on_after_with_reset
|
39
|
+
t0 = Time.now
|
40
|
+
v = @timer.move_on_after(0.01, with_value: :moved_on) do
|
41
|
+
sleep 0.007
|
42
|
+
@timer.reset
|
43
|
+
sleep 0.007
|
44
|
+
@timer.reset
|
45
|
+
sleep 0.007
|
46
|
+
nil
|
47
|
+
end
|
48
|
+
t1 = Time.now
|
49
|
+
|
50
|
+
assert_nil v
|
51
|
+
assert_in_range 0.015..0.03, t1 - t0
|
52
|
+
end
|
53
|
+
end
|
54
|
+
|
55
|
+
class TimerCancelAfterTest < MiniTest::Test
|
56
|
+
def setup
|
57
|
+
@timer = Polyphony::Timer.new(resolution: 0.01)
|
58
|
+
end
|
59
|
+
|
60
|
+
def teardown
|
61
|
+
@timer.stop
|
62
|
+
end
|
63
|
+
|
64
|
+
def test_timer_cancel_after
|
65
|
+
t0 = Time.now
|
66
|
+
|
67
|
+
assert_raises Polyphony::Cancel do
|
68
|
+
@timer.cancel_after(0.01) do
|
69
|
+
sleep 1
|
70
|
+
:foo
|
71
|
+
end
|
72
|
+
end
|
73
|
+
t1 = Time.now
|
74
|
+
assert_in_range 0.01..0.03, t1 - t0
|
75
|
+
end
|
76
|
+
|
77
|
+
def test_timer_cancel_after_with_reset
|
78
|
+
t0 = Time.now
|
79
|
+
@timer.cancel_after(0.01) do
|
80
|
+
sleep 0.007
|
81
|
+
@timer.reset
|
82
|
+
sleep 0.007
|
83
|
+
end
|
84
|
+
t1 = Time.now
|
85
|
+
assert_in_range 0.013..0.024, t1 - t0
|
86
|
+
end
|
87
|
+
|
88
|
+
class CustomException < Exception
|
89
|
+
end
|
90
|
+
|
91
|
+
def test_timer_cancel_after_with_custom_exception
|
92
|
+
assert_raises CustomException do
|
93
|
+
@timer.cancel_after(0.01, with_exception: CustomException) do
|
94
|
+
sleep 1
|
95
|
+
:foo
|
96
|
+
end
|
97
|
+
end
|
98
|
+
|
99
|
+
begin
|
100
|
+
err = nil
|
101
|
+
@timer.cancel_after(0.01, with_exception: [CustomException, 'custom message']) do
|
102
|
+
sleep 1
|
103
|
+
:foo
|
104
|
+
end
|
105
|
+
rescue Exception => err
|
106
|
+
ensure
|
107
|
+
assert_kind_of CustomException, err
|
108
|
+
assert_equal 'custom message', err.message
|
109
|
+
end
|
110
|
+
|
111
|
+
|
112
|
+
begin
|
113
|
+
e = nil
|
114
|
+
@timer.cancel_after(0.01, with_exception: 'foo') do
|
115
|
+
sleep 1
|
116
|
+
:foo
|
117
|
+
end
|
118
|
+
rescue => e
|
119
|
+
ensure
|
120
|
+
assert_kind_of RuntimeError, e
|
121
|
+
assert_equal 'foo', e.message
|
122
|
+
end
|
123
|
+
end
|
124
|
+
end
|
125
|
+
|
126
|
+
class TimerMiscTest < MiniTest::Test
|
127
|
+
def setup
|
128
|
+
@timer = Polyphony::Timer.new(resolution: 0.001)
|
129
|
+
sleep 0
|
130
|
+
end
|
131
|
+
|
132
|
+
def teardown
|
133
|
+
@timer.stop
|
134
|
+
end
|
135
|
+
|
136
|
+
def test_timer_after
|
137
|
+
buffer = []
|
138
|
+
f = @timer.after(0.01) { buffer << 2 }
|
139
|
+
assert_kind_of Fiber, f
|
140
|
+
snooze
|
141
|
+
assert_equal [], buffer
|
142
|
+
sleep 0.1
|
143
|
+
p :post_sleep
|
144
|
+
assert_equal [2], buffer
|
145
|
+
end
|
146
|
+
|
147
|
+
def test_timer_every
|
148
|
+
buffer = []
|
149
|
+
t0 = Time.now
|
150
|
+
f = spin do
|
151
|
+
@timer.every(0.01) { buffer << 1 }
|
152
|
+
end
|
153
|
+
sleep 0.05
|
154
|
+
f.stop
|
155
|
+
assert_in_range 4..6, buffer.size
|
156
|
+
end
|
157
|
+
end
|
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.
|
4
|
+
version: 0.50.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Sharon Rosner
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2021-01-28 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: rake-compiler
|
@@ -269,7 +269,7 @@ dependencies:
|
|
269
269
|
- !ruby/object:Gem::Version
|
270
270
|
version: 0.3.0
|
271
271
|
description:
|
272
|
-
email:
|
272
|
+
email: sharon@noteflakes.com
|
273
273
|
executables: []
|
274
274
|
extensions:
|
275
275
|
- ext/polyphony/extconf.rb
|
@@ -353,6 +353,7 @@ files:
|
|
353
353
|
- examples/core/forking.rb
|
354
354
|
- examples/core/handling-signals.rb
|
355
355
|
- examples/core/interrupt.rb
|
356
|
+
- examples/core/nested.rb
|
356
357
|
- examples/core/pingpong.rb
|
357
358
|
- examples/core/recurrent-timer.rb
|
358
359
|
- examples/core/resource_delegate.rb
|
@@ -360,6 +361,8 @@ files:
|
|
360
361
|
- examples/core/spin_error_backtrace.rb
|
361
362
|
- examples/core/supervise-process.rb
|
362
363
|
- examples/core/supervisor.rb
|
364
|
+
- examples/core/suspend.rb
|
365
|
+
- examples/core/terminate_main_fiber.rb
|
363
366
|
- examples/core/thread-sleep.rb
|
364
367
|
- examples/core/thread_pool.rb
|
365
368
|
- examples/core/throttling.rb
|
@@ -383,6 +386,7 @@ files:
|
|
383
386
|
- examples/io/raw.rb
|
384
387
|
- examples/io/reline.rb
|
385
388
|
- examples/io/system.rb
|
389
|
+
- examples/io/tcp_proxy.rb
|
386
390
|
- examples/io/tcpserver.rb
|
387
391
|
- examples/io/tcpsocket.rb
|
388
392
|
- examples/io/tunnel.rb
|
@@ -391,6 +395,8 @@ files:
|
|
391
395
|
- examples/performance/fiber_resume.rb
|
392
396
|
- examples/performance/fiber_transfer.rb
|
393
397
|
- examples/performance/fs_read.rb
|
398
|
+
- examples/performance/line_splitting.rb
|
399
|
+
- examples/performance/loop.rb
|
394
400
|
- examples/performance/mem-usage.rb
|
395
401
|
- examples/performance/messaging.rb
|
396
402
|
- examples/performance/multi_snooze.rb
|
@@ -433,7 +439,6 @@ files:
|
|
433
439
|
- ext/liburing/setup.c
|
434
440
|
- ext/liburing/syscall.c
|
435
441
|
- ext/liburing/syscall.h
|
436
|
-
- ext/polyphony/backend.h
|
437
442
|
- ext/polyphony/backend_common.h
|
438
443
|
- ext/polyphony/backend_io_uring.c
|
439
444
|
- ext/polyphony/backend_io_uring_context.c
|
@@ -474,6 +479,7 @@ files:
|
|
474
479
|
- lib/polyphony/core/sync.rb
|
475
480
|
- lib/polyphony/core/thread_pool.rb
|
476
481
|
- lib/polyphony/core/throttler.rb
|
482
|
+
- lib/polyphony/core/timer.rb
|
477
483
|
- lib/polyphony/extensions/core.rb
|
478
484
|
- lib/polyphony/extensions/debug.rb
|
479
485
|
- lib/polyphony/extensions/fiber.rb
|
@@ -508,6 +514,7 @@ files:
|
|
508
514
|
- test/test_thread.rb
|
509
515
|
- test/test_thread_pool.rb
|
510
516
|
- test/test_throttler.rb
|
517
|
+
- test/test_timer.rb
|
511
518
|
- test/test_trace.rb
|
512
519
|
homepage: https://digital-fabric.github.io/polyphony
|
513
520
|
licenses:
|