polyphony 0.23 → 0.24

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 (120) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +7 -0
  3. data/Gemfile.lock +4 -10
  4. data/README.md +0 -4
  5. data/TODO.md +5 -56
  6. data/docs/README.md +4 -7
  7. data/examples/core/{channel_echo.rb → xx-channels.rb} +0 -0
  8. data/examples/core/{defer.rb → xx-deferring-an-operation.rb} +0 -0
  9. data/examples/core/{genserver.rb → xx-erlang-style-genserver.rb} +2 -2
  10. data/examples/core/{fork.rb → xx-forking.rb} +2 -0
  11. data/examples/core/xx-move_on.rb +23 -0
  12. data/examples/core/{pulse.rb → xx-recurrent-timer.rb} +3 -2
  13. data/examples/core/{resource_cancel.rb → xx-resource_cancel.rb} +1 -2
  14. data/examples/core/{resource_delegate.rb → xx-resource_delegate.rb} +0 -0
  15. data/examples/core/{wait_for_signal.rb → xx-signals.rb} +0 -0
  16. data/examples/core/{sleep.rb → xx-sleeping.rb} +0 -0
  17. data/examples/core/{spin_error_backtrace.rb → xx-spin_error_backtrace.rb} +5 -2
  18. data/examples/core/{supervisor.rb → xx-supervisors.rb} +0 -0
  19. data/examples/core/{thread_cancel.rb → xx-thread_cancel.rb} +0 -0
  20. data/examples/core/{thread_pool.rb → xx-thread_pool.rb} +0 -0
  21. data/examples/core/{throttle.rb → xx-throttling.rb} +0 -0
  22. data/examples/core/{timeout.rb → xx-timeout.rb} +0 -0
  23. data/examples/core/{lock.rb → xx-using-a-mutex.rb} +0 -0
  24. data/examples/io/{backticks.rb → xx-backticks.rb} +0 -0
  25. data/examples/io/{echo_client.rb → xx-echo_client.rb} +0 -1
  26. data/examples/io/{echo_client_from_stdin.rb → xx-echo_client_from_stdin.rb} +0 -1
  27. data/examples/io/{echo_pipe.rb → xx-echo_pipe.rb} +0 -0
  28. data/examples/io/{echo_server.rb → xx-echo_server.rb} +0 -0
  29. data/examples/io/{echo_server_with_timeout.rb → xx-echo_server_with_timeout.rb} +0 -0
  30. data/examples/io/{echo_stdin.rb → xx-echo_stdin.rb} +0 -0
  31. data/examples/io/xx-httparty.rb +13 -0
  32. data/examples/io/{irb.rb → xx-irb.rb} +0 -0
  33. data/examples/io/{net-http.rb → xx-net-http.rb} +0 -0
  34. data/examples/io/{open.rb → xx-open.rb} +0 -1
  35. data/examples/io/{system.rb → xx-system.rb} +0 -0
  36. data/examples/io/{tcpserver.rb → xx-tcpserver.rb} +0 -0
  37. data/examples/io/{tcpsocket.rb → xx-tcpsocket.rb} +0 -1
  38. data/examples/{fs/read.rb → performance/fs_read.rb} +0 -0
  39. data/examples/{core → performance}/mem-usage.rb +1 -0
  40. data/examples/performance/multi_snooze.rb +2 -0
  41. data/examples/performance/snooze.rb +2 -0
  42. data/examples/performance/thread-vs-fiber/polyphony_server.rb +5 -3
  43. data/examples/performance/thread-vs-fiber/threaded_server.rb +1 -1
  44. data/examples/{io/httparty_multi.rb → performance/thread-vs-fiber/xx-httparty_multi.rb} +16 -13
  45. data/examples/{io/httparty_threaded.rb → performance/thread-vs-fiber/xx-httparty_threaded.rb} +2 -2
  46. data/examples/performance/thread.rb +27 -0
  47. data/examples/{core → performance}/thread_pool_perf.rb +0 -0
  48. data/ext/gyro/extconf.rb +1 -0
  49. data/lib/polyphony/extensions/core.rb +0 -5
  50. data/lib/polyphony/version.rb +1 -1
  51. data/polyphony.gemspec +3 -9
  52. metadata +59 -167
  53. data/bin/poly +0 -11
  54. data/examples/core/cancel.rb +0 -13
  55. data/examples/core/enumerator.rb +0 -15
  56. data/examples/core/error_bubbling.rb +0 -35
  57. data/examples/core/fiber_error.rb +0 -9
  58. data/examples/core/fiber_error_with_backtrace.rb +0 -73
  59. data/examples/core/move_on.rb +0 -11
  60. data/examples/core/move_on_twice.rb +0 -16
  61. data/examples/core/move_on_with_ensure.rb +0 -13
  62. data/examples/core/move_on_with_value.rb +0 -14
  63. data/examples/core/multiple_spin.rb +0 -18
  64. data/examples/core/nested_cancel.rb +0 -40
  65. data/examples/core/nested_multiple_spin.rb +0 -20
  66. data/examples/core/nested_spin.rb +0 -19
  67. data/examples/core/pingpong.rb +0 -21
  68. data/examples/core/resource.rb +0 -30
  69. data/examples/core/sleep_spin.rb +0 -21
  70. data/examples/core/snooze.rb +0 -32
  71. data/examples/core/spin_error.rb +0 -17
  72. data/examples/core/spin_uncaught_error.rb +0 -16
  73. data/examples/core/supervisor_with_cancel_scope.rb +0 -23
  74. data/examples/core/supervisor_with_error.rb +0 -24
  75. data/examples/core/supervisor_with_manual_move_on.rb +0 -23
  76. data/examples/core/suspend.rb +0 -13
  77. data/examples/core/thread.rb +0 -27
  78. data/examples/http/config.ru +0 -7
  79. data/examples/http/cuba.ru +0 -22
  80. data/examples/http/happy_eyeballs.rb +0 -37
  81. data/examples/http/http2_raw.rb +0 -135
  82. data/examples/http/http_client.rb +0 -28
  83. data/examples/http/http_get.rb +0 -33
  84. data/examples/http/http_parse_experiment.rb +0 -123
  85. data/examples/http/http_proxy.rb +0 -83
  86. data/examples/http/http_server.js +0 -24
  87. data/examples/http/http_server.rb +0 -28
  88. data/examples/http/http_server_forked.rb +0 -29
  89. data/examples/http/http_server_graceful.rb +0 -27
  90. data/examples/http/http_server_simple.rb +0 -11
  91. data/examples/http/http_server_throttled.rb +0 -15
  92. data/examples/http/http_ws_server.rb +0 -37
  93. data/examples/http/https_raw_client.rb +0 -12
  94. data/examples/http/https_server.rb +0 -22
  95. data/examples/http/https_wss_server.rb +0 -39
  96. data/examples/http/rack_server.rb +0 -12
  97. data/examples/http/rack_server_https.rb +0 -19
  98. data/examples/http/rack_server_https_forked.rb +0 -27
  99. data/examples/http/websocket_secure_server.rb +0 -27
  100. data/examples/http/websocket_server.rb +0 -24
  101. data/examples/http/ws_page.html +0 -34
  102. data/examples/http/wss_page.html +0 -34
  103. data/examples/io/cat.rb +0 -12
  104. data/examples/io/httparty.rb +0 -10
  105. data/examples/io/io_read.rb +0 -9
  106. data/lib/ev_ext.bundle +0 -0
  107. data/lib/polyphony/http.rb +0 -16
  108. data/lib/polyphony/http/client/agent.rb +0 -131
  109. data/lib/polyphony/http/client/http1.rb +0 -129
  110. data/lib/polyphony/http/client/http2.rb +0 -180
  111. data/lib/polyphony/http/client/response.rb +0 -32
  112. data/lib/polyphony/http/client/site_connection_manager.rb +0 -109
  113. data/lib/polyphony/http/server.rb +0 -49
  114. data/lib/polyphony/http/server/http1.rb +0 -268
  115. data/lib/polyphony/http/server/http2.rb +0 -78
  116. data/lib/polyphony/http/server/http2_stream.rb +0 -136
  117. data/lib/polyphony/http/server/rack.rb +0 -64
  118. data/lib/polyphony/http/server/request.rb +0 -118
  119. data/lib/polyphony/websocket.rb +0 -59
  120. data/test/test_http_server.rb +0 -313
