polyphony 0.33 → 0.34

Sign up to get free protection for your applications and to get access to all the features.
Files changed (49) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +8 -0
  3. data/Gemfile.lock +1 -1
  4. data/TODO.md +93 -68
  5. data/bin/polyphony-debug +87 -0
  6. data/docs/_includes/nav.html +5 -1
  7. data/docs/_sass/overrides.scss +4 -1
  8. data/docs/api-reference.md +11 -0
  9. data/docs/api-reference/exception.md +27 -0
  10. data/docs/api-reference/fiber.md +407 -0
  11. data/docs/api-reference/io.md +36 -0
  12. data/docs/api-reference/object.md +99 -0
  13. data/docs/api-reference/polyphony-baseexception.md +33 -0
  14. data/docs/api-reference/polyphony-cancel.md +26 -0
  15. data/docs/api-reference/polyphony-moveon.md +24 -0
  16. data/docs/api-reference/polyphony-net.md +20 -0
  17. data/docs/api-reference/polyphony-process.md +28 -0
  18. data/docs/api-reference/polyphony-resourcepool.md +59 -0
  19. data/docs/api-reference/polyphony-restart.md +18 -0
  20. data/docs/api-reference/polyphony-terminate.md +18 -0
  21. data/docs/api-reference/polyphony-threadpool.md +67 -0
  22. data/docs/api-reference/polyphony-throttler.md +77 -0
  23. data/docs/api-reference/polyphony.md +36 -0
  24. data/docs/api-reference/thread.md +88 -0
  25. data/docs/getting-started/tutorial.md +59 -156
  26. data/docs/index.md +2 -0
  27. data/examples/core/forever_sleep.rb +19 -0
  28. data/examples/core/xx-caller.rb +12 -0
  29. data/examples/core/xx-exception-backtrace.rb +40 -0
  30. data/examples/core/xx-fork-spin.rb +42 -0
  31. data/examples/core/xx-spin-fork.rb +49 -0
  32. data/examples/core/xx-supervise-process.rb +30 -0
  33. data/ext/gyro/gyro.h +1 -0
  34. data/ext/gyro/selector.c +8 -0
  35. data/ext/gyro/thread.c +8 -2
  36. data/lib/polyphony.rb +64 -17
  37. data/lib/polyphony/adapters/process.rb +29 -0
  38. data/lib/polyphony/adapters/trace.rb +6 -4
  39. data/lib/polyphony/core/exceptions.rb +5 -0
  40. data/lib/polyphony/core/global_api.rb +15 -0
  41. data/lib/polyphony/extensions/fiber.rb +89 -59
  42. data/lib/polyphony/version.rb +1 -1
  43. data/test/test_fiber.rb +23 -75
  44. data/test/test_global_api.rb +39 -0
  45. data/test/test_kernel.rb +5 -7
  46. data/test/test_process_supervision.rb +46 -0
  47. data/test/test_signal.rb +2 -3
  48. data/test/test_supervise.rb +103 -0
  49. metadata +29 -2
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Polyphony
4
- VERSION = '0.33'
4
+ VERSION = '0.34'
5
5
  end
@@ -659,20 +659,41 @@ class FiberTest < MiniTest::Test
659
659
  i, o = IO.pipe
660
660
  pid = Polyphony.fork do
661
661
  i.close
662
- f = spin do
662
+ spin do
663
663
  sleep 100
664
664
  rescue Exception => e
665
665
  o << e.class.to_s
666
666
  o.close
667
+ raise e
667
668
  end
668
- snooze
669
+ suspend
669
670
  end
670
671
  o.close
672
+ spin do
673
+ sleep 0.2
674
+ Process.kill('TERM', pid)
675
+ end
671
676
  Gyro::Child.new(pid).await
672
677
  klass = i.read
673
678
  i.close
674
679
  assert_equal 'Polyphony::Terminate', klass
675
680
  end
681
+
682
+ def test_setup_raw
683
+ buffer = []
684
+ f = Fiber.new { buffer << receive }
685
+
686
+ assert_raises(NoMethodError) { f << 'foo' }
687
+ snooze
688
+ f.setup_raw
689
+ assert_equal Thread.current, f.thread
690
+ assert_nil f.parent
691
+
692
+ f.schedule
693
+ f << 'bar'
694
+ snooze
695
+ assert_equal ['bar'], buffer
696
+ end
676
697
  end
677
698
 
678
699
  class MailboxTest < MiniTest::Test
