polyphony 0.43.8

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 (221) hide show
  1. checksums.yaml +7 -0
  2. data/.gitbook.yaml +4 -0
  3. data/.github/workflows/test.yml +29 -0
  4. data/.gitignore +59 -0
  5. data/.rubocop.yml +175 -0
  6. data/CHANGELOG.md +393 -0
  7. data/Gemfile +3 -0
  8. data/Gemfile.lock +141 -0
  9. data/LICENSE +21 -0
  10. data/README.md +51 -0
  11. data/Rakefile +26 -0
  12. data/TODO.md +201 -0
  13. data/bin/polyphony-debug +87 -0
  14. data/docs/_config.yml +64 -0
  15. data/docs/_includes/head.html +40 -0
  16. data/docs/_includes/title.html +1 -0
  17. data/docs/_sass/custom/custom.scss +10 -0
  18. data/docs/_sass/overrides.scss +0 -0
  19. data/docs/_user-guide/all-about-timers.md +126 -0
  20. data/docs/_user-guide/index.md +9 -0
  21. data/docs/_user-guide/web-server.md +136 -0
  22. data/docs/api-reference/exception.md +27 -0
  23. data/docs/api-reference/fiber.md +425 -0
  24. data/docs/api-reference/index.md +9 -0
  25. data/docs/api-reference/io.md +36 -0
  26. data/docs/api-reference/object.md +99 -0
  27. data/docs/api-reference/polyphony-baseexception.md +33 -0
  28. data/docs/api-reference/polyphony-cancel.md +26 -0
  29. data/docs/api-reference/polyphony-moveon.md +24 -0
  30. data/docs/api-reference/polyphony-net.md +20 -0
  31. data/docs/api-reference/polyphony-process.md +28 -0
  32. data/docs/api-reference/polyphony-resourcepool.md +59 -0
  33. data/docs/api-reference/polyphony-restart.md +18 -0
  34. data/docs/api-reference/polyphony-terminate.md +18 -0
  35. data/docs/api-reference/polyphony-threadpool.md +67 -0
  36. data/docs/api-reference/polyphony-throttler.md +77 -0
  37. data/docs/api-reference/polyphony.md +36 -0
  38. data/docs/api-reference/thread.md +88 -0
  39. data/docs/assets/img/echo-fibers.svg +1 -0
  40. data/docs/assets/img/sleeping-fiber.svg +1 -0
  41. data/docs/faq.md +195 -0
  42. data/docs/favicon.ico +0 -0
  43. data/docs/getting-started/index.md +10 -0
  44. data/docs/getting-started/installing.md +34 -0
  45. data/docs/getting-started/overview.md +486 -0
  46. data/docs/getting-started/tutorial.md +359 -0
  47. data/docs/index.md +94 -0
  48. data/docs/main-concepts/concurrency.md +151 -0
  49. data/docs/main-concepts/design-principles.md +161 -0
  50. data/docs/main-concepts/exception-handling.md +291 -0
  51. data/docs/main-concepts/extending.md +89 -0
  52. data/docs/main-concepts/fiber-scheduling.md +197 -0
  53. data/docs/main-concepts/index.md +9 -0
  54. data/docs/polyphony-logo.png +0 -0
  55. data/examples/adapters/concurrent-ruby.rb +9 -0
  56. data/examples/adapters/pg_client.rb +36 -0
  57. data/examples/adapters/pg_notify.rb +35 -0
  58. data/examples/adapters/pg_pool.rb +43 -0
  59. data/examples/adapters/pg_transaction.rb +31 -0
  60. data/examples/adapters/redis_blpop.rb +12 -0
  61. data/examples/adapters/redis_channels.rb +122 -0
  62. data/examples/adapters/redis_client.rb +19 -0
  63. data/examples/adapters/redis_pubsub.rb +26 -0
  64. data/examples/adapters/redis_pubsub_perf.rb +68 -0
  65. data/examples/core/01-spinning-up-fibers.rb +18 -0
  66. data/examples/core/02-awaiting-fibers.rb +20 -0
  67. data/examples/core/03-interrupting.rb +39 -0
  68. data/examples/core/04-handling-signals.rb +19 -0
  69. data/examples/core/xx-agent.rb +102 -0
  70. data/examples/core/xx-at_exit.rb +29 -0
  71. data/examples/core/xx-caller.rb +12 -0
  72. data/examples/core/xx-channels.rb +45 -0
  73. data/examples/core/xx-daemon.rb +14 -0
  74. data/examples/core/xx-deadlock.rb +8 -0
  75. data/examples/core/xx-deferring-an-operation.rb +14 -0
  76. data/examples/core/xx-erlang-style-genserver.rb +81 -0
  77. data/examples/core/xx-exception-backtrace.rb +40 -0
  78. data/examples/core/xx-fork-cleanup.rb +22 -0
  79. data/examples/core/xx-fork-spin.rb +42 -0
  80. data/examples/core/xx-fork-terminate.rb +27 -0
  81. data/examples/core/xx-forking.rb +24 -0
  82. data/examples/core/xx-move_on.rb +23 -0
  83. data/examples/core/xx-pingpong.rb +18 -0
  84. data/examples/core/xx-queue-async.rb +120 -0
  85. data/examples/core/xx-readpartial.rb +18 -0
  86. data/examples/core/xx-recurrent-timer.rb +12 -0
  87. data/examples/core/xx-resource_delegate.rb +31 -0
  88. data/examples/core/xx-signals.rb +16 -0
  89. data/examples/core/xx-sleep-forever.rb +9 -0
  90. data/examples/core/xx-sleeping.rb +25 -0
  91. data/examples/core/xx-snooze-starve.rb +16 -0
  92. data/examples/core/xx-spin-fork.rb +49 -0
  93. data/examples/core/xx-spin_error_backtrace.rb +33 -0
  94. data/examples/core/xx-state-machine.rb +51 -0
  95. data/examples/core/xx-stop.rb +20 -0
  96. data/examples/core/xx-supervise-process.rb +30 -0
  97. data/examples/core/xx-supervisors.rb +21 -0
  98. data/examples/core/xx-thread-selector-sleep.rb +51 -0
  99. data/examples/core/xx-thread-selector-snooze.rb +46 -0
  100. data/examples/core/xx-thread-sleep.rb +17 -0
  101. data/examples/core/xx-thread-snooze.rb +34 -0
  102. data/examples/core/xx-thread_pool.rb +17 -0
  103. data/examples/core/xx-throttling.rb +18 -0
  104. data/examples/core/xx-timeout.rb +10 -0
  105. data/examples/core/xx-timer-gc.rb +17 -0
  106. data/examples/core/xx-trace.rb +79 -0
  107. data/examples/core/xx-using-a-mutex.rb +21 -0
  108. data/examples/core/xx-worker-thread.rb +30 -0
  109. data/examples/io/tunnel.rb +48 -0
  110. data/examples/io/xx-backticks.rb +11 -0
  111. data/examples/io/xx-echo_client.rb +25 -0
  112. data/examples/io/xx-echo_client_from_stdin.rb +21 -0
  113. data/examples/io/xx-echo_pipe.rb +16 -0
  114. data/examples/io/xx-echo_server.rb +17 -0
  115. data/examples/io/xx-echo_server_with_timeout.rb +34 -0
  116. data/examples/io/xx-echo_stdin.rb +14 -0
  117. data/examples/io/xx-happy-eyeballs.rb +36 -0
  118. data/examples/io/xx-httparty.rb +38 -0
  119. data/examples/io/xx-irb.rb +17 -0
  120. data/examples/io/xx-net-http.rb +15 -0
  121. data/examples/io/xx-open.rb +16 -0
  122. data/examples/io/xx-switch.rb +15 -0
  123. data/examples/io/xx-system.rb +11 -0
  124. data/examples/io/xx-tcpserver.rb +15 -0
  125. data/examples/io/xx-tcpsocket.rb +18 -0
  126. data/examples/io/xx-zip.rb +19 -0
  127. data/examples/performance/fiber_transfer.rb +47 -0
  128. data/examples/performance/fs_read.rb +38 -0
  129. data/examples/performance/mem-usage.rb +56 -0
  130. data/examples/performance/messaging.rb +29 -0
  131. data/examples/performance/multi_snooze.rb +33 -0
  132. data/examples/performance/snooze.rb +39 -0
  133. data/examples/performance/snooze_raw.rb +39 -0
  134. data/examples/performance/thread-vs-fiber/polyphony_mt_server.rb +74 -0
  135. data/examples/performance/thread-vs-fiber/polyphony_server.rb +45 -0
  136. data/examples/performance/thread-vs-fiber/polyphony_server_read_loop.rb +58 -0
  137. data/examples/performance/thread-vs-fiber/threaded_server.rb +27 -0
  138. data/examples/performance/thread-vs-fiber/xx-httparty_multi.rb +36 -0
  139. data/examples/performance/thread-vs-fiber/xx-httparty_threaded.rb +29 -0
  140. data/examples/performance/thread_pool_perf.rb +63 -0
  141. data/examples/performance/xx-array.rb +11 -0
  142. data/examples/performance/xx-fiber-switch.rb +9 -0
  143. data/examples/performance/xx-snooze.rb +15 -0
  144. data/examples/xx-spin.rb +32 -0
  145. data/ext/libev/Changes +548 -0
  146. data/ext/libev/LICENSE +37 -0
  147. data/ext/libev/README +59 -0
  148. data/ext/libev/README.embed +3 -0
  149. data/ext/libev/ev.c +5279 -0
  150. data/ext/libev/ev.h +856 -0
  151. data/ext/libev/ev_epoll.c +296 -0
  152. data/ext/libev/ev_kqueue.c +224 -0
  153. data/ext/libev/ev_linuxaio.c +642 -0
  154. data/ext/libev/ev_poll.c +156 -0
  155. data/ext/libev/ev_port.c +192 -0
  156. data/ext/libev/ev_select.c +316 -0
  157. data/ext/libev/ev_vars.h +215 -0
  158. data/ext/libev/ev_win32.c +162 -0
  159. data/ext/libev/ev_wrap.h +216 -0
  160. data/ext/libev/test_libev_win32.c +123 -0
  161. data/ext/polyphony/extconf.rb +20 -0
  162. data/ext/polyphony/fiber.c +109 -0
  163. data/ext/polyphony/libev.c +2 -0
  164. data/ext/polyphony/libev.h +9 -0
  165. data/ext/polyphony/libev_agent.c +882 -0
  166. data/ext/polyphony/polyphony.c +71 -0
  167. data/ext/polyphony/polyphony.h +97 -0
  168. data/ext/polyphony/polyphony_ext.c +21 -0
  169. data/ext/polyphony/queue.c +168 -0
  170. data/ext/polyphony/ring_buffer.c +96 -0
  171. data/ext/polyphony/ring_buffer.h +28 -0
  172. data/ext/polyphony/thread.c +208 -0
  173. data/ext/polyphony/tracing.c +11 -0
  174. data/lib/polyphony.rb +136 -0
  175. data/lib/polyphony/adapters/fs.rb +19 -0
  176. data/lib/polyphony/adapters/irb.rb +52 -0
  177. data/lib/polyphony/adapters/postgres.rb +110 -0
  178. data/lib/polyphony/adapters/process.rb +33 -0
  179. data/lib/polyphony/adapters/redis.rb +67 -0
  180. data/lib/polyphony/adapters/trace.rb +138 -0
  181. data/lib/polyphony/core/channel.rb +46 -0
  182. data/lib/polyphony/core/exceptions.rb +36 -0
  183. data/lib/polyphony/core/global_api.rb +124 -0
  184. data/lib/polyphony/core/resource_pool.rb +117 -0
  185. data/lib/polyphony/core/sync.rb +21 -0
  186. data/lib/polyphony/core/thread_pool.rb +64 -0
  187. data/lib/polyphony/core/throttler.rb +41 -0
  188. data/lib/polyphony/event.rb +17 -0
  189. data/lib/polyphony/extensions/core.rb +174 -0
  190. data/lib/polyphony/extensions/fiber.rb +379 -0
  191. data/lib/polyphony/extensions/io.rb +221 -0
  192. data/lib/polyphony/extensions/openssl.rb +81 -0
  193. data/lib/polyphony/extensions/socket.rb +150 -0
  194. data/lib/polyphony/extensions/thread.rb +108 -0
  195. data/lib/polyphony/net.rb +77 -0
  196. data/lib/polyphony/version.rb +5 -0
  197. data/polyphony.gemspec +40 -0
  198. data/test/coverage.rb +54 -0
  199. data/test/eg.rb +27 -0
  200. data/test/helper.rb +56 -0
  201. data/test/q.rb +24 -0
  202. data/test/run.rb +5 -0
  203. data/test/stress.rb +25 -0
  204. data/test/test_agent.rb +130 -0
  205. data/test/test_event.rb +59 -0
  206. data/test/test_ext.rb +196 -0
  207. data/test/test_fiber.rb +988 -0
  208. data/test/test_global_api.rb +352 -0
  209. data/test/test_io.rb +249 -0
  210. data/test/test_kernel.rb +57 -0
  211. data/test/test_process_supervision.rb +46 -0
  212. data/test/test_queue.rb +112 -0
  213. data/test/test_resource_pool.rb +138 -0
  214. data/test/test_signal.rb +100 -0
  215. data/test/test_socket.rb +34 -0
  216. data/test/test_supervise.rb +103 -0
  217. data/test/test_thread.rb +170 -0
  218. data/test/test_thread_pool.rb +101 -0
  219. data/test/test_throttler.rb +50 -0
  220. data/test/test_trace.rb +68 -0
  221. metadata +482 -0
