polyphony 0.22 → 0.23

Sign up to get free protection for your applications and to get access to all the features.
Files changed (114) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +25 -0
  3. data/Gemfile.lock +9 -1
  4. data/TODO.md +13 -38
  5. data/docs/summary.md +19 -5
  6. data/docs/technical-overview/faq.md +12 -0
  7. data/examples/core/01-spinning-up-coprocesses.rb +2 -6
  8. data/examples/core/02-awaiting-coprocesses.rb +3 -1
  9. data/examples/core/03-interrupting.rb +3 -1
  10. data/examples/core/04-no-auto-run.rb +1 -3
  11. data/examples/core/cancel.rb +1 -1
  12. data/examples/core/channel_echo.rb +3 -1
  13. data/examples/core/defer.rb +3 -1
  14. data/examples/core/enumerator.rb +3 -1
  15. data/examples/core/error_bubbling.rb +35 -0
  16. data/examples/core/fork.rb +1 -1
  17. data/examples/core/genserver.rb +1 -1
  18. data/examples/core/lock.rb +3 -1
  19. data/examples/core/move_on.rb +1 -1
  20. data/examples/core/move_on_twice.rb +1 -1
  21. data/examples/core/move_on_with_ensure.rb +1 -1
  22. data/examples/core/move_on_with_value.rb +1 -1
  23. data/examples/core/multiple_spin.rb +3 -1
  24. data/examples/core/nested_cancel.rb +1 -1
  25. data/examples/core/nested_multiple_spin.rb +3 -1
  26. data/examples/core/nested_spin.rb +3 -1
  27. data/examples/core/pulse.rb +1 -1
  28. data/examples/core/resource.rb +1 -1
  29. data/examples/core/resource_cancel.rb +2 -2
  30. data/examples/core/resource_delegate.rb +1 -1
  31. data/examples/core/sleep.rb +1 -1
  32. data/examples/core/sleep_spin.rb +3 -1
  33. data/examples/core/snooze.rb +1 -1
  34. data/examples/core/spin_error.rb +2 -1
  35. data/examples/core/spin_error_backtrace.rb +1 -1
  36. data/examples/core/spin_uncaught_error.rb +3 -1
  37. data/examples/core/supervisor.rb +1 -1
  38. data/examples/core/supervisor_with_cancel_scope.rb +1 -1
  39. data/examples/core/supervisor_with_error.rb +3 -1
  40. data/examples/core/supervisor_with_manual_move_on.rb +1 -1
  41. data/examples/core/suspend.rb +1 -1
  42. data/examples/core/thread.rb +3 -3
  43. data/examples/core/thread_cancel.rb +6 -3
  44. data/examples/core/thread_pool.rb +8 -52
  45. data/examples/core/thread_pool_perf.rb +63 -0
  46. data/examples/core/throttle.rb +3 -1
  47. data/examples/core/timeout.rb +1 -1
  48. data/examples/core/wait_for_signal.rb +4 -2
  49. data/examples/fs/read.rb +1 -1
  50. data/examples/http/http2_raw.rb +1 -1
  51. data/examples/http/http_get.rb +1 -1
  52. data/examples/http/http_server.rb +2 -1
  53. data/examples/http/http_server_graceful.rb +3 -1
  54. data/examples/http/http_ws_server.rb +0 -2
  55. data/examples/http/https_wss_server.rb +0 -2
  56. data/examples/http/websocket_secure_server.rb +0 -2
  57. data/examples/http/websocket_server.rb +0 -2
  58. data/examples/interfaces/redis_channels.rb +3 -1
  59. data/examples/interfaces/redis_pubsub.rb +3 -1
  60. data/examples/interfaces/redis_pubsub_perf.rb +3 -1
  61. data/examples/io/backticks.rb +1 -1
  62. data/examples/io/cat.rb +1 -1
  63. data/examples/io/echo_client.rb +1 -1
  64. data/examples/io/echo_client_from_stdin.rb +3 -1
  65. data/examples/io/echo_pipe.rb +1 -1
  66. data/examples/io/echo_server.rb +1 -1
  67. data/examples/io/echo_server_with_timeout.rb +1 -1
  68. data/examples/io/echo_stdin.rb +1 -1
  69. data/examples/io/httparty_multi.rb +1 -1
  70. data/examples/io/io_read.rb +1 -1
  71. data/examples/io/irb.rb +1 -1
  72. data/examples/io/net-http.rb +1 -1
  73. data/examples/io/open.rb +1 -1
  74. data/examples/io/system.rb +1 -1
  75. data/examples/io/tcpserver.rb +1 -1
  76. data/examples/io/tcpsocket.rb +1 -1
  77. data/examples/performance/multi_snooze.rb +1 -1
  78. data/examples/performance/snooze.rb +18 -10
  79. data/ext/gyro/async.c +16 -9
  80. data/ext/gyro/child.c +2 -2
  81. data/ext/gyro/gyro.c +17 -10
  82. data/ext/gyro/gyro.h +2 -2
  83. data/ext/gyro/io.c +2 -2
  84. data/ext/gyro/signal.c +33 -35
  85. data/ext/gyro/timer.c +6 -73
  86. data/lib/polyphony.rb +6 -8
  87. data/lib/polyphony/core/cancel_scope.rb +32 -21
  88. data/lib/polyphony/core/coprocess.rb +26 -23
  89. data/lib/polyphony/core/global_api.rb +86 -0
  90. data/lib/polyphony/core/resource_pool.rb +1 -1
  91. data/lib/polyphony/core/supervisor.rb +47 -13
  92. data/lib/polyphony/core/thread.rb +10 -36
  93. data/lib/polyphony/core/thread_pool.rb +6 -26
  94. data/lib/polyphony/extensions/core.rb +30 -100
  95. data/lib/polyphony/extensions/io.rb +10 -7
  96. data/lib/polyphony/extensions/openssl.rb +18 -28
  97. data/lib/polyphony/http/client/agent.rb +15 -11
  98. data/lib/polyphony/http/client/http2.rb +1 -1
  99. data/lib/polyphony/version.rb +1 -1
  100. data/polyphony.gemspec +1 -0
  101. data/test/coverage.rb +45 -0
  102. data/test/helper.rb +15 -5
  103. data/test/test_async.rb +4 -4
  104. data/test/test_cancel_scope.rb +109 -0
  105. data/test/test_coprocess.rb +80 -36
  106. data/test/{test_core.rb → test_global_api.rb} +67 -13
  107. data/test/test_gyro.rb +1 -5
  108. data/test/test_io.rb +2 -2
  109. data/test/test_resource_pool.rb +19 -0
  110. data/test/test_signal.rb +10 -5
  111. data/test/test_supervisor.rb +168 -0
  112. data/test/test_timer.rb +31 -5
  113. metadata +23 -4
  114. data/lib/polyphony/auto_run.rb +0 -19
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 27942af70470ad8751268c35230cf822e5b671305450edc19dc4b998409ca1b2
4
- data.tar.gz: 94393e31d741b484e188730496980fd5fc44fd4ff632abf8abe7e9ba3117b71f
3
+ metadata.gz: 42975a9e638525d2264fbddea88ee0756fb7e7dbc5c0585c033b71a06a27711c
4
+ data.tar.gz: 2c233b91c02d60e1dc40fbacb1dbade17c591a9ddede854e71dc7b2a840dcfd0
5
5
  SHA512:
6
- metadata.gz: 2d97e95fd9b8d5c9bf8f3224652c88f29a8e5e930918819647a4e66f2d09be6c190c43c88cf202c3f3211b41faedf5afc0c1c67922fe6e31e2453750b0566777
7
- data.tar.gz: 4f86964e496dcc418ed23f45cffe88db4d93489dc6ab7616157456f309f117e1fe3f4e12a2edc06347ee3b7ca3af76f2e2ec461499c5bf05caf30eea281bb6bd
6
+ metadata.gz: 339373f341a10fa68bec7d39588407519c12e17f9b02f774b9179af9b682512c156aa254cac116d4f60d1528e4dae21cfe220e71bf998787c0f1b55c244ef959
7
+ data.tar.gz: 429a5960bbc3a38d23282ab1a8339b1ae556832fd098e34ae1a63fca36f4bc9f15f8996a715c70ac3363e01ea1858c2cf9de6b9296e90cf7f6a6c8a79f42c48c
@@ -1,3 +1,28 @@
1
+ 0.23 2020-01-07
2
+ ---------------
3
+
4
+ * Remove `API#pulse`
5
+ * Better repeat timer, reimplement `API#every`
6
+ * Move global API methods to separate module, include in `Object` instead of
7
+ `Kernel`
8
+ * Improve setting root fiber and corresponding coprocess
9
+ * Fix `ResourcePool#preheat!`
10
+ * Rename `$Coprocess#list` to `Coprocess#map`
11
+ * Fix `CancelScope#on_cancel`, remove `CancelScope#protect`
12
+ * Remove `auto_run` mechanism. Just use `suspend`!
13
+ * Optional coverage report for tests
14
+ * More tests
15
+ * Add `Coprocess.select` and `Supervisor#select` methods
16
+ * Add `Coprocess.join` alias to `Coprocess.await` method
17
+ * Add support for cancelling multiple coprocesses with a single cancel scope
18
+ * Fix stopping a coprocess before it being scheduled for the first time
19
+ * Rewrite `thread`, `thread_pool` modules
20
+ * Add `Kernel#orig_sleep` alias to sync `#sleep` method
21
+ * Add optional resume value to `Gyro::Async#signal!`
22
+ * Patch Fiber#inspect to show correct block location
23
+ * Add Gyro.run
24
+ * Move away from callback-based API for `Gyro::Timer`, `Gyro::Signal`
25
+
1
26
  0.22 2020-01-02