@@ -956,76 +977,3 @@ class RestartTest < MiniTest::Test
956
977
  assert_equal [f, 'foo', 'bar', :done, f2, 'baz', 42, :done], buffer
957
978
  end
958
979
  end
959
-
960
- class SuperviseTest < MiniTest::Test
961
- def test_supervise
962
- p = spin { supervise }
963
- snooze
964
- f1 = p.spin { receive }
965
- f2 = p.spin { receive }
966
-
967
- snooze
968
- assert_equal p.state, :waiting
969
- f1 << 'foo'
970
- f1.await
971
- snooze
972
-
973
- assert_equal :waiting, p.state
974
- assert_equal :waiting, f2.state
975
-
976
- f2 << 'bar'
977
- f2.await
978
- snooze
979
-
980
- assert_equal :waiting, p.state
981
- end
982
-
983
- def test_supervise_with_restart
984
- parent = spin { supervise(on_error: :restart) }
985
- snooze
986
-
987
- buffer = []
988
- f1 = parent.spin do
989
- buffer << 'f1'
990
- buffer << receive
991
- end
992
-
993
- snooze
994
- assert_equal ['f1'], buffer
995
-
996
- f1.raise 'foo'
997
-
998
- 3.times { snooze }
999
-
1000
- assert_equal ['f1', 'f1'], buffer
1001
- assert_equal :dead, f1.state
1002
-
1003
- # f1 should have been restarted by supervisor
1004
- f1 = parent.children.first
1005
- assert_kind_of Fiber, f1
1006
- f1 << 'foo'
1007
-
1008
- f1.await
1009
- 3.times { snooze }
1010
-
1011
- assert_equal ['f1', 'f1', 'foo'], buffer
1012
- end
1013
-
1014
- def test_supervise_with_block
1015
- failed = []
1016
- p = spin do
1017
- supervise(on_error: :restart) { |f, e| failed << [f, e] }
1018
- end
1019
- snooze
1020
- f1 = p.spin { receive }
1021
- snooze
1022
-
1023
- f1.raise 'foo'
1024
- 3.times { snooze }
1025
-
1026
- assert_equal 1, failed.size
1027
- assert_equal f1, failed.first[0]
1028
- assert_kind_of RuntimeError, failed.first[1]
1029
- assert_equal 'foo', failed.first[1].message
1030
- end
1031
- end
@@ -121,8 +121,47 @@ class MoveOnAfterTest < MiniTest::Test
121
121
  assert t1 - t0 < 0.02
122
122
  assert_equal :bar, v
123
123
  end
124
+
125
+ def test_move_on_after_without_block
126
+ t0 = Time.now
127
+ f = move_on_after(0.01, with_value: 'foo')
128
+ assert_kind_of Fiber, f
129
+ assert_equal Fiber.current, f.parent
130
+ v = sleep 1
131
+ t1 = Time.now
132
+ assert t1 - t0 < 0.02
133
+ assert_equal 'foo', v
134
+ end
135
+ end
136
+
137
+ class CancelAfterTest < MiniTest::Test
138
+ def test_cancel_after
139
+ t0 = Time.now
140
+
141
+ assert_raises Polyphony::Cancel do
142
+ cancel_after(0.01) do
143
+ sleep 1
144
+ :foo
145
+ end
146
+ end
147
+ t1 = Time.now
148
+ assert t1 - t0 < 0.02
149
+ end
150
+
151
+ def test_cancel_after_without_block
152
+ t0 = Time.now
153
+ f = cancel_after(0.01)
154
+ assert_kind_of Fiber, f
155
+ assert_equal Fiber.current, f.parent
156
+ assert_raises Polyphony::Cancel do
157
+ sleep 1
158
+ end
159
+ t1 = Time.now
160
+ assert t1 - t0 < 0.02
161
+ end
124
162
  end
125
163
 
164
+
126
165
  class SpinLoopTest < MiniTest::Test
127
166
  def test_spin_loop
128
167
  buffer = []
@@ -4,20 +4,18 @@ require_relative 'helper'
4
4
 
5
5
  class KernelTest < MiniTest::Test
6
6
  def test_system_method
7
+ fn = '/tmp/test_system_method'
8
+ FileUtils.rm(fn) rescue nil
9
+
7
10
  counter = 0
8
11
  timer = spin { throttled_loop(200) { counter += 1 } }
9
12
 
10
13
  system('sleep 0.01')
11
14
  assert(counter >= 2)
12
15
 
