polyphony 0.23 → 0.24
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG.md +7 -0
- data/Gemfile.lock +4 -10
- data/README.md +0 -4
- data/TODO.md +5 -56
- data/docs/README.md +4 -7
- data/examples/core/{channel_echo.rb → xx-channels.rb} +0 -0
- data/examples/core/{defer.rb → xx-deferring-an-operation.rb} +0 -0
- data/examples/core/{genserver.rb → xx-erlang-style-genserver.rb} +2 -2
- data/examples/core/{fork.rb → xx-forking.rb} +2 -0
- data/examples/core/xx-move_on.rb +23 -0
- data/examples/core/{pulse.rb → xx-recurrent-timer.rb} +3 -2
- data/examples/core/{resource_cancel.rb → xx-resource_cancel.rb} +1 -2
- data/examples/core/{resource_delegate.rb → xx-resource_delegate.rb} +0 -0
- data/examples/core/{wait_for_signal.rb → xx-signals.rb} +0 -0
- data/examples/core/{sleep.rb → xx-sleeping.rb} +0 -0
- data/examples/core/{spin_error_backtrace.rb → xx-spin_error_backtrace.rb} +5 -2
- data/examples/core/{supervisor.rb → xx-supervisors.rb} +0 -0
- data/examples/core/{thread_cancel.rb → xx-thread_cancel.rb} +0 -0
- data/examples/core/{thread_pool.rb → xx-thread_pool.rb} +0 -0
- data/examples/core/{throttle.rb → xx-throttling.rb} +0 -0
- data/examples/core/{timeout.rb → xx-timeout.rb} +0 -0
- data/examples/core/{lock.rb → xx-using-a-mutex.rb} +0 -0
- data/examples/io/{backticks.rb → xx-backticks.rb} +0 -0
- data/examples/io/{echo_client.rb → xx-echo_client.rb} +0 -1
- data/examples/io/{echo_client_from_stdin.rb → xx-echo_client_from_stdin.rb} +0 -1
- data/examples/io/{echo_pipe.rb → xx-echo_pipe.rb} +0 -0
- data/examples/io/{echo_server.rb → xx-echo_server.rb} +0 -0
- data/examples/io/{echo_server_with_timeout.rb → xx-echo_server_with_timeout.rb} +0 -0
- data/examples/io/{echo_stdin.rb → xx-echo_stdin.rb} +0 -0
- data/examples/io/xx-httparty.rb +13 -0
- data/examples/io/{irb.rb → xx-irb.rb} +0 -0
- data/examples/io/{net-http.rb → xx-net-http.rb} +0 -0
- data/examples/io/{open.rb → xx-open.rb} +0 -1
- data/examples/io/{system.rb → xx-system.rb} +0 -0
- data/examples/io/{tcpserver.rb → xx-tcpserver.rb} +0 -0
- data/examples/io/{tcpsocket.rb → xx-tcpsocket.rb} +0 -1
- data/examples/{fs/read.rb → performance/fs_read.rb} +0 -0
- data/examples/{core → performance}/mem-usage.rb +1 -0
- data/examples/performance/multi_snooze.rb +2 -0
- data/examples/performance/snooze.rb +2 -0
- data/examples/performance/thread-vs-fiber/polyphony_server.rb +5 -3
- data/examples/performance/thread-vs-fiber/threaded_server.rb +1 -1
- data/examples/{io/httparty_multi.rb → performance/thread-vs-fiber/xx-httparty_multi.rb} +16 -13
- data/examples/{io/httparty_threaded.rb → performance/thread-vs-fiber/xx-httparty_threaded.rb} +2 -2
- data/examples/performance/thread.rb +27 -0
- data/examples/{core → performance}/thread_pool_perf.rb +0 -0
- data/ext/gyro/extconf.rb +1 -0
- data/lib/polyphony/extensions/core.rb +0 -5
- data/lib/polyphony/version.rb +1 -1
- data/polyphony.gemspec +3 -9
- metadata +59 -167
- data/bin/poly +0 -11
- data/examples/core/cancel.rb +0 -13
- data/examples/core/enumerator.rb +0 -15
- data/examples/core/error_bubbling.rb +0 -35
- data/examples/core/fiber_error.rb +0 -9
- data/examples/core/fiber_error_with_backtrace.rb +0 -73
- data/examples/core/move_on.rb +0 -11
- data/examples/core/move_on_twice.rb +0 -16
- data/examples/core/move_on_with_ensure.rb +0 -13
- data/examples/core/move_on_with_value.rb +0 -14
- data/examples/core/multiple_spin.rb +0 -18
- data/examples/core/nested_cancel.rb +0 -40
- data/examples/core/nested_multiple_spin.rb +0 -20
- data/examples/core/nested_spin.rb +0 -19
- data/examples/core/pingpong.rb +0 -21
- data/examples/core/resource.rb +0 -30
- data/examples/core/sleep_spin.rb +0 -21
- data/examples/core/snooze.rb +0 -32
- data/examples/core/spin_error.rb +0 -17
- data/examples/core/spin_uncaught_error.rb +0 -16
- data/examples/core/supervisor_with_cancel_scope.rb +0 -23
- data/examples/core/supervisor_with_error.rb +0 -24
- data/examples/core/supervisor_with_manual_move_on.rb +0 -23
- data/examples/core/suspend.rb +0 -13
- data/examples/core/thread.rb +0 -27
- data/examples/http/config.ru +0 -7
- data/examples/http/cuba.ru +0 -22
- data/examples/http/happy_eyeballs.rb +0 -37
- data/examples/http/http2_raw.rb +0 -135
- data/examples/http/http_client.rb +0 -28
- data/examples/http/http_get.rb +0 -33
- data/examples/http/http_parse_experiment.rb +0 -123
- data/examples/http/http_proxy.rb +0 -83
- data/examples/http/http_server.js +0 -24
- data/examples/http/http_server.rb +0 -28
- data/examples/http/http_server_forked.rb +0 -29
- data/examples/http/http_server_graceful.rb +0 -27
- data/examples/http/http_server_simple.rb +0 -11
- data/examples/http/http_server_throttled.rb +0 -15
- data/examples/http/http_ws_server.rb +0 -37
- data/examples/http/https_raw_client.rb +0 -12
- data/examples/http/https_server.rb +0 -22
- data/examples/http/https_wss_server.rb +0 -39
- data/examples/http/rack_server.rb +0 -12
- data/examples/http/rack_server_https.rb +0 -19
- data/examples/http/rack_server_https_forked.rb +0 -27
- data/examples/http/websocket_secure_server.rb +0 -27
- data/examples/http/websocket_server.rb +0 -24
- data/examples/http/ws_page.html +0 -34
- data/examples/http/wss_page.html +0 -34
- data/examples/io/cat.rb +0 -12
- data/examples/io/httparty.rb +0 -10
- data/examples/io/io_read.rb +0 -9
- data/lib/ev_ext.bundle +0 -0
- data/lib/polyphony/http.rb +0 -16
- data/lib/polyphony/http/client/agent.rb +0 -131
- data/lib/polyphony/http/client/http1.rb +0 -129
- data/lib/polyphony/http/client/http2.rb +0 -180
- data/lib/polyphony/http/client/response.rb +0 -32
- data/lib/polyphony/http/client/site_connection_manager.rb +0 -109
- data/lib/polyphony/http/server.rb +0 -49
- data/lib/polyphony/http/server/http1.rb +0 -268
- data/lib/polyphony/http/server/http2.rb +0 -78
- data/lib/polyphony/http/server/http2_stream.rb +0 -136
- data/lib/polyphony/http/server/rack.rb +0 -64
- data/lib/polyphony/http/server/request.rb +0 -118
- data/lib/polyphony/websocket.rb +0 -59
- data/test/test_http_server.rb +0 -313
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 8a8da629de739b6091367c7220fd4a69dd83d7c78eb6d8c55c67385c8ca3edb2
|
4
|
+
data.tar.gz: 351f78d8b9635b6bc2c9838d652781a66009554287cfb5486c9fe0a0748ed6d6
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 768ed2703dd01653e5c71c2d17799b0c42fd9eb03f382dd3e4d3e4a337f7055d7a68643f479160febd3aa9412a9b66ccf0adf79f1608882ef0d61b625c8f7ed2
|
7
|
+
data.tar.gz: eab163c7ce680640def7fe6971359969202e6cb53238e8006c479e158c9b488bf73a2e575008a94cee1320fcf6899276da85df33d2fb00f97fa8133ad8fc3f06
|
data/CHANGELOG.md
CHANGED
data/Gemfile.lock
CHANGED
@@ -1,11 +1,8 @@
|
|
1
1
|
PATH
|
2
2
|
remote: .
|
3
3
|
specs:
|
4
|
-
polyphony (0.
|
5
|
-
|
6
|
-
http_parser.rb (= 0.6.0)
|
7
|
-
modulation (~> 0.25)
|
8
|
-
rack
|
4
|
+
polyphony (0.24)
|
5
|
+
modulation (~> 1.0)
|
9
6
|
|
10
7
|
GEM
|
11
8
|
remote: https://rubygems.org/
|
@@ -14,7 +11,6 @@ GEM
|
|
14
11
|
builder (3.2.4)
|
15
12
|
docile (1.3.2)
|
16
13
|
hiredis (0.6.3)
|
17
|
-
http-2 (0.10.0)
|
18
14
|
http_parser.rb (0.6.0)
|
19
15
|
httparty (0.17.0)
|
20
16
|
mime-types (~> 3.0)
|
@@ -30,10 +26,9 @@ GEM
|
|
30
26
|
builder
|
31
27
|
minitest (>= 5.0)
|
32
28
|
ruby-progressbar
|
33
|
-
modulation (0
|
29
|
+
modulation (1.0)
|
34
30
|
multi_xml (0.6.0)
|
35
31
|
pg (1.1.3)
|
36
|
-
rack (2.0.8)
|
37
32
|
rake (13.0.1)
|
38
33
|
rake-compiler (1.0.5)
|
39
34
|
rake
|
@@ -44,13 +39,13 @@ GEM
|
|
44
39
|
json (>= 1.8, < 3)
|
45
40
|
simplecov-html (~> 0.10.0)
|
46
41
|
simplecov-html (0.10.2)
|
47
|
-
websocket (1.2.8)
|
48
42
|
|
49
43
|
PLATFORMS
|
50
44
|
ruby
|
51
45
|
|
52
46
|
DEPENDENCIES
|
53
47
|
hiredis (= 0.6.3)
|
48
|
+
http_parser.rb (~> 0.6.0)
|
54
49
|
httparty (= 0.17.0)
|
55
50
|
localhost (= 1.1.4)
|
56
51
|
minitest (= 5.11.3)
|
@@ -60,7 +55,6 @@ DEPENDENCIES
|
|
60
55
|
rake-compiler (= 1.0.5)
|
61
56
|
redis (= 4.1.0)
|
62
57
|
simplecov (= 0.17.1)
|
63
|
-
websocket (= 1.2.8)
|
64
58
|
|
65
59
|
BUNDLED WITH
|
66
60
|
2.1.3
|
data/README.md
CHANGED
@@ -13,9 +13,6 @@ Polyphony makes it possible to use normal Ruby built-in classes like `IO`, and `
|
|
13
13
|
|
14
14
|
## Features
|
15
15
|
|
16
|
-
* **Full-blown, integrated, high-performance HTTP 1 / HTTP 2 / WebSocket server
|
17
|
-
with TLS/SSL termination, automatic ALPN protocol selection, and body
|
18
|
-
streaming**.
|
19
16
|
* Co-operative scheduling of concurrent tasks using Ruby fibers.
|
20
17
|
* High-performance event reactor for handling I/O events and timers.
|
21
18
|
* Natural, sequential programming style that makes it easy to reason about
|
@@ -25,7 +22,6 @@ Polyphony makes it possible to use normal Ruby built-in classes like `IO`, and `
|
|
25
22
|
* Code can use native networking classes and libraries, growing support for
|
26
23
|
third-party gems such as `pg` and `redis`.
|
27
24
|
* Use stdlib classes such as `TCPServer`, `TCPSocket` and
|
28
|
-
* HTTP 1 / HTTP 2 client agent with persistent connections.
|
29
25
|
* Competitive performance and scalability characteristics, in terms of both
|
30
26
|
throughput and memory consumption.
|
31
27
|
|
data/TODO.md
CHANGED
@@ -1,54 +1,8 @@
|
|
1
|
-
|
1
|
+
## 0.25 Move Other interface code into separate gem
|
2
2
|
|
3
|
-
The concurrency model and the fact that we want to serve the response object on
|
4
|
-
receiving headers and let the user lazily read the response body, means we'll
|
5
|
-
need to change the API to accept a block:
|
6
|
-
|
7
|
-
```ruby
|
8
|
-
# current API
|
9
|
-
resp = Agent.get('http://acme.org')
|
10
|
-
puts resp.body
|
11
|
-
|
12
|
-
# proposed API
|
13
|
-
Agent.get('http://acme.org') do |resp|
|
14
|
-
puts resp.body
|
15
|
-
end
|
16
|
-
```
|
17
|
-
|
18
|
-
While the block is running, the connection adapter is acquired. Once the block
|
19
|
-
is done running, the request (and response) can be discarded. The problem with
|
20
|
-
that if we spin up a coprocess from that block we risk all kinds of race
|
21
|
-
conditions and weird behaviours.
|
22
|
-
|
23
|
-
A compromise might be to allow the two: doing a `get` without providing a block
|
24
|
-
will return a response object that already has the body (i.e. the entire
|
25
|
-
response has already been received). Doing a `get` with a block will invoke the
|
26
|
-
block once headers are received, letting the user's code stream the body:
|
27
|
-
|
28
|
-
```ruby
|
29
|
-
def request(ctx, &block)
|
30
|
-
...
|
31
|
-
connection_manager.acquire do |adapter|
|
32
|
-
response = adapter.request(ctx)
|
33
|
-
if block
|
34
|
-
block.(response)
|
35
|
-
else
|
36
|
-
# wait for body
|
37
|
-
response.body
|
38
|
-
end
|
39
|
-
response
|
40
|
-
end
|
41
|
-
end
|
42
|
-
```
|
43
|
-
|
44
|
-
# Roadmap:
|
45
|
-
|
46
|
-
## 0.24 Move HTTP code into separate gem
|
47
|
-
|
48
|
-
- Pull out HTTP/websocket code, put into new `polyphony-http` gem
|
49
3
|
- Pull out redis/postgres code, put into new `polyphony-contrib` gem
|
50
4
|
|
51
|
-
## 0.
|
5
|
+
## 0.26 Full Rack adapter implementation
|
52
6
|
|
53
7
|
- Work better mechanism supervising multiple coprocesses (`when_done` feels a
|
54
8
|
bit hacky)
|
@@ -56,21 +10,16 @@ end
|
|
56
10
|
- Homogenize HTTP 1 and HTTP 2 headers - upcase ? downcase ?
|
57
11
|
- find some demo Rack apps and test with Polyphony
|
58
12
|
|
59
|
-
## 0.
|
13
|
+
## 0.27 Working Sinatra application
|
60
14
|
|
61
15
|
- app with database access (postgresql)
|
62
16
|
- benchmarks!
|
63
17
|
|
64
|
-
## 0.
|
18
|
+
## 0.28 Support for multi-threading
|
65
19
|
|
66
20
|
- Separate event loop for each thread
|
67
21
|
|
68
|
-
## 0.
|
69
|
-
|
70
|
-
- test thread / thread_pool modules
|
71
|
-
- report test coverage
|
72
|
-
|
73
|
-
## 0.29 Documentation
|
22
|
+
## 0.29 Testing && Docs
|
74
23
|
|
75
24
|
## 0.30 Integration
|
76
25
|
|
data/docs/README.md
CHANGED
@@ -1,8 +1,8 @@
|
|
1
1
|
# Polyphony - Easy Concurrency for Ruby
|
2
2
|
|
3
|
-
> Polyphony \| pəˈlɪf\(ə\)ni \|
|
4
|
-
|
5
|
-
|
3
|
+
> Polyphony \| pəˈlɪf\(ə\)ni \|
|
4
|
+
> 1. _Music_ the style of simultaneously combining a number of parts, each forming an individual melody and harmonizing with each other.
|
5
|
+
> 2. _Programming_ a Ruby gem for concurrent programming focusing on performance and developer happiness.
|
6
6
|
|
7
7
|
Polyphony is a library for building concurrent applications in Ruby. Polyphony harnesses the power of [Ruby fibers](https://ruby-doc.org/core-2.5.1/Fiber.html) to provide a cooperative, sequential coprocess-based concurrency model. Under the hood, Polyphony uses [libev](https://github.com/enki/libev) as a high-performance event reactor that provides timers, I/O watchers and other asynchronous event primitives.
|
8
8
|
|
@@ -10,14 +10,12 @@ Polyphony makes it possible to use normal Ruby built-in classes like `IO`, and `
|
|
10
10
|
|
11
11
|
## Features
|
12
12
|
|
13
|
-
* **Full-blown, integrated, high-performance HTTP 1 / HTTP 2 / WebSocket server with TLS/SSL termination, automatic ALPN protocol selection, and body streaming**.
|
14
13
|
* Co-operative scheduling of concurrent tasks using Ruby fibers.
|
15
14
|
* High-performance event reactor for handling I/O events and timers.
|
16
15
|
* Natural, sequential programming style that makes it easy to reason about concurrent code.
|
17
16
|
* Abstractions and constructs for controlling the execution of concurrent code: coprocesses, supervisors, cancel scopes, throttling, resource pools etc.
|
18
17
|
* Code can use native networking classes and libraries, growing support for third-party gems such as `pg` and `redis`.
|
19
18
|
* Use stdlib classes such as `TCPServer` and `TCPSocket` and `Net::HTTP`.
|
20
|
-
* HTTP 1 / HTTP 2 client agent with persistent connections.
|
21
19
|
* Competitive performance and scalability characteristics, in terms of both throughput and memory consumption.
|
22
20
|
|
23
21
|
## Prior Art
|
@@ -35,5 +33,4 @@ To learn more about using Polyphony to build concurrent applications, read the t
|
|
35
33
|
|
36
34
|
## Contributing to Polyphony
|
37
35
|
|
38
|
-
|
39
|
-
|
36
|
+
Issues and pull requests will be gladly accepted. Please use the git repository at https://github.com/digital-fabric/polyphony as your primary point of departure for contributing.
|
File without changes
|
File without changes
|
@@ -65,14 +65,14 @@ module Map
|
|
65
65
|
end
|
66
66
|
end
|
67
67
|
|
68
|
-
map_server = GenServer.start(Map, foo: :bar)
|
68
|
+
map_server = GenServer.start(Map, {foo: :bar})
|
69
69
|
|
70
70
|
puts 'getting value from map server'
|
71
71
|
v = map_server.get(:foo)
|
72
72
|
puts "value: #{v.inspect}"
|
73
73
|
|
74
74
|
puts 'putting value in map server'
|
75
|
-
map_server.put!(:foo,
|
75
|
+
map_server.put!(:foo, :baz)
|
76
76
|
|
77
77
|
puts 'getting value from map server'
|
78
78
|
v = map_server.get(:foo)
|
@@ -0,0 +1,23 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'bundler/setup'
|
4
|
+
require 'polyphony'
|
5
|
+
Exception.__disable_sanitized_backtrace__ = true
|
6
|
+
|
7
|
+
puts 'going to sleep...'
|
8
|
+
move_on_after(1) do
|
9
|
+
sleep 60
|
10
|
+
puts 'woke up'
|
11
|
+
end
|
12
|
+
|
13
|
+
puts 'going to sleep...'
|
14
|
+
move_on_after(0.5) do
|
15
|
+
t0 = Time.now
|
16
|
+
sleep(60)
|
17
|
+
ensure
|
18
|
+
puts 'woke up'
|
19
|
+
end
|
20
|
+
|
21
|
+
puts 'going to sleep...'
|
22
|
+
value = move_on_after(1, with_value: :bar) { sleep 60 }
|
23
|
+
puts "got value #{value.inspect}"
|
@@ -5,7 +5,7 @@ require 'polyphony'
|
|
5
5
|
|
6
6
|
resource_count = 0
|
7
7
|
Pool = Polyphony::ResourcePool.new(limit: 3) do
|
8
|
-
|
8
|
+
+"resource#{resource_count += 1}"
|
9
9
|
end
|
10
10
|
|
11
11
|
def user(number)
|
@@ -13,7 +13,6 @@ def user(number)
|
|
13
13
|
Polyphony::CancelScope.new(timeout: 0.2) do |scope|
|
14
14
|
scope.on_cancel { puts "#{number} (cancelled)" }
|
15
15
|
Pool.acquire do |r|
|
16
|
-
scope.disable
|
17
16
|
puts "#{number} #{r.inspect} >"
|
18
17
|
sleep(0.1 + rand * 0.2)
|
19
18
|
puts "#{number} #{r.inspect} <"
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
@@ -0,0 +1,13 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'bundler/setup'
|
4
|
+
require 'polyphony'
|
5
|
+
require 'httparty'
|
6
|
+
|
7
|
+
timer = spin { throttled_loop(100) {
|
8
|
+
STDOUT << '.'
|
9
|
+
} }
|
10
|
+
|
11
|
+
res = HTTParty.get('http://worldtimeapi.org/api/timezone/Europe/Paris')
|
12
|
+
puts res
|
13
|
+
timer.stop
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
@@ -18,7 +18,7 @@ class Http::Parser
|
|
18
18
|
end
|
19
19
|
end
|
20
20
|
|
21
|
-
|
21
|
+
def handle_client(socket)
|
22
22
|
parser = Http::Parser.new
|
23
23
|
req = nil
|
24
24
|
parser.on_message_complete = proc do |env|
|
@@ -47,12 +47,12 @@ def handle_request(client, parser)
|
|
47
47
|
end
|
48
48
|
|
49
49
|
spin do
|
50
|
-
server = TCPServer.open(1234)
|
50
|
+
server = TCPServer.open('0.0.0.0', 1234)
|
51
51
|
puts "listening on port 1234"
|
52
52
|
|
53
53
|
loop do
|
54
54
|
client = server.accept
|
55
|
-
|
55
|
+
spin { handle_client(client) }
|
56
56
|
end
|
57
57
|
rescue Exception => e
|
58
58
|
puts "uncaught exception: #{e.inspect}"
|
@@ -60,3 +60,5 @@ rescue Exception => e
|
|
60
60
|
exit!
|
61
61
|
server.close
|
62
62
|
end
|
63
|
+
|
64
|
+
suspend
|