polyphony 0.42 → 0.43.4

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.
@@ -482,9 +482,9 @@ class FiberTest < MiniTest::Test
482
482
  def test_select_from_multiple_fibers
483
483
  sleep 0
484
484
  buffer = []
485
- f1 = spin { sleep 0.01; buffer << :foo; :foo }
486
- f2 = spin { sleep 0.03; buffer << :bar; :bar }
487
- f3 = spin { sleep 0.05; buffer << :baz; :baz }
485
+ f1 = spin { sleep 0.1; buffer << :foo; :foo }
486
+ f2 = spin { sleep 0.3; buffer << :bar; :bar }
487
+ f3 = spin { sleep 0.5; buffer << :baz; :baz }
488
488
 
489
489
  selected, result = Fiber.select(f1, f2, f3)
490
490
  assert_equal :foo, result
@@ -106,7 +106,7 @@ class MoveOnAfterTest < MiniTest::Test
106
106
  end
107
107
  t1 = Time.now
108
108
 
109
- assert t1 - t0 < 0.03
109
+ assert t1 - t0 < 0.1
110
110
  assert_nil v
111
111
  end
112
112
 
@@ -118,7 +118,7 @@ class MoveOnAfterTest < MiniTest::Test
118
118
  end
119
119
  t1 = Time.now
120
120
 
121
- assert t1 - t0 < 0.02
121
+ assert t1 - t0 < 0.1
122
122
  assert_equal :bar, v
123
123
  end
124
124
 
@@ -129,7 +129,7 @@ class MoveOnAfterTest < MiniTest::Test
129
129
  assert_equal Fiber.current, f.parent
130
130
  v = sleep 1
131
131
  t1 = Time.now
132
- assert t1 - t0 < 0.02
132
+ assert t1 - t0 < 0.1
133
133
  assert_equal 'foo', v
134
134
  end
135
135
  end
@@ -145,7 +145,7 @@ class CancelAfterTest < MiniTest::Test
145
145
  end
146
146
  end
147
147
  t1 = Time.now
148
- assert t1 - t0 < 0.02
148
+ assert t1 - t0 < 0.1
149
149
  end
150
150
 
151
151
  def test_cancel_after_without_block
@@ -157,7 +157,31 @@ class CancelAfterTest < MiniTest::Test
157
157
  sleep 1
158
158
  end
159
159
  t1 = Time.now
160
- assert t1 - t0 < 0.02
160
+ assert t1 - t0 < 0.1
161
+ end
162
+
163
+ class CustomException < Exception
164
+ end
165
+
166
+ def test_cancel_after_with_custom_exception
167
+ assert_raises CustomException do
168
+ cancel_after(0.01, with_exception: CustomException) do
169
+ sleep 1
170
+ :foo
171
+ end
172
+ end
173
+
174
+ begin
175
+ e = nil
176
+ cancel_after(0.01, with_exception: 'foo') do
177
+ sleep 1
178
+ :foo
179
+ end
180
+ rescue => e
181
+ ensure
182
+ assert_kind_of RuntimeError, e
183
+ assert_equal 'foo', e.message
184
+ end
161
185
  end
162
186
  end
163
187
 
@@ -201,10 +225,13 @@ class SpinLoopTest < MiniTest::Test
201
225
  def test_spin_loop_with_rate
202
226
  buffer = []
203
227
  counter = 0
204
- f = spin_loop(rate: 50) { buffer << (counter += 1) }
228
+ t0 = Time.now
229
+ f = spin_loop(rate: 10) { buffer << (counter += 1) }
205
230
  sleep 0.2
206
231
  f.stop
207
- assert counter >= 9 && counter <= 11
232
+ elapsed = Time.now - t0
233
+ expected = (elapsed * 10).to_i
234
+ assert counter >= expected - 1 && counter <= expected + 1
208
235
  end
209
236
  end
210
237
 
@@ -212,12 +239,15 @@ class ThrottledLoopTest < MiniTest::Test
212
239
  def test_throttled_loop
213
240
  buffer = []
214
241
  counter = 0
242
+ t0 = Time.now
215
243
  f = spin do
216
- throttled_loop(50) { buffer << (counter += 1) }
244
+ throttled_loop(10) { buffer << (counter += 1) }
217
245
  end
218
- sleep 0.2
246
+ sleep 0.3
219
247
  f.stop
220
- assert counter >= 9 && counter <= 11
248
+ elapsed = Time.now - t0
249
+ expected = (elapsed * 10).to_i
250
+ assert counter >= expected - 1 && counter <= expected + 1
221
251
  end
222
252
 
223
253
  def test_throttled_loop_with_count
