polyphony 0.13 → 0.14
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.gitbook.yaml +5 -0
- data/.gitignore +55 -0
- data/.rubocop.yml +49 -0
- data/CHANGELOG.md +13 -2
- data/Gemfile +3 -0
- data/Gemfile.lock +31 -0
- data/LICENSE +21 -0
- data/README.md +35 -18
- data/Rakefile +20 -0
- data/TODO.md +49 -0
- data/docs/getting-started/getting-started.md +10 -0
- data/docs/getting-started/tutorial.md +2 -0
- data/docs/summary.md +9 -0
- data/examples/core/cancel.rb +10 -0
- data/examples/core/channel_echo.rb +43 -0
- data/examples/core/enumerator.rb +14 -0
- data/examples/core/fork.rb +22 -0
- data/examples/core/genserver.rb +74 -0
- data/examples/core/lock.rb +20 -0
- data/examples/core/move_on.rb +11 -0
- data/examples/core/move_on_twice.rb +17 -0
- data/examples/core/move_on_with_ensure.rb +17 -0
- data/examples/core/multiple_async.rb +17 -0
- data/examples/core/nested_async.rb +18 -0
- data/examples/core/nested_cancel.rb +41 -0
- data/examples/core/nested_multiple_async.rb +19 -0
- data/examples/core/next_tick.rb +13 -0
- data/examples/core/pulse.rb +13 -0
- data/examples/core/resource.rb +29 -0
- data/examples/core/resource_cancel.rb +34 -0
- data/examples/core/resource_delegate.rb +32 -0
- data/examples/core/sleep.rb +9 -0
- data/examples/core/sleep2.rb +13 -0
- data/examples/core/spawn.rb +15 -0
- data/examples/core/spawn_cancel.rb +19 -0
- data/examples/core/spawn_error.rb +28 -0
- data/examples/core/supervisor.rb +22 -0
- data/examples/core/supervisor_with_cancel_scope.rb +24 -0
- data/examples/core/supervisor_with_error.rb +23 -0
- data/examples/core/supervisor_with_manual_move_on.rb +25 -0
- data/examples/core/thread.rb +30 -0
- data/examples/core/thread_cancel.rb +30 -0
- data/examples/core/thread_pool.rb +60 -0
- data/examples/core/throttle.rb +17 -0
- data/examples/fs/read.rb +37 -0
- data/examples/interfaces/pg_client.rb +38 -0
- data/examples/interfaces/pg_pool.rb +37 -0
- data/examples/interfaces/pg_query.rb +32 -0
- data/examples/interfaces/redis_channels.rb +119 -0
- data/examples/interfaces/redis_client.rb +21 -0
- data/examples/interfaces/redis_pubsub.rb +26 -0
- data/examples/interfaces/redis_pubsub_perf.rb +65 -0
- data/examples/io/config.ru +3 -0
- data/examples/io/echo_client.rb +22 -0
- data/examples/io/echo_server.rb +14 -0
- data/examples/io/echo_server_with_timeout.rb +33 -0
- data/examples/io/echo_stdin.rb +15 -0
- data/examples/io/happy_eyeballs.rb +32 -0
- data/examples/io/http_client.rb +19 -0
- data/examples/io/http_server.js +24 -0
- data/examples/io/http_server.rb +16 -0
- data/examples/io/http_server_forked.rb +27 -0
- data/examples/io/http_server_throttled.rb +16 -0
- data/examples/io/http_ws_server.rb +42 -0
- data/examples/io/https_client.rb +17 -0
- data/examples/io/https_server.rb +23 -0
- data/examples/io/https_wss_server.rb +46 -0
- data/examples/io/rack_server.rb +19 -0
- data/examples/io/rack_server_https.rb +24 -0
- data/examples/io/rack_server_https_forked.rb +32 -0
- data/examples/io/websocket_server.rb +33 -0
- data/examples/io/ws_page.html +34 -0
- data/examples/io/wss_page.html +34 -0
- data/examples/performance/perf_multi_snooze.rb +21 -0
- data/examples/performance/perf_snooze.rb +30 -0
- data/examples/performance/thread-vs-fiber/polyphony_server.rb +63 -0
- data/examples/performance/thread-vs-fiber/threaded_server.rb +27 -0
- data/examples/streams/lines.rb +27 -0
- data/examples/streams/stdio.rb +18 -0
- data/ext/ev/async.c +168 -0
- data/ext/ev/child.c +169 -0
- data/ext/ev/ev.h +32 -0
- data/ext/ev/ev_ext.c +20 -0
- data/ext/ev/ev_module.c +222 -0
- data/ext/ev/io.c +405 -0
- data/ext/ev/libev.h +9 -0
- data/ext/ev/signal.c +119 -0
- data/ext/ev/timer.c +197 -0
- data/ext/libev/Changes +513 -0
- data/ext/libev/LICENSE +37 -0
- data/ext/libev/README +58 -0
- data/ext/libev/README.embed +3 -0
- data/ext/libev/ev.c +5214 -0
- data/ext/libev/ev.h +849 -0
- data/ext/libev/ev_epoll.c +285 -0
- data/ext/libev/ev_kqueue.c +218 -0
- data/ext/libev/ev_poll.c +151 -0
- data/ext/libev/ev_port.c +189 -0
- data/ext/libev/ev_select.c +316 -0
- data/ext/libev/ev_vars.h +204 -0
- data/ext/libev/ev_win32.c +162 -0
- data/ext/libev/ev_wrap.h +200 -0
- data/ext/libev/test_libev_win32.c +123 -0
- data/lib/polyphony.rb +7 -2
- data/lib/polyphony/core.rb +1 -1
- data/lib/polyphony/core/{coroutine.rb → coprocess.rb} +10 -10
- data/lib/polyphony/core/exceptions.rb +5 -5
- data/lib/polyphony/core/supervisor.rb +16 -16
- data/lib/polyphony/core/thread.rb +1 -1
- data/lib/polyphony/extensions/io.rb +43 -42
- data/lib/polyphony/extensions/kernel.rb +10 -34
- data/lib/polyphony/extensions/postgres.rb +3 -2
- data/lib/polyphony/extensions/redis.rb +1 -1
- data/lib/polyphony/extensions/socket.rb +8 -4
- data/lib/polyphony/extensions/ssl.rb +0 -54
- data/lib/polyphony/http/agent.rb +4 -10
- data/lib/polyphony/http/http1.rb +25 -25
- data/lib/polyphony/http/http1_request.rb +38 -26
- data/lib/polyphony/http/http2.rb +4 -5
- data/lib/polyphony/http/http2_request.rb +12 -18
- data/lib/polyphony/http/rack.rb +1 -3
- data/lib/polyphony/http/server.rb +9 -9
- data/lib/polyphony/net.rb +2 -2
- data/lib/polyphony/resource_pool.rb +5 -1
- data/lib/polyphony/version.rb +1 -1
- data/lib/polyphony/websocket.rb +52 -0
- data/polyphony.gemspec +31 -0
- data/test/test_coprocess.rb +131 -0
- data/test/test_core.rb +274 -0
- data/test/test_ev.rb +117 -0
- data/test/test_io.rb +38 -0
- metadata +113 -7
- data/lib/polyphony/core/async.rb +0 -36
- data/lib/polyphony/net_old.rb +0 -299
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 78b1d2bf93b1562b6ef1010acdf4a30993d6fd8f40e001ab13a00606e0ed2137
|
4
|
+
data.tar.gz: ea0f410c483ee06da41e1acdd342f9fccadf87c51bbca258571d8f5d2c6048a5
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 70af3ec736856b611bd1d4242f6430761b83382f88239a31a1a7e4124fbe6804153e08d248c03c61510c272f9511cdf7f6f4ada277eab2cbd6809f2e41daaa39
|
7
|
+
data.tar.gz: 678dad06dab6f6dbbccc23e39ac45e8045b4fdf0b2ea29959fd34e243d9d0f19f624ef80a8022f7dde4790e080302f59b06e65ec3ca26c9fe5efc4a70856f2c2
|
data/.gitbook.yaml
ADDED
data/.gitignore
ADDED
@@ -0,0 +1,55 @@
|
|
1
|
+
*.gem
|
2
|
+
*.rbc
|
3
|
+
/.config
|
4
|
+
/coverage/
|
5
|
+
/InstalledFiles
|
6
|
+
/pkg/
|
7
|
+
/spec/reports/
|
8
|
+
/spec/examples.txt
|
9
|
+
/test/tmp/
|
10
|
+
/test/version_tmp/
|
11
|
+
/tmp/
|
12
|
+
|
13
|
+
# Used by dotenv library to load environment variables.
|
14
|
+
# .env
|
15
|
+
|
16
|
+
## Specific to RubyMotion:
|
17
|
+
.dat*
|
18
|
+
.repl_history
|
19
|
+
build/
|
20
|
+
*.bridgesupport
|
21
|
+
build-iPhoneOS/
|
22
|
+
build-iPhoneSimulator/
|
23
|
+
|
24
|
+
## Specific to RubyMotion (use of CocoaPods):
|
25
|
+
#
|
26
|
+
# We recommend against adding the Pods directory to your .gitignore. However
|
27
|
+
# you should judge for yourself, the pros and cons are mentioned at:
|
28
|
+
# https://guides.cocoapods.org/using/using-cocoapods.html#should-i-check-the-pods-directory-into-source-control
|
29
|
+
#
|
30
|
+
# vendor/Pods/
|
31
|
+
|
32
|
+
## Documentation cache and generated files:
|
33
|
+
/.yardoc/
|
34
|
+
/_yardoc/
|
35
|
+
/doc/
|
36
|
+
/rdoc/
|
37
|
+
|
38
|
+
## Environment normalization:
|
39
|
+
/.bundle/
|
40
|
+
/vendor/bundle
|
41
|
+
/lib/bundler/man/
|
42
|
+
|
43
|
+
# for a library or gem, you might want to ignore these files since the code is
|
44
|
+
# intended to run in multiple environments; otherwise, check them in:
|
45
|
+
# Gemfile.lock
|
46
|
+
# .ruby-version
|
47
|
+
# .ruby-gemset
|
48
|
+
|
49
|
+
# unless supporting rvm < 1.11.0 or doing something fancy, ignore this:
|
50
|
+
.rvmrc
|
51
|
+
|
52
|
+
test.rb
|
53
|
+
.vscode
|
54
|
+
|
55
|
+
lib/ev_ext.bundle
|
data/.rubocop.yml
ADDED
@@ -0,0 +1,49 @@
|
|
1
|
+
AllCops:
|
2
|
+
TargetRubyVersion: 2.5
|
3
|
+
RubyInterpreters:
|
4
|
+
- ruby
|
5
|
+
Exclude:
|
6
|
+
- '**/*.gemspec'
|
7
|
+
- 'test/**/*.rb'
|
8
|
+
- 'examples/**/*.rb'
|
9
|
+
- 'Gemfile*'
|
10
|
+
|
11
|
+
Style/LambdaCall:
|
12
|
+
Enabled: false
|
13
|
+
# Style/ModuleFunction:
|
14
|
+
# Enabled: false
|
15
|
+
# Style/RegexpLiteral:
|
16
|
+
# Enabled: false
|
17
|
+
|
18
|
+
# Naming/MemoizedInstanceVariableName:
|
19
|
+
# Enabled: false
|
20
|
+
|
21
|
+
Style/Alias:
|
22
|
+
EnforcedStyle: prefer_alias_method
|
23
|
+
|
24
|
+
Style/SpecialGlobalVars:
|
25
|
+
Enabled: false
|
26
|
+
|
27
|
+
Style/ClassAndModuleChildren:
|
28
|
+
Enabled: false
|
29
|
+
|
30
|
+
Metrics/AbcSize:
|
31
|
+
Enabled: false
|
32
|
+
|
33
|
+
Style/MixinUsage:
|
34
|
+
Enabled: false
|
35
|
+
|
36
|
+
Style/MultilineBlockChain:
|
37
|
+
Enabled: false
|
38
|
+
|
39
|
+
Lint/RescueException:
|
40
|
+
Enabled: false
|
41
|
+
|
42
|
+
Lint/InheritException:
|
43
|
+
Enabled: false
|
44
|
+
|
45
|
+
Style/NumericPredicate:
|
46
|
+
Enabled: false
|
47
|
+
|
48
|
+
Style/TrivialAccessors:
|
49
|
+
Enabled: false
|
data/CHANGELOG.md
CHANGED
@@ -1,3 +1,14 @@
|
|
1
|
+
0.14 2019-05-17
|
2
|
+
---------------
|
3
|
+
|
4
|
+
* Use chunked encoding in HTTP 1 response
|
5
|
+
* Rewrite IO#read, #readpartial, #write in C (about 30% performance improvement)
|
6
|
+
* Add method delegation to `ResourcePool`
|
7
|
+
* Optimize PG::Connection#async_exec
|
8
|
+
* Fix Coprocess#cancel!
|
9
|
+
* Preliminary support for websocket (see `examples/io/http_ws_server.rb`)
|
10
|
+
* Rename `Coroutine` to `Coprocess`
|
11
|
+
|
1
12
|
0.13 2019-01-05
|
2
13
|
---------------
|
3
14
|
|
@@ -18,8 +29,8 @@
|
|
18
29
|
|
19
30
|
* Move reactor loop to secondary fiber, allow blocking operations on main
|
20
31
|
fiber.
|
21
|
-
* Example implementation of erlang-style generic server pattern (implement
|
22
|
-
|
32
|
+
* Example implementation of erlang-style generic server pattern (implement async
|
33
|
+
API to a coroutine)
|
23
34
|
* Implement coroutine mailboxes, Coroutine#<<, Coroutine#receive, Kernel.receive
|
24
35
|
for message passing
|
25
36
|
* Add Coroutine.current for getting current coroutine
|
data/Gemfile
ADDED
data/Gemfile.lock
ADDED
@@ -0,0 +1,31 @@
|
|
1
|
+
PATH
|
2
|
+
remote: .
|
3
|
+
specs:
|
4
|
+
polyphony (0.14)
|
5
|
+
http-2 (= 0.10.0)
|
6
|
+
http_parser.rb (= 0.6.0)
|
7
|
+
modulation (= 0.23)
|
8
|
+
|
9
|
+
GEM
|
10
|
+
remote: https://rubygems.org/
|
11
|
+
specs:
|
12
|
+
http-2 (0.10.0)
|
13
|
+
http_parser.rb (0.6.0)
|
14
|
+
localhost (1.1.4)
|
15
|
+
minitest (5.11.3)
|
16
|
+
modulation (0.23)
|
17
|
+
rake (12.3.2)
|
18
|
+
rake-compiler (1.0.5)
|
19
|
+
rake
|
20
|
+
|
21
|
+
PLATFORMS
|
22
|
+
ruby
|
23
|
+
|
24
|
+
DEPENDENCIES
|
25
|
+
localhost (= 1.1.4)
|
26
|
+
minitest (= 5.11.3)
|
27
|
+
polyphony!
|
28
|
+
rake-compiler (= 1.0.5)
|
29
|
+
|
30
|
+
BUNDLED WITH
|
31
|
+
1.17.2
|
data/LICENSE
ADDED
@@ -0,0 +1,21 @@
|
|
1
|
+
MIT License
|
2
|
+
|
3
|
+
Copyright (c) 2018 Sharon Rosner
|
4
|
+
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
7
|
+
in the Software without restriction, including without limitation the rights
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
10
|
+
furnished to do so, subject to the following conditions:
|
11
|
+
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
13
|
+
copies or substantial portions of the Software.
|
14
|
+
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
21
|
+
SOFTWARE.
|
data/README.md
CHANGED
@@ -19,7 +19,7 @@ supports Linux and MacOS only. This software is currently at the alpha stage.
|
|
19
19
|
Polyphony is a library for building concurrent applications in Ruby. Polyphony
|
20
20
|
harnesses the power of
|
21
21
|
[Ruby fibers](https://ruby-doc.org/core-2.5.1/Fiber.html) to provide a
|
22
|
-
cooperative, sequential
|
22
|
+
cooperative, sequential coprocess-based concurrency model. Under the hood,
|
23
23
|
Polyphony uses [libev](https://github.com/enki/libev) as a high-performance event
|
24
24
|
reactor that provides timers, I/O watchers and other asynchronous event
|
25
25
|
primitives.
|
@@ -31,16 +31,18 @@ takes care of context-switching automatically whenever a blocking call like
|
|
31
31
|
|
32
32
|
## Features
|
33
33
|
|
34
|
+
- **Full-blown, integrated, high-performance HTTP 1 / HTTP 2 / WebSocket server
|
35
|
+
with TLS/SSL termination and automatic ALPN protocol selection**.
|
34
36
|
- Co-operative scheduling of concurrent tasks using Ruby fibers.
|
35
37
|
- High-performance event reactor for handling I/O events and timers.
|
36
38
|
- Natural, sequential programming style that makes it easy to reason about
|
37
39
|
concurrent code.
|
38
|
-
-
|
40
|
+
- Abstractions and constructs for controlling the execution of concurrent code:
|
39
41
|
coprocesses, supervisors, cancel scopes, throttling, resource pools etc.
|
40
42
|
- Code can use native networking classes and libraries, growing support for
|
41
43
|
third-party gems such as `pg` and `redis`.
|
42
|
-
-
|
43
|
-
-
|
44
|
+
- HTTP 1 / HTTP 2 client
|
45
|
+
- Competitive performance and scalability characteristics, in terms of both
|
44
46
|
throughput and memory consumption.
|
45
47
|
|
46
48
|
## Prior Art
|
@@ -89,12 +91,12 @@ end
|
|
89
91
|
In the above example, both `sleep` calls will be executed concurrently, and thus
|
90
92
|
the program will take approximately only 1 second to execute. Note the lack of
|
91
93
|
any boilerplate relating to concurrency. Each `spawn` block starts a
|
92
|
-
*
|
94
|
+
*coprocess*, and is executed in sequential manner.
|
93
95
|
|
94
|
-
> **
|
95
|
-
> operations take place inside
|
96
|
-
> `Fiber`, which allows it to be suspended whenever a blocking operation is
|
97
|
-
> called, and resumed once that operation has been completed.
|
96
|
+
> **Coprocesses - the basic unit of concurrency**: In Polyphony, concurrent
|
97
|
+
> operations take place inside coprocesses. A `Coprocess` is executed on top of
|
98
|
+
> a `Fiber`, which allows it to be suspended whenever a blocking operation is
|
99
|
+
> called, and resumed once that operation has been completed. Coprocesses offer
|
98
100
|
> significant advantages over threads - they consume only about 10KB, switching
|
99
101
|
> between them is much faster than switching threads, and literally millions of
|
100
102
|
> them can be spawned without affecting performance*. Besides, Ruby does not yet
|
@@ -113,7 +115,7 @@ require 'polyphony'
|
|
113
115
|
|
114
116
|
server = TCPServer.open(1234)
|
115
117
|
while client = server.accept
|
116
|
-
# spawn starts a new
|
118
|
+
# spawn starts a new coprocess on a separate fiber
|
117
119
|
spawn {
|
118
120
|
while data = client.read rescue nil
|
119
121
|
client.write(data)
|
@@ -128,10 +130,10 @@ This example demonstrates several features of Polyphony:
|
|
128
130
|
server. The result of `server.accept` is also a native `TCPSocket` object.
|
129
131
|
There are no wrapper classes being used.
|
130
132
|
- The only hint of the code being concurrent is the use of `Kernel#spawn`,
|
131
|
-
which starts a new
|
133
|
+
which starts a new coprocess on a dedicated fiber. This allows serving
|
132
134
|
multiple clients at once. Whenever a blocking call is issued, such as
|
133
135
|
`#accept` or `#read`, execution is *yielded* to the event loop, which will
|
134
|
-
resume only those
|
136
|
+
resume only those coprocesses which are ready to be resumed.
|
135
137
|
- Exception handling is done using the normal Ruby constructs `raise`, `rescue`
|
136
138
|
and `ensure`. Exceptions never go unhandled (as might be the case with Ruby
|
137
139
|
threads), and must be dealt with explicitly. An unhandled exception will cause
|
@@ -224,9 +226,9 @@ In order to facilitate writing concurrent code, Polyphony provides additional
|
|
224
226
|
constructs that make it easier to spawn concurrent tasks and to control them.
|
225
227
|
|
226
228
|
`CancelScope` - an abstraction used to cancel the execution of one or more
|
227
|
-
|
229
|
+
coprocesses or supervisors. It usually works by defining a timeout for the
|
228
230
|
completion of a task. Any blocking operation can be cancelled, including
|
229
|
-
a
|
231
|
+
a coprocess or a supervisor. The developer may choose to cancel with or without
|
230
232
|
an exception with `cancel` or `move_on`, respectively. Cancel scopes are
|
231
233
|
typically started using `Kernel.cancel_after` and `Kernel.move_on`:
|
232
234
|
|
@@ -261,9 +263,24 @@ Pool = Polyphony::ResourcePool.new(limit: 5) {
|
|
261
263
|
}
|
262
264
|
```
|
263
265
|
|
264
|
-
|
265
|
-
to
|
266
|
-
|
266
|
+
You can also call arbitrary methods on the resource pool, which will be
|
267
|
+
delegated to the resource using `#method_missing`:
|
268
|
+
|
269
|
+
```ruby
|
270
|
+
# up to 5 concurrent connections
|
271
|
+
Pool = Polyphony::ResourcePool.new(limit: 5) {
|
272
|
+
# the block sets up the resource
|
273
|
+
PG.connect(...)
|
274
|
+
}
|
275
|
+
|
276
|
+
1000.times {
|
277
|
+
spawn { p Pool.query('select 1') }
|
278
|
+
}
|
279
|
+
```
|
280
|
+
|
281
|
+
`Supervisor` - a class used to control one or more `Coprocess`s. It can be used
|
282
|
+
to start, stop and restart multiple coprocesses. A supervisor can also be
|
283
|
+
used for awaiting the completion of multiple coprocesses. It is usually started
|
267
284
|
using `Kernel.supervise`:
|
268
285
|
|
269
286
|
```ruby
|
@@ -289,7 +306,7 @@ result = Polyphony::ThreadPool.process { long_running_process }
|
|
289
306
|
`Throttler` - a mechanism for throttling an arbitrary task, such as sending of
|
290
307
|
emails, or crawling a website. A throttler is normally created using
|
291
308
|
`Kernel.throttle`, and can even be used to throttle operations across multiple
|
292
|
-
|
309
|
+
coprocesses:
|
293
310
|
|
294
311
|
```ruby
|
295
312
|
server = Net.tcp_listen(1234)
|
data/Rakefile
ADDED
@@ -0,0 +1,20 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "bundler/gem_tasks"
|
4
|
+
require "rake/clean"
|
5
|
+
|
6
|
+
# frozen_string_literal: true
|
7
|
+
|
8
|
+
require "rake/extensiontask"
|
9
|
+
Rake::ExtensionTask.new("ev_ext") do |ext|
|
10
|
+
ext.ext_dir = "ext/ev"
|
11
|
+
end
|
12
|
+
|
13
|
+
task :default => [:compile, :test]
|
14
|
+
task :test do
|
15
|
+
Dir.glob('./test/test_*.rb').each { |file| require(file) }
|
16
|
+
end
|
17
|
+
|
18
|
+
# task default: %w[compile]# spec rubocop]
|
19
|
+
|
20
|
+
CLEAN.include "**/*.o", "**/*.so", "**/*.bundle", "**/*.jar", "pkg", "tmp"
|
data/TODO.md
ADDED
@@ -0,0 +1,49 @@
|
|
1
|
+
## Testing
|
2
|
+
|
3
|
+
- test IO
|
4
|
+
- test TCP server / client
|
5
|
+
- test thread / thread_pool modules
|
6
|
+
|
7
|
+
## UDP socket
|
8
|
+
|
9
|
+
```ruby
|
10
|
+
socket = UDPSocket.new
|
11
|
+
socket.bind("127.0.0.1", 1234)
|
12
|
+
|
13
|
+
socket.send "message-to-self", 0, "127.0.0.1", 1234
|
14
|
+
p socket.recvfrom(10)
|
15
|
+
#=> ["message-to", ["AF_INET", 4913, "localhost", "127.0.0.1"]]
|
16
|
+
```
|
17
|
+
|
18
|
+
## DNS client
|
19
|
+
|
20
|
+
```ruby
|
21
|
+
ip_address = DNS.lookup('google.com', 'A')
|
22
|
+
```
|
23
|
+
|
24
|
+
Prior art:
|
25
|
+
|
26
|
+
- https://github.com/alexdalitz/dnsruby
|
27
|
+
- https://github.com/eventmachine/eventmachine/blob/master/lib/em/resolver.rb
|
28
|
+
- https://github.com/gmodarelli/em-resolv-replace/blob/master/lib/em-dns-resolver.rb
|
29
|
+
- https://github.com/socketry/async-dns
|
30
|
+
|
31
|
+
### DNS server
|
32
|
+
|
33
|
+
```ruby
|
34
|
+
Server = import('../../lib/polyphony/dns/server')
|
35
|
+
|
36
|
+
server = Server.new do |transaction|
|
37
|
+
puts "got query from #{transaction.info[:client_ip_address]}"
|
38
|
+
transaction.questions.each do |q|
|
39
|
+
respond(transaction, q[:domain], q[:resource_class])
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
43
|
+
server.listen(port: 5300)
|
44
|
+
puts "listening on port 5300"
|
45
|
+
```
|
46
|
+
|
47
|
+
Prior art:
|
48
|
+
|
49
|
+
- https://github.com/socketry/async-dns
|
data/docs/summary.md
ADDED
@@ -0,0 +1,43 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'modulation'
|
4
|
+
|
5
|
+
Polyphony = import('../../lib/polyphony')
|
6
|
+
|
7
|
+
def echo(rchan, wchan)
|
8
|
+
puts "start echoer"
|
9
|
+
while msg = rchan.receive
|
10
|
+
wchan << "you said: #{msg}"
|
11
|
+
end
|
12
|
+
ensure
|
13
|
+
puts "echoer stopped"
|
14
|
+
end
|
15
|
+
|
16
|
+
chan1, chan2 = Polyphony::Channel.new, Polyphony::Channel.new
|
17
|
+
|
18
|
+
echoer = spawn { echo(chan1, chan2) }
|
19
|
+
|
20
|
+
spawn do
|
21
|
+
puts "start receiver"
|
22
|
+
while msg = chan2.receive
|
23
|
+
puts msg
|
24
|
+
$main.resume if msg =~ /world/
|
25
|
+
end
|
26
|
+
ensure
|
27
|
+
puts "receiver stopped"
|
28
|
+
end
|
29
|
+
|
30
|
+
$main = spawn do
|
31
|
+
t0 = Time.now
|
32
|
+
puts "send hello"
|
33
|
+
chan1 << "hello"
|
34
|
+
puts "send world"
|
35
|
+
chan1 << "world"
|
36
|
+
|
37
|
+
suspend
|
38
|
+
|
39
|
+
puts "closing channels"
|
40
|
+
chan1.close
|
41
|
+
chan2.close
|
42
|
+
puts "done #{Time.now - t0}"
|
43
|
+
end
|