@@ -0,0 +1,34 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative 'helper'
4
+
5
+ class SocketTest < MiniTest::Test
6
+ def setup
7
+ super
8
+ end
9
+
10
+ def test_tcp
11
+ port = rand(1234..5678)
12
+ server = TCPServer.new('127.0.0.1', port)
13
+
14
+ server_fiber = spin do
15
+ while (socket = server.accept)
16
+ spin do
17
+ while (data = socket.gets(8192))
18
+ socket << data
19
+ end
20
+ end
21
+ end
22
+ end
23
+
24
+ snooze
25
+ client = TCPSocket.new('127.0.0.1', port)
26
+ client.write("1234\n")
27
+ assert_equal "1234\n", client.readpartial(8192)
28
+ client.close
29
+ ensure
30
+ server_fiber&.stop
31
+ server_fiber&.await
32
+ server&.close
33
+ end
34
+ end
@@ -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
@@ -0,0 +1,170 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative 'helper'
4
+ require 'polyphony/adapters/trace'
5
+
6
+ class ThreadTest < MiniTest::Test
7
+ def test_thread_spin
8
+ buffer = []
9
+ f = spin { (1..3).each { |i| snooze; buffer << i } }
10
+ t = Thread.new do
11
+ sleep 0.01
12
+ s1 = spin { (11..13).each { |i| snooze; buffer << i } }
13
+ s2 = spin { (21..23).each { |i| snooze; buffer << i } }
14
+ sleep 0.02
15
+ Fiber.current.await_all_children
16
+ end
17
+ f.join
18
+ t.join
19
+ t = nil
20
+
21
+ assert_equal [1, 2, 3, 11, 12, 13, 21, 22, 23], buffer.sort
22
+ ensure
23
+ t&.kill
24
+ t&.join
25
+ end
26
+
27
+ def test_thread_join
28
+ buffer = []
29
+ spin { (1..3).each { |i| snooze; buffer << i } }
30
+ t = Thread.new { sleep 0.01; buffer << 4; :foo }
31
+
32
+ r = t.join
33
+ t = nil
34
+
35
+ assert_equal :foo, r
36
+ assert_equal [1, 2, 3, 4], buffer
37
+ ensure
38
+ t&.kill
39
+ t&.join
40
+ end
41
+
42
+ def test_thread_join_with_timeout
43
+ buffer = []
44
+ spin { (1..3).each { |i| snooze; buffer << i } }
45
+ t = Thread.new { sleep 1; buffer << 4 }
46
+ t0 = Time.now
47
+ r = t.join(0.01)
48
+ t = nil
49
+
50
+ assert Time.now - t0 < 0.2
51
+ assert_equal [1, 2, 3], buffer
52
+ assert_nil r
53
+ ensure
54
+ # killing the thread will prevent stopping the sleep timer, as well as the
55
+ # thread's event selector, leading to a memory leak.
56
+ t&.kill
57
+ t&.join
58
+ end
59
+
60
+ def test_thread_await_alias_method
61
+ buffer = []
62
+ spin { (1..3).each { |i| snooze; buffer << i } }
63
+ t = Thread.new { sleep 0.01; buffer << 4; :foo }
64
+ r = t.await
65
+ t = nil
66
+
67
+ assert_equal [1, 2, 3, 4], buffer
68
+ assert_equal :foo, r
69
+ ensure
70
+ t&.kill
71
+ t&.join
72
+ end
73
+
74
+ def test_join_race_condition_on_thread_spawning
75
+ buffer = []
76
+ t = Thread.new do
77
+ :foo
78
+ end
79
+ r = t.join
80
+ t = nil
81
+ assert_equal :foo, r
82
+ ensure
83
+ t&.kill
84
+ t&.join
85
+ end
86
+
87
+ def test_thread_uncaught_exception_propagation
88
+ ready = Polyphony::Event.new
89
+
90
+ t = Thread.new do
91
+ ready.signal
92
+ sleep 0.01
93
+ raise 'foo'
94
+ end
95
+ e = nil
96
+ begin
97
+ ready.await
98
+ r = t.await
99
+ rescue Exception => e
100
+ end
101
+ t = nil
102
+ assert_kind_of RuntimeError, e
103
+ assert_equal 'foo', e.message
104
+ ensure
105
+ t&.kill
106
+ t&.join
107
+ end
108
+
109
+ def test_thread_inspect
110
+ lineno = __LINE__ + 1
111
+ t = Thread.new { sleep 1 }
112
+ str = format(
113
+ "#<Thread:%d %s:%d",
114
+ t.object_id,
115
+ __FILE__,
116
+ lineno,
117
+ )
118
+ assert t.inspect =~ /#{str}/
119
+ rescue => e
120
+ p e
121
+ puts e.backtrace.join("\n")
122
+ ensure
123
+ t&.kill
124
+ t&.join
125
+ end
126
+
127
+ def test_that_suspend_returns_immediately_if_no_watchers
128
+ records = []
129
+ t = Polyphony::Trace.new(:fiber_all) do |r|
130
+ records << r if r[:event] =~ /^fiber_/
131
+ end
132
+ t.enable
133
+ Polyphony.trace(true)
134
+
135
+ suspend
136
+ t.disable
137
+ assert_equal [:fiber_switchpoint], records.map { |r| r[:event] }
138
+ ensure
139
+ t&.disable
140
+ Polyphony.trace(false)
141
+ end
142
+
143
+ def test_thread_child_fiber_termination
144
+ buffer = []
145
+ t = Thread.new do
146
+ spin do
147
+ sleep 61
148
+ ensure
149
+ buffer << :foo
150
+ end
151
+ spin do
152
+ sleep 62
153
+ ensure
154
+ buffer << :bar
155
+ end
156
+ assert 2, Fiber.current.children.size
157
+ sleep 1
158
+ end
159
+ sleep 0.05
160
+ assert_equal 2, t.main_fiber.children.size
161
+ t.kill
162
+ t.join
163
+ t = nil
164
+
165
+ assert_equal [:foo, :bar], buffer
166
+ ensure
167
+ t&.kill
168
+ t&.join
169
+ end
170
+ end
@@ -0,0 +1,101 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative 'helper'
4
+
5
+ class ThreadPoolTest < MiniTest::Test
6
+ def setup
7
+ super
8
+ @pool = Polyphony::ThreadPool.new
9
+ end
10
+
11
+ def test_process
12
+ current_thread = Thread.current
13
+
14
+ processing_thread = nil
15
+ result = @pool.process do
16
+ processing_thread = Thread.current
17
+ +'foo' + 'bar'
18
+ end
19
+ assert_equal 'foobar', result
20
+ assert processing_thread != current_thread
21
+ end
22
+
23
+ def test_multi_process
24
+ current_thread = Thread.current
25
+ threads = []
26
+ results = []
27
+
28
+ 15.times do |i|
29
+ spin do
30
+ results << @pool.process do
31
+ threads << Thread.current
32
+ sleep 0.01
33
+ i * 10
34
+ end
35
+ end
36
+ end
37
+
38
+ suspend
39
+
40
+ assert_equal @pool.size, threads.uniq.size
41
+ assert_equal (0..14).map { |i| i * 10}, results.sort
42
+ end
43
+
44
+ def test_process_with_exception
45
+ result = nil
46
+ begin
47
+ result = @pool.process { raise 'foo' }
48
+ rescue => result
49
+ end
50
+
51
+ assert_kind_of RuntimeError, result
52
+ assert_equal 'foo', result.message
53
+ end
54
+
55
+ def test_cast
56
+ t0 = Time.now
57
+ threads = []
58
+ buffer = []
59
+ 10.times do |i|
60
+ @pool.cast do
61
+ sleep 0.01
62
+ threads << Thread.current
63
+ buffer << i
64
+ end
65
+ end
66
+ elapsed = Time.now - t0
67
+
68
+ assert elapsed < 0.007
69
+ assert buffer.size < 2
70
+
71
+ sleep 0.1 # allow time for threads to spawn
72
+ assert_equal @pool.size, threads.uniq.size
73
+ assert_equal (0..9).to_a, buffer.sort
74
+ end
75
+
76
+ def test_busy?
77
+ assert_equal false, @pool.busy?
78
+
79
+ f = spin do
80
+ @pool.process { sleep 0.001 }
81
+ end
82
+
83
+ snooze
84
+ assert_equal true, @pool.busy?
85
+ f.await
86
+
87
+ assert_equal false, @pool.busy?
88
+ end
89
+
90
+ def test_default_thread_pool_process
91
+ current_thread = Thread.current
92
+
93
+ processing_thread = nil
94
+ result = Polyphony::ThreadPool.process do
95
+ processing_thread = Thread.current
96
+ +'foo' + 'bar'
97
+ end
98
+ assert_equal 'foobar', result
99
+ assert processing_thread != current_thread
100
+ end
101
+ end
@@ -0,0 +1,50 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative 'helper'
4
+
5
+ class ThrottlerTest < MiniTest::Test
6
+ def test_throttler_with_rate
7
+ t = Polyphony::Throttler.new(10)
8
+ buffer = []
9
+ t0 = Time.now
10
+ f = spin { loop { t.process { buffer << 1 } } }
11
+ sleep 0.2
12
+ f.stop
13
+ elapsed = Time.now - t0
14
+ expected = (elapsed * 10).to_i
15
+ assert buffer.size >= expected - 1 && buffer.size <= expected + 1
16
+ ensure
17
+ t.stop
18
+ end
19
+
20
+ def test_throttler_with_hash_of_rate
21
+ t = Polyphony::Throttler.new(rate: 20)
22
+ buffer = []
23
+ f = spin do
24
+ loop { t.process { buffer << 1 } }
25
+ end
26
+ sleep 0.25
27
+ f.stop
28
+ assert (2..6).include?(buffer.size)
29
+ ensure
30
+ t.stop
31
+ end
32
+
33
+ def test_throttler_with_hash_of_interval
34
+ t = Polyphony::Throttler.new(interval: 0.01)
35
+ buffer = []
36
+ f = spin { loop { t.process { buffer << 1 } } }
37
+ sleep 0.02
38
+ f.stop
39
+ assert buffer.size >= 2
40
+ assert buffer.size <= 3
41
+ ensure
42
+ t.stop
43
+ end
44
+
45
+ def test_throttler_with_invalid_argument
46
+ assert_raises RuntimeError do
47
+ Polyphony::Throttler.new(:foobar)
48
+ end
49
+ end
50
+ end