polyphony 0.47.3 → 0.49.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 (42) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +318 -295
  3. data/Gemfile.lock +1 -1
  4. data/LICENSE +1 -1
  5. data/TODO.md +40 -27
  6. data/examples/core/supervisor.rb +3 -3
  7. data/examples/core/worker-thread.rb +3 -4
  8. data/examples/io/tcp_proxy.rb +32 -0
  9. data/examples/io/unix_socket.rb +26 -0
  10. data/examples/performance/line_splitting.rb +34 -0
  11. data/examples/performance/loop.rb +32 -0
  12. data/examples/performance/thread-vs-fiber/polyphony_server.rb +6 -0
  13. data/ext/polyphony/backend_common.h +2 -2
  14. data/ext/polyphony/backend_io_uring.c +42 -83
  15. data/ext/polyphony/backend_libev.c +32 -77
  16. data/ext/polyphony/event.c +1 -1
  17. data/ext/polyphony/polyphony.c +0 -2
  18. data/ext/polyphony/polyphony.h +5 -4
  19. data/ext/polyphony/queue.c +2 -2
  20. data/ext/polyphony/thread.c +9 -28
  21. data/lib/polyphony.rb +1 -0
  22. data/lib/polyphony/adapters/postgres.rb +3 -3
  23. data/lib/polyphony/core/global_api.rb +14 -2
  24. data/lib/polyphony/core/thread_pool.rb +3 -1
  25. data/lib/polyphony/core/throttler.rb +1 -1
  26. data/lib/polyphony/core/timer.rb +72 -0
  27. data/lib/polyphony/extensions/fiber.rb +32 -8
  28. data/lib/polyphony/extensions/io.rb +8 -14
  29. data/lib/polyphony/extensions/openssl.rb +4 -4
  30. data/lib/polyphony/extensions/socket.rb +68 -16
  31. data/lib/polyphony/version.rb +1 -1
  32. data/polyphony.gemspec +1 -1
  33. data/test/helper.rb +1 -0
  34. data/test/test_backend.rb +1 -1
  35. data/test/test_fiber.rb +64 -1
  36. data/test/test_global_api.rb +30 -0
  37. data/test/test_io.rb +26 -0
  38. data/test/test_socket.rb +32 -6
  39. data/test/test_supervise.rb +2 -1
  40. data/test/test_timer.rb +122 -0
  41. metadata +9 -4
  42. data/ext/polyphony/backend.h +0 -26
@@ -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
@@ -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
 
@@ -1,6 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  require_relative 'helper'
4
+ require 'fileutils'
4
5
 
5
6
  class SocketTest < MiniTest::Test
6
7
  def setup
@@ -24,7 +25,32 @@ class SocketTest < MiniTest::Test
24
25
  snooze
25
26
  client = TCPSocket.new('127.0.0.1', port)
26
27
  client.write("1234\n")
27
- assert_equal "1234\n", client.readpartial(8192)
28
+ assert_equal "1234\n", client.recv(8192)
29
+ client.close
30
+ ensure
31
+ server_fiber&.stop
32
+ server_fiber&.await
33
+ server&.close
34
+ end
35
+
36
+ def test_unix_socket
37
+ path = '/tmp/test_unix_socket'
38
+ FileUtils.rm(path) rescue nil
39
+ server = UNIXServer.new(path)
40
+ server_fiber = spin do
41
+ server.accept_loop do |socket|
42
+ spin do
43
+ while (data = socket.gets(8192))
44
+ socket << data
45
+ end
46
+ end
47
+ end
48
+ end
49
+
50
+ snooze
51
+ client = UNIXSocket.new(path)
52
+ client.write("1234\n")
53
+ assert_equal "1234\n", client.recv(8192)
28
54
  client.close
29
55
  ensure
30
56
  server_fiber&.stop
@@ -34,18 +60,18 @@ class SocketTest < MiniTest::Test
34
60
  end
35
61
 
36
62
  class HTTPClientTest < MiniTest::Test
37
- require 'httparty'
38
63
  require 'json'
39
64
 
40
65
  def test_http
41
- res = HTTParty.get('http://worldtimeapi.org/api/timezone/Europe/Paris')
66
+ res = HTTParty.get('http://ipinfo.io/')
67
+
42
68
  response = JSON.load(res.body)
43
- assert_equal "CET", response['abbreviation']
69
+ assert_equal 'https://ipinfo.io/missingauth', response['readme']
44
70
  end
45
71
 
46
72
  def test_https
47
- res = HTTParty.get('https://worldtimeapi.org/api/timezone/Europe/Paris')
73
+ res = HTTParty.get('https://ipinfo.io/')
48
74
  response = JSON.load(res.body)
49
- assert_equal "CET", response['abbreviation']
75
+ assert_equal 'https://ipinfo.io/missingauth', response['readme']
50
76
  end
51
77
  end
@@ -20,9 +20,10 @@ class SuperviseTest < MiniTest::Test
20
20
 
21
21
  f2 << 'bar'
22
22
  f2.await
23
+ assert_equal :runnable, p.state
23
24
  snooze
24
25
 
25
- assert_equal :waiting, p.state
26
+ assert_equal :dead, p.state
26
27
  end
27
28
 
28
29
  def test_supervise_with_restart