2
27
  ---------------
3
28
 
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- polyphony (0.22)
4
+ polyphony (0.23)
5
5
  http-2 (= 0.10.0)
6
6
  http_parser.rb (= 0.6.0)
7
7
  modulation (~> 0.25)
@@ -12,12 +12,14 @@ GEM
12
12
  specs:
13
13
  ansi (1.5.0)
14
14
  builder (3.2.4)
15
+ docile (1.3.2)
15
16
  hiredis (0.6.3)
16
17
  http-2 (0.10.0)
17
18
  http_parser.rb (0.6.0)
18
19
  httparty (0.17.0)
19
20
  mime-types (~> 3.0)
20
21
  multi_xml (>= 0.5.2)
22
+ json (2.1.0)
21
23
  localhost (1.1.4)
22
24
  mime-types (3.3.1)
23
25
  mime-types-data (~> 3.2015)
@@ -37,6 +39,11 @@ GEM
37
39
  rake
38
40
  redis (4.1.0)
39
41
  ruby-progressbar (1.10.1)
42
+ simplecov (0.17.1)
43
+ docile (~> 1.1)
44
+ json (>= 1.8, < 3)
45
+ simplecov-html (~> 0.10.0)
46
+ simplecov-html (0.10.2)
40
47
  websocket (1.2.8)
41
48
 
42
49
  PLATFORMS
@@ -52,6 +59,7 @@ DEPENDENCIES
52
59
  polyphony!
53
60
  rake-compiler (= 1.0.5)
54
61
  redis (= 4.1.0)
62
+ simplecov (= 0.17.1)
55
63
  websocket (= 1.2.8)
56
64
 
57
65
  BUNDLED WITH