@@ -243,19 +273,22 @@ class GlobalAPIEtcTest < MiniTest::Test
243
273
 
244
274
  def test_every
245
275
  buffer = []
276
+ t0 = Time.now
246
277
  f = spin do
247
- every(0.01) { buffer << 1 }
278
+ every(0.1) { buffer << 1 }
248
279
  end
249
- sleep 0.05
280
+ sleep 0.5
250
281
  f.stop
251
- assert (4..5).include?(buffer.size)
282
+ elapsed = Time.now - t0
283
+ expected = (elapsed / 0.1).to_i
284
+ assert buffer.size >= expected - 2 && buffer.size <= expected + 2
252
285
  end
253
286
 
254
287
  def test_sleep
255
288
  t0 = Time.now
256
- sleep 0.05
289
+ sleep 0.1
257
290
  elapsed = Time.now - t0
258
- assert (0.045..0.08).include? elapsed
291
+ assert (0.05..0.15).include? elapsed
259
292
 
260
293
  f = spin { sleep }
261
294
  snooze
@@ -123,4 +123,16 @@ class ResourcePoolTest < MiniTest::Test
123
123
  pool.preheat!
124
124
  assert_equal 2, pool.size
125
125
  end
126
+
127
+ def test_reentrant_resource_pool
128
+ resources = [+'a', +'b']
129
+ pool = Polyphony::ResourcePool.new(limit: 1) { resources.shift }
130
+
131
+ pool.acquire do |r|
132
+ assert_equal 'a', r
133
+ pool.acquire do |r|
134
+ assert_equal 'a', r
135
+ end
136
+ end
137
+ end
126
138
  end
@@ -8,7 +8,8 @@ class SocketTest < MiniTest::Test
8
8
  end
9
9
 
10
10
  def test_tcp
11
- server = TCPServer.new('127.0.0.1', 1234)
11
+ port = rand(1234..5678)
12
+ server = TCPServer.new('127.0.0.1', port)
12
13
 
13
14
  server_fiber = spin do
14
15
  while (socket = server.accept)
@@ -21,13 +22,13 @@ class SocketTest < MiniTest::Test
21
22
  end
22
23
 
23
24
  snooze
24
- client = TCPSocket.new('127.0.0.1', 1234)
25
+ client = TCPSocket.new('127.0.0.1', port)
25
26
  client.write("1234\n")
26
27
  assert_equal "1234\n", client.readpartial(8192)
27
28
  client.close
28
29
  ensure
29
- server_fiber.stop
30
- snooze
30
+ server_fiber&.stop
31
+ server_fiber&.await
31
32
  server&.close
32
33
  end
33
34
  end
@@ -4,14 +4,15 @@ require_relative 'helper'
4
4
 
5
5
  class ThrottlerTest < MiniTest::Test
6
6
  def test_throttler_with_rate
7
- t = Polyphony::Throttler.new(100)
7
+ t = Polyphony::Throttler.new(10)
8
8
  buffer = []
9
+ t0 = Time.now
9
10
  f = spin { loop { t.process { buffer << 1 } } }
10
- sleep 0.02
11
+ sleep 0.2
11
12
  f.stop
12
- snooze
13
- assert buffer.size >= 2
14
- assert buffer.size <= 3
13
+ elapsed = Time.now - t0
14
+ expected = (elapsed * 10).to_i
15
+ assert buffer.size >= expected - 1 && buffer.size <= expected + 1
15
16
  ensure
16
17
  t.stop
17
18
  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.42'
4
+ version: 0.43.4
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-07-03 00:00:00.000000000 Z
11
+ date: 2020-07-09 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: httparty
@@ -267,6 +267,7 @@ files:
267
267
  - docs/assets/img/echo-fibers.svg
268
268
  - docs/assets/img/sleeping-fiber.svg
269
269
  - docs/faq.md
270
+ - docs/favicon.ico
270
271
  - docs/getting-started/index.md
271
272
  - docs/getting-started/installing.md
272
273
  - docs/getting-started/overview.md
@@ -278,10 +279,13 @@ files:
278
279
  - docs/main-concepts/extending.md
279
280
  - docs/main-concepts/fiber-scheduling.md
280
281
  - docs/main-concepts/index.md
282
+ - docs/polyphony-logo.png
283
+ - examples/adapters/concurrent-ruby.rb
281
284
  - examples/adapters/pg_client.rb
282
285
  - examples/adapters/pg_notify.rb
283
286
  - examples/adapters/pg_pool.rb
284
287
  - examples/adapters/pg_transaction.rb
288
+ - examples/adapters/redis_blpop.rb
285
289
  - examples/adapters/redis_channels.rb
286
290
  - examples/adapters/redis_client.rb