@@ -0,0 +1,122 @@
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_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_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.02, t1 - t0
35
+ assert_equal :bar, v
36
+ end
37
+
38
+ def test_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
+ nil
45
+ end
46
+ t1 = Time.now
47
+
48
+ assert_nil v
49
+ assert_in_range 0.014..0.02, t1 - t0
50
+ end
51
+ end
52
+
53
+ class CancelAfterTest < MiniTest::Test
54
+ def setup
55
+ @timer = Polyphony::Timer.new(resolution: 0.01)
56
+ end
57
+
58
+ def teardown
59
+ @timer.stop
60
+ end
61
+
62
+ def test_cancel_after
63
+ t0 = Time.now
64
+
65
+ assert_raises Polyphony::Cancel do
66
+ @timer.cancel_after(0.01) do
67
+ sleep 1
68
+ :foo
69
+ end
70
+ end
71
+ t1 = Time.now
72
+ assert_in_range 0.01..0.02, t1 - t0
73
+ end
74
+
75
+ def test_cancel_after_with_reset
76
+ t0 = Time.now
77
+ @timer.cancel_after(0.01) do
78
+ sleep 0.007
79
+ @timer.reset
80
+ sleep 0.007
81
+ end
82
+ t1 = Time.now
83
+ assert_in_range 0.014..0.024, t1 - t0
84
+ end
85
+
86
+ class CustomException < Exception
87
+ end
88
+
89
+ def test_cancel_after_with_custom_exception
90
+ assert_raises CustomException do
91
+ @timer.cancel_after(0.01, with_exception: CustomException) do
92
+ sleep 1
93
+ :foo
94
+ end
95
+ end
96
+
97
+ begin
98
+ err = nil
99
+ @timer.cancel_after(0.01, with_exception: [CustomException, 'custom message']) do
100
+ sleep 1
101
+ :foo
102
+ end
103
+ rescue Exception => err
104
+ ensure
105
+ assert_kind_of CustomException, err
106
+ assert_equal 'custom message', err.message
107
+ end
108
+
109
+
110
+ begin
111
+ e = nil
112
+ @timer.cancel_after(0.01, with_exception: 'foo') do
113
+ sleep 1
114
+ :foo
115
+ end
116
+ rescue => e
117
+ ensure
118
+ assert_kind_of RuntimeError, e
119
+ assert_equal 'foo', e.message
120
+ end
121
+ end
122
+ 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.47.3
4
+ version: 0.49.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: 2020-11-12 00:00:00.000000000 Z
11
+ date: 2021-01-11 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: ciconia@gmail.com
272
+ email: sharon@noteflakes.com
273
273
  executables: []
274
274
  extensions:
275
275
  - ext/polyphony/extconf.rb
@@ -383,13 +383,17 @@ files:
383
383
  - examples/io/raw.rb
384
384
  - examples/io/reline.rb
385
385
  - examples/io/system.rb
386
+ - examples/io/tcp_proxy.rb
386
387
  - examples/io/tcpserver.rb
387
388
  - examples/io/tcpsocket.rb
388
389
  - examples/io/tunnel.rb
390
+ - examples/io/unix_socket.rb
389
391
  - examples/io/zip.rb
390
392
  - examples/performance/fiber_resume.rb
391
393
  - examples/performance/fiber_transfer.rb
392
394
  - examples/performance/fs_read.rb
395
+ - examples/performance/line_splitting.rb
396
+ - examples/performance/loop.rb
393
397
  - examples/performance/mem-usage.rb
394
398
  - examples/performance/messaging.rb
395
399
  - examples/performance/multi_snooze.rb
@@ -432,7 +436,6 @@ files:
432
436
  - ext/liburing/setup.c
433
437
  - ext/liburing/syscall.c
434
438
  - ext/liburing/syscall.h
435
- - ext/polyphony/backend.h
436
439
  - ext/polyphony/backend_common.h
437
440
  - ext/polyphony/backend_io_uring.c
438
441
  - ext/polyphony/backend_io_uring_context.c
@@ -473,6 +476,7 @@ files:
473
476
  - lib/polyphony/core/sync.rb
474
477
  - lib/polyphony/core/thread_pool.rb
475
478
  - lib/polyphony/core/throttler.rb
479
+ - lib/polyphony/core/timer.rb
476
480
  - lib/polyphony/extensions/core.rb
477
481
  - lib/polyphony/extensions/debug.rb
478
482
  - lib/polyphony/extensions/fiber.rb
@@ -507,6 +511,7 @@ files:
507
511
  - test/test_thread.rb
508
512
  - test/test_thread_pool.rb
509
513
  - test/test_throttler.rb
514
+ - test/test_timer.rb
510
515
  - test/test_trace.rb
511
516
  homepage: https://digital-fabric.github.io/polyphony
512
517
  licenses:
@@ -1,26 +0,0 @@
1
- #ifndef BACKEND_H
2
- #define BACKEND_H
3
-
4
- #include "ruby.h"
5
-
6
- typedef VALUE (* backend_pending_count_t)(VALUE self);
7
- typedef VALUE (*backend_poll_t)(VALUE self, VALUE nowait, VALUE current_fiber, VALUE runqueue);
8
- typedef VALUE (* backend_ref_t)(VALUE self);
9
- typedef int (* backend_ref_count_t)(VALUE self);
10
- typedef void (* backend_reset_ref_count_t)(VALUE self);
11
- typedef VALUE (* backend_unref_t)(VALUE self);
12
- typedef VALUE (* backend_wait_event_t)(VALUE self, VALUE raise_on_exception);
13
- typedef VALUE (* backend_wakeup_t)(VALUE self);
14
-
15
- typedef struct backend_interface {
16
- backend_pending_count_t pending_count;
17
- backend_poll_t poll;
18
- backend_ref_t ref;
19
- backend_ref_count_t ref_count;
20
- backend_reset_ref_count_t reset_ref_count;
21
- backend_unref_t unref;
22
- backend_wait_event_t wait_event;
23
- backend_wakeup_t wakeup;
24
- } backend_interface_t;
25
-
26
- #endif /* BACKEND_H */