data/TODO.md CHANGED
@@ -1,31 +1,3 @@
1
- # Add ability to cancel multiple coprocesses
2
-
3
- ```ruby
4
- scope = CancelScope.new
5
-
6
- 3.times { |i|
7
- spin {
8
- puts "sleep for #{i + 1}s"
9
- scope.call { sleep i + 1 }
10
- puts "woke up"
11
- }
12
- }
13
-
14
- sleep 0.5
15
- scope.cancel!
16
- ```
17
-
18
- # Add ability to wait for signal
19
-
20
- ```ruby
21
- sig = Gyro::Signal('SIGUP')
22
-
23
- loop do
24
- sig.await
25
- restart
26
- end
27
- ```
28
-
29
1
  # HTTP Client Agent
30
2
 
31
3
  The concurrency model and the fact that we want to serve the response object on
@@ -71,14 +43,12 @@ end
71
43
 
72
44
  # Roadmap:
73
45
 
74
- ## 0.22 Redesign of Gyro scheduling system
46
+ ## 0.24 Move HTTP code into separate gem
75
47
 
76
- - Schedulerless design - no separate fiber for running ev loop
77
- - Blocking operations directly transfer to first scheduled fiber
78
- - Scheduled fibers managed using linked list, switching directly from one to the
79
- other
48
+ - Pull out HTTP/websocket code, put into new `polyphony-http` gem
49
+ - Pull out redis/postgres code, put into new `polyphony-contrib` gem
80
50
 
81
- ## 0.23 Full Rack adapter implementation
51
+ ## 0.25 Full Rack adapter implementation
82
52
 
83
53
  - Work better mechanism supervising multiple coprocesses (`when_done` feels a
84
54
  bit hacky)
@@ -86,21 +56,26 @@ end
86
56
  - Homogenize HTTP 1 and HTTP 2 headers - upcase ? downcase ?
87
57
  - find some demo Rack apps and test with Polyphony
88
58
 
89
- ## 0.24 Working Sinatra application
59
+ ## 0.26 Working Sinatra application
90
60
 
91
61
  - app with database access (postgresql)
92
62
  - benchmarks!
93
63
 
94
- ## 0.25 Support for multi-threading
64
+ ## 0.27 Support for multi-threading
95
65
 
96
66
  - Separate event loop for each thread
97
67
 
98
- ## 0.26 Testing
68
+ ## 0.28 Testing
99
69
 
100
70
  - test thread / thread_pool modules
101
71
  - report test coverage
102
72
 
103
- ## 0.27 Documentation
73
+ ## 0.29 Documentation
74
+
75
+ ## 0.30 Integration
76
+
77
+ - Sidekick
78
+ - Rails?
104
79
 
105
80
  # DNS
106
81
 
@@ -15,11 +15,25 @@
15
15
  * [Exception Handling](technical-overview/exception-handling.md)
16
16
  * [Frequently Asked Questions](technical-overview/faq.md)
17
17
 