13
- i, o = IO.pipe
14
- orig_stdout = $stdout
15
- $stdout = o
16
- system('echo "hello"')
17
- o.close
18
- assert_equal "hello\n", i.read
16
+ system('echo "hello" > ' + fn)
17
+ assert_equal "hello\n", IO.read(fn)
19
18
  ensure
20
- $stdout = orig_stdout
21
19
  timer&.stop
22
20
  end
23
21
 
@@ -0,0 +1,46 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative 'helper'
4
+
5
+ class ProcessSupervisionTest < MiniTest::Test
6
+ def test_process_supervisor_with_block
7
+ i, o = IO.pipe
8
+
9
+ f = spin do
10
+ Polyphony.watch_process do
11
+ i.close
12
+ sleep 5
13
+ ensure
14
+ o << 'foo'
15
+ o.close
16
+ end
17
+ supervise(on_error: :restart)
18
+ end
19
+
20
+ sleep 0.05
21
+ f.terminate
22
+ f.await
23
+
24
+ o.close
25
+ msg = i.read
26
+ i.close
27
+ assert_equal 'foo', msg
28
+ end
29
+
30
+ def test_process_supervisor_with_cmd
31
+ fn = '/tmp/test_process_supervisor_with_cmd'
32
+ FileUtils.rm(fn) rescue nil
33
+
34
+ f = spin do
35
+ Polyphony.watch_process("echo foo >> #{fn}")
36
+ supervise(on_error: :restart)
37
+ end
38
+
39
+ sleep 0.05
40
+ f.terminate
41
+ f.await
42
+
43
+ assert_equal "foo\n", IO.read(fn)
44
+
45
+ end
46
+ end
@@ -44,11 +44,10 @@ class SignalTrapTest < Minitest::Test
44
44
  i.close
45
45
  spin do
46
46
  spin do
47
- sleep 1
47
+ sleep 5
48
48
  rescue ::Interrupt => e
49
- # the signal will be trapped in the context of this fiber
49
+ # the signal should be raised only in the main fiber
50
50
  o.puts "1-interrupt"
51
- raise e
52
51
  end.await
53
52
  end.await
54
53
  rescue ::Interrupt => e
@@ -0,0 +1,103 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative 'helper'
4
+
5
+ class SuperviseTest < MiniTest::Test
6
+ def test_supervise
7
+ p = spin { supervise }
8
+ snooze
9
+ f1 = p.spin { receive }
10
+ f2 = p.spin { receive }
11
+
12
+ snooze
13
+ assert_equal p.state, :waiting
14
+ f1 << 'foo'
15
+ f1.await
16
+ snooze
17
+
18
+ assert_equal :waiting, p.state
19
+ assert_equal :waiting, f2.state
20
+
21
+ f2 << 'bar'
22
+ f2.await
23
+ snooze
24
+
25
+ assert_equal :waiting, p.state
26
+ end
27
+
28
+ def test_supervise_with_restart
29
+ watcher = spin { receive }
30
+ parent = spin { supervise(restart: true, watcher: watcher) }
31
+ snooze
32
+
33
+ buffer = []
34
+ f1 = parent.spin do
35
+ buffer << 'f1'
36
+ end
37
+
38
+ f1.await
39
+ assert_equal ['f1'], buffer
40
+ watcher.await
41
+ assert_equal ['f1', 'f1'], buffer
42
+ end
43
+
44
+ def test_supervise_with_restart_on_error
45
+ parent = spin { supervise(restart: true) }
46
+ snooze
47
+
48
+ buffer = []
49
+ f1 = parent.spin do
50
+ buffer << 'f1'
51
+ buffer << receive
52
+ end
53
+
54
+ snooze
55
+ assert_equal ['f1'], buffer
56
+
57
+ f1.raise 'foo'
58
+
59
+ 3.times { snooze }
60
+
61
+ assert_equal ['f1', 'f1'], buffer
62
+ assert_equal :dead, f1.state
63
+
64
+ # f1 should have been restarted by supervisor
65
+ f1 = parent.children.first
66
+ assert_kind_of Fiber, f1
67
+
68
+ f1 << 'foo'
69
+ f1.await
70
+
71
+ assert_equal ['f1', 'f1', 'foo'], buffer
72
+ end
73
+
74
+ def test_supervisor_termination
75
+ f = nil
76
+ p = spin do
77
+ f = spin { sleep 1 }
78
+ supervise
79
+ end
80
+ sleep 0.01
81
+
82
+ p.terminate
83
+ p.await
84
+
85
+ assert :dead, f.state
86
+ assert :dead, p.state
87
+ end
88
+
89
+ def test_supervisor_termination_with_restart
90
+ f = nil
91
+ p = spin do
92
+ f = spin { sleep 1 }
93
+ supervise(restart: true)
94
+ end
95
+ sleep 0.01
96
+
97
+ p.terminate
98
+ p.await
99
+
100
+ assert :dead, f.state
101
+ assert :dead, p.state
102
+ end
103
+ 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.33'
4
+ version: '0.34'
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-03-08 00:00:00.000000000 Z
11
+ date: 2020-03-25 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: modulation
@@ -254,12 +254,30 @@ files:
254
254
  - README.md