287
291
  - examples/adapters/redis_pubsub.rb
@@ -294,6 +298,7 @@ files:
294
298
  - examples/core/xx-at_exit.rb
295
299
  - examples/core/xx-caller.rb
296
300
  - examples/core/xx-channels.rb
301
+ - examples/core/xx-daemon.rb
297
302
  - examples/core/xx-deadlock.rb
298
303
  - examples/core/xx-deferring-an-operation.rb
299
304
  - examples/core/xx-erlang-style-genserver.rb
@@ -386,7 +391,6 @@ files:
386
391
  - ext/polyphony/polyphony.c
387
392
  - ext/polyphony/polyphony.h
388
393
  - ext/polyphony/polyphony_ext.c
389
- - ext/polyphony/socket.c
390
394
  - ext/polyphony/thread.c
391
395
  - ext/polyphony/tracing.c
392
396
  - lib/polyphony.rb
@@ -1,213 +0,0 @@
1
- #include "polyphony.h"
2
- #include <sys/socket.h>
3
-
4
- static VALUE cTCPSocket;
5
-
6
- ///////////////////////////////////////////////////////////////////////////
7
-
8
- struct rsock_send_arg {
9
- int fd, flags;
10
- VALUE mesg;
11
- struct sockaddr *to;
12
- socklen_t tolen;
13
- };
14
-
15
- #define StringValue(v) rb_string_value(&(v))
16
- #define IS_ADDRINFO(obj) rb_typeddata_is_kind_of((obj), &addrinfo_type)
17
-
18
- VALUE
19
- rsock_sockaddr_string_value(volatile VALUE *v)
20
- {
21
- // VALUE val = *v;
22
- // if (IS_ADDRINFO(val)) {
23
- // *v = addrinfo_to_sockaddr(val);
24
- // }
25
- StringValue(*v);
26
- return *v;
27
- }
28
-
29
- #define SockAddrStringValue(v) rsock_sockaddr_string_value(&(v))
30
- #define RSTRING_LENINT(str) rb_long2int(RSTRING_LEN(str))
31
- #ifndef RSTRING_SOCKLEN
32
- # define RSTRING_SOCKLEN (socklen_t)RSTRING_LENINT
33
- #endif
34
-
35
- #if defined __APPLE__
36
- # define do_write_retry(code) do {ret = code;} while (ret == -1 && errno == EPROTOTYPE)
37
- #else
38
- # define do_write_retry(code) ret = code
39
- #endif
40
-
41
- VALUE
42
- rsock_sendto_blocking(void *data)
43
- {
44
- struct rsock_send_arg *arg = data;
45
- VALUE mesg = arg->mesg;
46
- ssize_t ret;
47
- do_write_retry(sendto(arg->fd, RSTRING_PTR(mesg), RSTRING_LEN(mesg),
48
- arg->flags, arg->to, arg->tolen));
49
- return (VALUE)ret;
50
- }
51
-
52
- VALUE
53
- rsock_send_blocking(void *data)
54
- {
55
- struct rsock_send_arg *arg = data;
56
- VALUE mesg = arg->mesg;
57
- ssize_t ret;
58
- do_write_retry(send(arg->fd, RSTRING_PTR(mesg), RSTRING_LEN(mesg),
59
- arg->flags));
60
- return (VALUE)ret;
61
- }
62
-
63
- ///////////////////////////////////////////////////////////////////////////
64
-
65
- static VALUE BasicSocket_send(int argc, VALUE *argv, VALUE sock) {
66
- VALUE underlying_socket = rb_iv_get(sock, "@io");
67
- if (!NIL_P(underlying_socket)) sock = underlying_socket;
68
- struct rsock_send_arg arg;
69
- VALUE flags, to;
70
- rb_io_t *fptr;
71
- ssize_t n;
72
- rb_blocking_function_t *func;
73
- const char *funcname;
74
- VALUE agent = Qnil;
75
-
76
- rb_scan_args(argc, argv, "21", &arg.mesg, &flags, &to);
77
-
78
- StringValue(arg.mesg);
79
-
80
- if (!NIL_P(to)) {
81
- SockAddrStringValue(to);
82
- to = rb_str_new4(to);
83
- arg.to = (struct sockaddr *)RSTRING_PTR(to);
84
- arg.tolen = RSTRING_SOCKLEN(to);
85
- func = rsock_sendto_blocking;
86
- funcname = "sendto(2)";
87
- }
88
- else {
89
- func = rsock_send_blocking;
90
- funcname = "send(2)";
91
- }
92
- GetOpenFile(sock, fptr);
93
- rb_io_set_nonblock(fptr);
94
- arg.fd = fptr->fd;
95
- arg.flags = NUM2INT(flags);
96
- while ((n = (ssize_t)func(&arg)) < 0) {
97
- if (NIL_P(agent))
98
- agent = rb_ivar_get(rb_thread_current(), ID_ivar_agent);
99
- LibevAgent_wait_io(agent, sock, Qtrue);
100
- }
101
- return SSIZET2NUM(n);
102
- }
103
-
104
- static VALUE BasicSocket_recv(int argc, VALUE *argv, VALUE sock) {
105
- VALUE underlying_socket = rb_iv_get(sock, "@io");
106
- if (!NIL_P(underlying_socket)) sock = underlying_socket;
107
- long len = argc >= 1 ? NUM2LONG(argv[0]) : 8192;
108
- if (len < 0) {
109
- rb_raise(rb_eArgError, "negative length %ld given", len);
110
- }
111
-
112
- rb_io_t *fptr;
113
- long n;
114
- int shrinkable;
115
- VALUE agent = Qnil;
116
-
117
-
118
- VALUE str = argc >= 3 ? argv[2] : Qnil;
119
-
120
- shrinkable = io_setstrbuf(&str, len);
121
- OBJ_TAINT(str);
122
- GetOpenFile(sock, fptr);
123
- // rb_io_set_nonblock(fptr);
124
- rb_io_check_byte_readable(fptr);
125
-
126
- if (len == 0)
127
- return str;
128
-
129
- while (1) {
130
- n = recv(fptr->fd, RSTRING_PTR(str), len, MSG_DONTWAIT);
131
- if (n < 0) {
132
- int e = errno;
133
- if (e == EWOULDBLOCK || e == EAGAIN) {
134
- if (NIL_P(agent))
135
- agent = rb_ivar_get(rb_thread_current(), ID_ivar_agent);
136
- LibevAgent_wait_io(agent, sock, Qnil);
137
- }
138
- else
139
- rb_syserr_fail(e, strerror(e));
140
- // rb_syserr_fail_path(e, fptr->pathv);
141
- }
142
- else
143
- break;
144
- }
145
-
146
- io_set_read_length(str, n, shrinkable);
147
- io_enc_str(str, fptr);
148
-
149
- if (n == 0)
150
- return Qnil;
151
-
152
- return str;
153
- }
154
-
155
- static VALUE Socket_accept(VALUE sock) {
156
- rb_io_t *fptr;
157
- int fd;
158
- struct sockaddr addr;
159
- socklen_t len = (socklen_t)sizeof addr;
160
- VALUE agent = Qnil;
161
-
162
- GetOpenFile(sock, fptr);
163
- rb_io_set_nonblock(fptr);
164
-
165
- while (1) {
166
- fd = accept(fptr->fd, &addr, &len);
167
-
168
- if (fd < 0) {
169
- int e = errno;
170
- if (e == EWOULDBLOCK || e == EAGAIN) {
171
- if (NIL_P(agent))
172
- agent = rb_ivar_get(rb_thread_current(), ID_ivar_agent);
173
- LibevAgent_wait_io(agent, sock, Qnil);
174
- }
175
- else
176
- rb_syserr_fail(e, strerror(e));
177
- // rb_syserr_fail_path(e, fptr->pathv);
178
- }
179
- else {
180
- VALUE connection = rb_obj_alloc(cTCPSocket);
181
- rb_io_t *fp;
182
- MakeOpenFile(connection, fp);
183
- rb_update_max_fd(fd);
184
- fp->fd = fd;
185
- fp->mode = FMODE_READWRITE | FMODE_DUPLEX;
186
- rb_io_ascii8bit_binmode(connection);
187
- rb_io_set_nonblock(fp);
188
- rb_io_synchronized(fp);
189
- // if (rsock_do_not_reverse_lookup) {
190
- // fp->mode |= FMODE_NOREVLOOKUP;
191
- // }
192
-
193
- return connection;
194
- }
195
- }
196
- }
197
-
198
- void Init_Socket() {
199
- VALUE cBasicSocket;
200
- VALUE cSocket;
201
-
202
- rb_require("socket");
203
- cBasicSocket = rb_const_get(rb_cObject, rb_intern("BasicSocket"));
204
-
205
- rb_define_method(cBasicSocket, "send", BasicSocket_send, -1);
206
- rb_define_method(cBasicSocket, "recv", BasicSocket_recv, -1);
207
-
208
- cSocket = rb_const_get(rb_cObject, rb_intern("Socket"));
209
-
210
- // rb_define_method(cSocket, "accept", Socket_accept, 0);
211
-
212
- cTCPSocket = rb_const_get(rb_cObject, rb_intern("TCPSocket"));
213
- }