18
- ## Using Polyphony
19
-
20
- * [Coprocesses](#)
21
- * [Supervisors](#)
22
- * [Cancel Scopes](#)
18
+ ## How To
19
+
20
+ * [Make an echo server](howto/echo-server.md)
21
+ * [Make an HTTP server](howto/http-server.md)
22
+ * [Make a Websocket server](howto/websocket-server.md)
23
+ * [Use timers](howto/timers.md)
24
+ * [Throttle recurrent operations](howto/throttle.md)
25
+ * [Cancel ongoing operations](howto/cancel.md)
26
+ * [Control coprocesses](howto/coprocesses.md)
27
+ * [Synchronize concurrent operations](howto/synchronize.md)
28
+ * [Perform CPU-bound operations](howto/cpu-bound.md)
29
+ * [Control backpressure](howto/backpressure.md)
30
+ * [Fork worker processes](howto/worker-processes.md)
31
+
32
+ ## Polyphony extensions
33
+
34
+ * [Postgresql](extensions/pg)
35
+ * [Redis](extensions/redis)
36
+ * [IRB](extensions/irb)
23
37
  * [Throttlers](#)
24
38
  * [Resource Pools](#)
25
39
  * [Synchronisation](#)
@@ -80,6 +80,18 @@ The API for `Fiber.yield`/`Fiber#resume` is stateful and is intended for the asy
80
80
 
81
81
  Polyphony is currently at an experimental stage, and its different APIs are still in flux. For that reason, all the different parts of Polyphony are currently kept in a single gem. Once things stabilize, and as Polyphony approaches version 1.0, it will be split into separate gems, each with its own functionality.
82
82
 
83
+ ## Can I use Polyphony in a multithreaded program?
84
+
85
+ Not yet. We plan to support multiple threads when Ruby 3.0 is ready.
86
+
87
+ ## Can I run Rails using Polyphony?
88
+
89
+ Not yet. We do plan to support running Rails when our multithreaded support is ready (see above).
90
+
91
+ ## How can I contribute to Polyphony?
92
+
93
+ The Polyphony repository is at https://github.com/digital-fabric/polyphony. Feel free to create issues and contribute pull requests.
94
+
83
95
  ## Who is behind this project?
84
96
 
85
97
  I'm Sharon Rosner, an independent software developer living in France. Here's my [github profile](https://github.com/ciconia). You can contact me by writing to [noteflakes@gmail.com](mailto:ciconia@gmail.com).
@@ -2,9 +2,7 @@
2
2
 
3
3
  require 'bundler/setup'
4
4
 
5
- # In order to automatically start the reactor, we need to require
6
- # `polyphony/auto_run`. Otherwise, we can just require `polyphony`
7
- require 'polyphony/auto_run'
5
+ require 'polyphony'
8
6
 
9
7
  def nap(tag, t)
10
8
  puts "#{Time.now} #{tag} napping for #{t} seconds..."
@@ -16,6 +14,4 @@ end
16
14
  spin { nap(:a, 1) }
17
15
  spin { nap(:b, 2) }
18
16
 
19
- # Having required `polyphony/auto_run`, once our program is done, the
20
- # libev-based event reactor is started, and runs until there's no more work left
21
- # for it to handle.
17
+ suspend
@@ -1,7 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  require 'bundler/setup'
4
- require 'polyphony/auto_run'
4
+ require 'polyphony'
5
5
 
6
6
  sleeper = spin do
7
7
  puts 'going to sleep'
@@ -16,3 +16,5 @@ waiter = spin do
16
16
  sleeper.await
17
17
  puts 'done waiting'
18
18
  end
19
+
20
+ waiter.await
@@ -1,7 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  require 'bundler/setup'
4
- require 'polyphony/auto_run'
4
+ require 'polyphony'
5
5
 
6
6
  # Let's see how a long-running blocking operation can be interrupted. Polyphony
7
7
  # provides several APIs for interrupting an ongoing operation, and distinguishes
@@ -32,3 +32,5 @@ spin do
32
32
  nap(:move_on, 2)
33
33
  end
34
34
  end
35
+
36
+ suspend
@@ -2,7 +2,6 @@
2
2
 
3
3
  require 'bundler/setup'
4
4
 
5
- # Notice we require 'polyphony' and not 'polyphony/auto_run'
6
5
  require 'polyphony'
7
6
 
8
7
  def nap(tag, t)
@@ -13,6 +12,5 @@ end
13
12
 
14
13
  spin { nap(:a, 1) }
15
14
 
16
- # If polyphony/auto_run has not been `require`d, the reactor fiber needs to be
17
- # started manually. This is done by transferring control to it using `suspend`:
15
+ # Wait for any coprocess still alive
18
16
  suspend
@@ -1,7 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  require 'bundler/setup'
4
- require 'polyphony/auto_run'
4
+ require 'polyphony'
5
5
 
6
6
  begin
7
7
  puts 'going to sleep...'
@@ -1,7 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  require 'bundler/setup'
4
- require 'polyphony/auto_run'
4
+ require 'polyphony'
5
5
 
6
6
  def echo(cin, cout)
7
7
  puts 'start echoer'
@@ -41,3 +41,5 @@ $main = spin do
41
41
  chan2.close
42
42
  puts "done #{Time.now - t0}"
43
43
  end
44
+
45
+ suspend
@@ -1,7 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  require 'bundler/setup'
4
- require 'polyphony/auto_run'
4
+ require 'polyphony'
5
5
 
6
6
  defer do
7
7
  puts 'two'
@@ -10,3 +10,5 @@ defer do
10
10
  end
11
11
 
12
12
  puts 'one'
13
+
14
+ suspend
@@ -1,7 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  require 'bundler/setup'
4
- require 'polyphony/auto_run'
4
+ require 'polyphony'
5
5
 
6
6
  enum = [1, 2, 3].each
7
7
 
@@ -11,3 +11,5 @@ spin do
11
11
  sleep 0.1
12
12
  end
13
13
  end
14
+
15
+ suspend
@@ -0,0 +1,35 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'bundler/setup'
4
+ require 'polyphony'
5
+
6
+ ::Exception.__disable_sanitized_backtrace__ = true
7
+
8
+ def test
9
+ # error is propagated to calling coprocess
10
+ raised_error = nil
11
+ spin do
12
+ spin do
13
+ raise 'foo'
14
+ end
15
+ puts "before snooze"
16
+ snooze # allow nested coprocess to run before finishing
17
+ puts "after snooze"
18
+ end
19
+ suspend
20
+ rescue Exception => e
21
+ raised_error = e
22
+ ensure
23
+ puts "raised_error: #{raised_error.inspect}"
24
+ # puts "msg: #{raised_error.message.inspect}"
25
+ end
26
+
27
+ test
28
+ begin
29
+ puts "last suspend"
30
+ #suspend
31
+ Gyro.run
32
+ rescue => e
33
+ puts "!" * 60
34
+ puts "Error after last suspend: #{e.inspect}"
35
+ end
@@ -1,7 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  require 'bundler/setup'
4
- require 'polyphony/auto_run'
4
+ require 'polyphony'
5
5
 
6
6
  puts "parent pid: #{Process.pid}"
7
7
 
@@ -1,7 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  require 'bundler/setup'
4
- require 'polyphony/auto_run'
4
+ require 'polyphony'
5
5
 
6
6
  class GenServer
7
7
  def self.start(receiver, *args)
@@ -1,7 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  require 'bundler/setup'
4
- require 'polyphony/auto_run'
4
+ require 'polyphony'
5
5
 
6
6
  def loop_it(number, lock)
7
7
  loop do
@@ -17,3 +17,5 @@ lock = Polyphony::Sync::Mutex.new
17
17
  spin { loop_it(1, lock) }
18
18
  spin { loop_it(2, lock) }
19
19
  spin { loop_it(3, lock) }
20
+
21
+ suspend
@@ -1,7 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  require 'bundler/setup'
4
- require 'polyphony/auto_run'
4
+ require 'polyphony'
5
5
  Exception.__disable_sanitized_backtrace__ = true
6
6
 
7
7
  puts 'going to sleep...'
@@ -1,7 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  require 'bundler/setup'
4
- require 'polyphony/auto_run'
4
+ require 'polyphony'
5
5
 
6
6
  puts 'going to sleep...'
7
7
  move_on_after(1) do
@@ -1,7 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  require 'bundler/setup'
4
- require 'polyphony/auto_run'
4
+ require 'polyphony'
5
5
 
6
6
  puts 'going to sleep...'
7
7
  move_on_after(0.5) do
@@ -1,7 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  require 'bundler/setup'
4
- require 'polyphony/auto_run'
4
+ require 'polyphony'
5
5
  Exception.__disable_sanitized_backtrace__ = true
6
6
 
7
7
  def blocking_operation