255
255
  - Rakefile
256
256
  - TODO.md
257
+ - bin/polyphony-debug
257
258
  - docs/_config.yml
258
259
  - docs/_includes/nav.html
259
260
  - docs/_includes/prevnext.html
260
261
  - docs/_layouts/default.html
261
262
  - docs/_sass/custom/custom.scss
262
263
  - docs/_sass/overrides.scss
264
+ - docs/api-reference.md
265
+ - docs/api-reference/exception.md
266
+ - docs/api-reference/fiber.md
267
+ - docs/api-reference/io.md
268
+ - docs/api-reference/object.md
269
+ - docs/api-reference/polyphony-baseexception.md
270
+ - docs/api-reference/polyphony-cancel.md
271
+ - docs/api-reference/polyphony-moveon.md
272
+ - docs/api-reference/polyphony-net.md
273
+ - docs/api-reference/polyphony-process.md
274
+ - docs/api-reference/polyphony-resourcepool.md
275
+ - docs/api-reference/polyphony-restart.md
276
+ - docs/api-reference/polyphony-terminate.md
277
+ - docs/api-reference/polyphony-threadpool.md
278
+ - docs/api-reference/polyphony-throttler.md
279
+ - docs/api-reference/polyphony.md
280
+ - docs/api-reference/thread.md
263
281
  - docs/assets/img/echo-fibers.svg
264
282
  - docs/assets/img/sleeping-fiber.svg
265
283
  - docs/faq.md
@@ -287,11 +305,15 @@ files:
287
305
  - examples/core/01-spinning-up-fibers.rb
288
306
  - examples/core/02-awaiting-fibers.rb
289
307
  - examples/core/03-interrupting.rb
308
+ - examples/core/forever_sleep.rb
290
309
  - examples/core/xx-at_exit.rb
310
+ - examples/core/xx-caller.rb
291
311
  - examples/core/xx-channels.rb
292
312
  - examples/core/xx-deadlock.rb
293
313
  - examples/core/xx-deferring-an-operation.rb
294
314
  - examples/core/xx-erlang-style-genserver.rb
315
+ - examples/core/xx-exception-backtrace.rb
316
+ - examples/core/xx-fork-spin.rb
295
317
  - examples/core/xx-fork-terminate.rb
296
318
  - examples/core/xx-forking.rb
297
319
  - examples/core/xx-move_on.rb
@@ -304,9 +326,11 @@ files:
304
326
  - examples/core/xx-sleep-forever.rb
305
327
  - examples/core/xx-sleeping.rb
306
328
  - examples/core/xx-snooze-starve.rb
329
+ - examples/core/xx-spin-fork.rb
307
330
  - examples/core/xx-spin_error_backtrace.rb
308
331
  - examples/core/xx-state-machine.rb
309
332
  - examples/core/xx-stop.rb
333
+ - examples/core/xx-supervise-process.rb
310
334
  - examples/core/xx-supervisors.rb
311
335
  - examples/core/xx-thread-selector-sleep.rb
312
336
  - examples/core/xx-thread-selector-snooze.rb
@@ -381,6 +405,7 @@ files:
381
405
  - lib/polyphony/adapters/fs.rb
382
406
  - lib/polyphony/adapters/irb.rb
383
407
  - lib/polyphony/adapters/postgres.rb
408
+ - lib/polyphony/adapters/process.rb
384
409
  - lib/polyphony/adapters/redis.rb
385
410
  - lib/polyphony/adapters/trace.rb
386
411
  - lib/polyphony/core/channel.rb
@@ -410,8 +435,10 @@ files:
410
435
  - test/test_global_api.rb
411
436
  - test/test_io.rb
412
437
  - test/test_kernel.rb
438
+ - test/test_process_supervision.rb
413
439
  - test/test_resource_pool.rb
414
440
  - test/test_signal.rb
441
+ - test/test_supervise.rb
415
442
  - test/test_thread.rb
416
443
  - test/test_thread_pool.rb
417
444
  - test/test_throttler.rb