@@ -1,16 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require 'bundler/setup'
4
- require 'polyphony'
5
-
6
- def foo
7
- spin do
8
- spin do
9
- raise 'This is an error'
10
- end
11
- end
12
- end
13
-
14
- foo
15
-
16
- suspend
@@ -1,23 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require 'bundler/setup'
4
- require 'polyphony'
5
-
6
- def my_sleep(t)
7
- puts "start: #{t}"
8
- r = sleep(t)
9
- puts "my_sleep result #{r.inspect}"
10
- puts "done: #{t}"
11
- end
12
-
13
- puts "#{Time.now} going to sleep..."
14
- move_on_after(0.5) do
15
- supervise do |s|
16
- puts 'supervise block'
17
- s.spin my_sleep(1)
18
- s.spin my_sleep(2)
19
- s.spin my_sleep(3)
20
- end
21
- puts 'supervisor done'
22
- end
23
- puts "#{Time.now} woke up"
@@ -1,24 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require 'bundler/setup'
4
- require 'polyphony'
5
-
6
- def my_sleep(t)
7
- sleep(t)
8
- raise 'foo'
9
- end
10
-
11
- spin do
12
- puts "#{Time.now} going to sleep..."
13
- supervise do |s|
14
- s.spin { my_sleep(1) }
15
- s.spin { my_sleep(2) }
16
- s.spin { my_sleep(3) }
17
- end
18
- # rescue StandardError => e
19
- # puts "exception from supervisor: #{e}"
20
- ensure
21
- puts "#{Time.now} woke up"
22
- end
23
-
24
- suspend
@@ -1,23 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require 'bundler/setup'
4
- require 'polyphony'
5
-
6
- def my_sleep(t)
7
- puts "start: #{t}"
8
- sleep(t)
9
- puts "done: #{t}"
10
- end
11
-
12
- puts "#{Time.now} going to sleep..."
13
- result = supervise do |s|
14
- spin do
15
- sleep(0.5)
16
- puts 'stopping supervisor...'
17
- s.stop!
18
- end
19
- s.spin { my_sleep(1) }
20
- s.spin { my_sleep(2) }
21
- s.spin { my_sleep(3) }
22
- end
23
- puts "#{Time.now} woke up with #{result.inspect}"
@@ -1,13 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require 'bundler/setup'
4
- require 'polyphony'
5
-
6
- spin do
7
- 1.times do
8
- puts Time.now
9
- sleep 1
10
- end
11
- end
12
-
13
- suspend
@@ -1,27 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require 'bundler/setup'
4
- require 'polyphony'
5
-
6
- def lengthy_op
7
- IO.orig_read(__FILE__)
8
- end
9
-
10
- X = 10000
11
-
12
- def blocking
13
- t0 = Time.now
14
- data = lengthy_op
15
- X.times { lengthy_op }
16
- puts "read blocking #{data.bytesize} bytes (#{Time.now - t0}s)"
17
- end
18
-
19
- def threaded
20
- t0 = Time.now
21
- data = Polyphony::Thread.spawn { lengthy_op }.await
22
- X.times { Polyphony::Thread.spawn { lengthy_op } }
23
- puts "read threaded #{data.bytesize} bytes (#{Time.now - t0}s)"
24
- end
25
-
26
- blocking
27
- threaded
@@ -1,7 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- run(proc do |env|
4
- ['200', { 'Content-Type' => 'text/html' }, [
5
- env.select { |k, _v| k =~ /^[A-Z]/ }.inspect
6
- ]]
7
- end)
@@ -1,22 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require 'cuba'
4
- require 'cuba/safe'
5
-
6
- Cuba.use Rack::Session::Cookie, secret: '__a_very_long_string__'
7
-
8
- Cuba.plugin Cuba::Safe
9
-
10
- Cuba.define do
11
- on get do
12
- on 'hello' do
13
- res.write 'Hello world!'
14
- end
15
-
16
- on root do
17
- res.redirect '/hello'
18
- end
19
- end
20
- end
21
-
22
- run Cuba
@@ -1,37 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- # idea taken from the example given in trio:
4
- # https://www.youtube.com/watch?v=oLkfnc_UMcE
5
-
6
- require 'bundler/setup'
7
- require 'polyphony/http'
8
-
9
- def try_connect(target, supervisor)
10
- puts "trying #{target[2]}"
11
- socket = Polyphony::Net.tcp_connect(target[2], 80)
12
- # connection successful
13
- supervisor.stop!([target[2], socket])
14
- rescue IOError, SystemCallError
15
- # ignore error
16
- end
17
-
18
- def happy_eyeballs(hostname, port, max_wait_time: 0.025)
19
- targets = Socket.getaddrinfo(hostname, port, :INET, :STREAM)
20
- t0 = Time.now
21
- cancel_after(5) do
22
- success = supervise do |supervisor|
23
- targets.each_with_index do |t, idx|
24
- sleep(max_wait_time) if idx > 0
25
- supervisor.spin { try_connect(t, supervisor) }
26
- end
27
- end
28
- if success
29
- puts format('success: %s (%.3fs)', success[0], Time.now - t0)
30
- else
31
- puts "timed out (#{Time.now - t0}s)"
32
- end
33
- end
34
- end
35
-
36
- # Let's try it out:
37
- happy_eyeballs('debian.org', 'https')
@@ -1,135 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require 'bundler/setup'
4
- require 'polyphony'
5
- require 'http/2'
6
-
7
- # Response = import '../../lib/polyphony/http/client/response'
8
-
9
- url = 'https://realiteq.net/?q=time'
10
- uri = URI(url)
11
- uri_key = { scheme: uri.scheme, host: uri.host, port: uri.port }
12
-
13
- ctx = {
14
- method: :GET,
15
- uri: uri,
16
- opts: {},
17
- retry: 0
18
- }
19
-
20
- SECURE_OPTS = { secure: true, alpn_protocols: ['h2', 'http/1.1'] }.freeze
21
- socket = Polyphony::Net.tcp_connect(uri_key[:host], uri_key[:port], SECURE_OPTS)
22
-
23
- puts 'connected'
24
-
25
- $client = HTTP2::Client.new
26
- $client.on(:frame) { |bytes| socket << bytes }
27
- $client.on(:frame_received) do |frame|
28
- puts "Received frame: #{frame.inspect}"
29
- end
30
- # $client.on(:frame_sent) do |frame|
31
- # puts "Sent frame: #{frame.inspect}"
32
- # end
33
-
34
- reader = spin do
35
- while (data = socket.readpartial(8192))
36
- $client << data
37
- snooze
38
- end
39
- end
40
-
41
- stream = $client.new_stream
42
-
43
- $headers = nil
44
- $done = nil
45
- @buffered_chunks = []
46
-
47
- @waiting_headers_fiber = nil
48
- @waiting_chunk_fiber = nil
49
- @waiting_done_fiber = nil
50
-
51
- # send request
52
- headers = {
53
- ':method' => ctx[:method].to_s,
54
- ':scheme' => ctx[:uri].scheme,
55
- ':authority' => [ctx[:uri].host, ctx[:uri].port].join(':'),
56
- ':path' => ctx[:uri].request_uri,
57
- 'User-Agent' => 'curl/7.54.0'
58
- }
59
- headers.merge!(ctx[:opts][:headers]) if ctx[:opts][:headers]
60
-
61
- if ctx[:opts][:payload]
62
- stream.headers(headers, end_stream: false)
63
- stream.data(ctx[:opts][:payload], end_stream: true)
64
- else
65
- stream.headers(headers, end_stream: true)
66
- end
67
-
68
- stream.on(:headers) { |headers|
69
- puts "got headers"
70
- # if @waiting_headers_fiber
71
- # @waiting_headers_fiber.transfer headers.to_h
72
- # else
73
- $headers = headers.to_h
74
- # end
75
- }
76
- stream.on(:data) { |chunk|
77
- puts "got data"
78
- # if @waiting_chunk_fiber
79
- # @waiting_chunk_fiber&.transfer c
80
- # else
81
- @buffered_chunks << chunk
82
- # end
83
- }
84
-
85
- def close
86
- puts "got close"
87
- $done = true
88
- end
89
-
90
- stream.on(:close) { close }
91
- # @waiting_done_fiber&.transfer
92
- # }
93
-
94
- stream.on(:active) { puts "* active" }
95
- stream.on(:half_close) { puts "* half_close" }
96
-
97
-
98
-
99
- # wait for response
100
- # unless $headers
101
- # @waiting_headers_fiber = Fiber.current
102
- # $headers = suspend
103
- # end
104
- # p $headers
105
- # response = Response.new(self, $headers[':status'].to_i, $headers)
106
- # p response
107
-
108
- puts "waiting for response"
109
- while !$done
110
- puts "waiting..."
111
- sleep 1
112
- end
113
- puts "done"
114
-
115
- # def body
116
- # @waiting_chunk_fiber = Fiber.current
117
- # body = +''
118
- # while !$done
119
- # chunk = suspend
120
- # body << chunk
121
- # end
122
- # body
123
- # rescue => e
124
- # p e
125
- # puts e.backtrace.join("\n")
126
- # end
127
- # end
128
-
129
- # adapter = StreamAdapter.new
130
- # resp = adapter.request(ctx)
131
- # puts "*" * 40
132
- # p resp
133
-
134
- # body = resp.body
135
- # p body
@@ -1,28 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require 'bundler/setup'
4
- require 'polyphony/http'
5
-
6
- Exception.__disable_sanitized_backtrace__ = true
7
-
8
- TIME_URI = 'https://ui.realiteq.net/'
9
-
10
- def get_server_time
11
- json = Polyphony::HTTP::Agent.get(TIME_URI, query: { q: :time }).json
12
- puts "*" * 40
13
- p json
14
- end
15
-
16
- X = 1
17
- puts "Making #{X} requests..."
18
- t0 = Time.now
19
- supervise do |s|
20
- X.times {
21
- s.spin {
22
- get_server_time
23
- }
24
- }
25
- end
26
- # get_server_time
27
- elapsed = Time.now - t0
28
- puts "count: #{X} elapsed: #{elapsed} rate: #{X / elapsed} reqs/s"
@@ -1,33 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require 'bundler/setup'
4
- require 'polyphony/http'
5
- require 'polyphony'
6
-
7
- Exception.__disable_sanitized_backtrace__ = true
8
-
9
- resp = Polyphony::HTTP::Agent.get('https://realiteq.net/?q=time')
10
- puts "*" * 40
11
- puts resp.body
12
-
13
- __END__
14
-
15
- X = 1
16
- Y = 1
17
- t0 = Time.now
18
- supervise { |s|
19
- X.times {
20
- s.spin {
21
- Y.times {
22
- resp = Polyphony::HTTP::Agent.get('http://about.gitlab.com/')
23
- puts "*" * 40
24
- p resp.headers
25
- puts "*" * 40
26
- puts resp.body
27
- # puts "body size: #{resp.body.bytesize}"
28
- }
29
- }
30
- }
31
- }
32
- elapsed = Time.now - t0
33
- puts "\nelapsed: #{elapsed} rate: #{(X * Y) / elapsed}"
@@ -1,123 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require 'bundler/setup'
4
- require 'polyphony'
5
-
6
- require 'http/parser'
7
- require 'fiber'
8
-
9
- i, o = IO.pipe
10
-
11
- class ParseLoop
12
- def initialize(conn)
13
- @parser = HTTP::Parser.new(self)
14
- @conn = conn
15
- @parse_fiber = Fiber.new do
16
- while (data = conn.readpartial(8192))
17
- @parser << data
18
- snooze
19
- end
20
- rescue StandardError => e
21
- conn.close
22
- e
23
- ensure
24
- @message_in_train = nil
25
- end
26
- @state = nil
27
- end
28
-
29
- def on_headers_complete(headers)
30
- @calling_fiber.transfer(headers)
31
- end
32
-
33
- def on_body(chunk)
34
- @calling_fiber.transfer(chunk) if @read_body
35
- end
36
-
37
- def on_message_begin
38
- @message_in_train = true
39
- end
40
-
41
- def on_message_complete
42
- @message_in_train = nil
43
- @calling_fiber.transfer nil
44
- end
45
-
46
- def parse_headers
47
- @calling_fiber = Fiber.current
48
- @parse_fiber.safe_transfer
49
- end
50
-
51
- def parse_body_chunk
52
- @calling_fiber = Fiber.current
53
- @read_body = true
54
- @parse_fiber.safe_transfer
55
- end
56
-
57
- def consume_request
58
- return unless @message_in_train
59
-
60
- @calling_fiber = Fiber.current
61
- @read_body = false
62
- @parse_fiber.safe_transfer while @message_in_train
63
- end
64
-
65
- def alive?
66
- @parse_fiber.alive?
67
- end
68
-
69
- def busy?
70
- @message_in_train
71
- end
72
- end
73
-
74
- def handle(parser)
75
- headers = parser.parse_headers
76
- return unless headers
77
-
78
- puts "headers: #{headers.inspect}"
79
- headers['Content-Length']
80
- # if content_length && (content_length.to_i < 1000)
81
- while (chunk = parser.parse_body_chunk)
82
- puts "chunk: #{chunk.inspect}"
83
- end
84
- # else
85
- # parser.consume_request
86
- # end
87
- puts 'end of request'
88
- rescue StandardError => e
89
- puts "error: #{e.inspect}"
90
- raise e
91
- end
92
-
93
- writer = spin do
94
- o << "POST / HTTP/1.1\r\nHost: example.com\r\nContent-Length: 6\r\n\r\n"
95
- o << 'Hello!'
96
-
97
- o << "POST / HTTP/1.1\r\nHost: example.com\r\n\r\n"
98
-
99
- # o << "POST / HTTP/1.1\r\nHost: example.com\r\nContent-Length: 8192\r\n\r\n"
100
- # o << ("Bye!" * 2048)
101
-
102
- o << "POST / HTTP/1.1\r\nHost: example.com\r\nContent-Length: 4\r\n\r\n"
103
- o << 'Bye!'
104
-
105
- begin
106
- (o << ('BLAH' * 100_000))
107
- rescue StandardError
108
- nil
109
- end
110
- o.close
111
- end
112
-
113
- begin
114
- parse_loop = ParseLoop.new(i)
115
- while parse_loop.alive?
116
- puts '*' * 40
117
- handle(parse_loop)
118
- end
119
- rescue StandardError => e
120
- writer.stop
121
- puts "#{e.class}: #{e.message}"
122
- puts e.backtrace
123
- end