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
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 42975a9e638525d2264fbddea88ee0756fb7e7dbc5c0585c033b71a06a27711c
4
- data.tar.gz: 2c233b91c02d60e1dc40fbacb1dbade17c591a9ddede854e71dc7b2a840dcfd0
3
+ metadata.gz: 8a8da629de739b6091367c7220fd4a69dd83d7c78eb6d8c55c67385c8ca3edb2
4
+ data.tar.gz: 351f78d8b9635b6bc2c9838d652781a66009554287cfb5486c9fe0a0748ed6d6
5
5
  SHA512:
6
- metadata.gz: 339373f341a10fa68bec7d39588407519c12e17f9b02f774b9179af9b682512c156aa254cac116d4f60d1528e4dae21cfe220e71bf998787c0f1b55c244ef959
7
- data.tar.gz: 429a5960bbc3a38d23282ab1a8339b1ae556832fd098e34ae1a63fca36f4bc9f15f8996a715c70ac3363e01ea1858c2cf9de6b9296e90cf7f6a6c8a79f42c48c
6
+ metadata.gz: 768ed2703dd01653e5c71c2d17799b0c42fd9eb03f382dd3e4d3e4a337f7055d7a68643f479160febd3aa9412a9b66ccf0adf79f1608882ef0d61b625c8f7ed2
7
+ data.tar.gz: eab163c7ce680640def7fe6971359969202e6cb53238e8006c479e158c9b488bf73a2e575008a94cee1320fcf6899276da85df33d2fb00f97fa8133ad8fc3f06
@@ -1,3 +1,10 @@
1
+ 0.24 2020-01-08
2
+ ---------------
3
+
4
+ * Extract HTTP code into separate polyphony-http gem
5
+ * Cull core, io examples
6
+ * Remove `SIGINT` handler
7
+
1
8
  0.23 2020-01-07
2
9
  ---------------
3
10
 
@@ -1,11 +1,8 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- polyphony (0.23)
5
- http-2 (= 0.10.0)
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.34)
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
- # HTTP Client Agent
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.25 Full Rack adapter implementation
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.26 Working Sinatra application
13
+ ## 0.27 Working Sinatra application
60
14
 
61
15
  - app with database access (postgresql)
62
16
  - benchmarks!
63
17
 
64
- ## 0.27 Support for multi-threading
18
+ ## 0.28 Support for multi-threading
65
19
 
66
20
  - Separate event loop for each thread
67
21
 
68
- ## 0.28 Testing
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
 
@@ -1,8 +1,8 @@
1
1
  # Polyphony - Easy Concurrency for Ruby
2
2
 
3
- > Polyphony \| pəˈlɪf\(ə\)ni \| _Music_ - the style of simultaneously combining a number of parts, each forming an individual melody and harmonizing with each other.
4
-
5
- ## What is Polyphony
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
- If there's some blocking behavior you'd like to see handled by Polyphony, please let us know by [creating an issue](https://github.com/digital-fabric/polyphony/issues). Our aim is for Polyphony to be a comprehensive solution for writing concurrent Ruby programs.
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.
@@ -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, 42)
75
+ map_server.put!(:foo, :baz)
76
76
 
77
77
  puts 'getting value from map server'
78
78
  v = map_server.get(:foo)
@@ -13,6 +13,8 @@ pid = Polyphony.fork do
13
13
  sleep 1
14
14
  puts 'child woke up 1'
15
15
  end
16
+
17
+ suspend
16
18
  end
17
19
 
18
20
  puts "got child pid #{pid}"
@@ -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,8 @@ require 'polyphony'
5
5
 
6
6
  move_on_after(3) do
7
7
  puts 'Start...'
8
- pulser = pulse(1)
9
- puts Time.now while pulser.await
8
+ every(1) do
9
+ puts Time.now
10
+ end
10
11
  end
11
12
  puts 'done!'
@@ -5,7 +5,7 @@ require 'polyphony'
5
5
 
6
6
  resource_count = 0
7
7
  Pool = Polyphony::ResourcePool.new(limit: 3) do
8
- :"resource#{resource_count += 1}"
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} <"
@@ -8,8 +8,8 @@ def error(t)
8
8
  end
9
9
 
10
10
  def deferred_error(t)
11
- snooze
12
- de2(t)
11
+ puts "deferred_error"
12
+ defer { de2(t) }
13
13
  end
14
14
 
15
15
  def de2(t)
@@ -28,3 +28,6 @@ spin do
28
28
  end.await
29
29
  end.await
30
30
  end.await
31
+
32
+ suspend
33
+ suspend
@@ -2,7 +2,6 @@
2
2
 
3
3
  require 'bundler/setup'
4
4
  require 'polyphony'
5
- require 'polyphony/extensions/backtrace'
6
5
 
7
6
  socket = Polyphony::Net.tcp_connect('127.0.0.1', 1234)
8
7
 
@@ -2,7 +2,6 @@
2
2
 
3
3
  require 'bundler/setup'
4
4
  require 'polyphony'
5
- require 'polyphony/extensions/backtrace'
6
5
 
7
6
  socket = Polyphony::Net.tcp_connect('127.0.0.1', 1234)
8
7
 
@@ -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
@@ -2,7 +2,6 @@
2
2
 
3
3
  require 'bundler/setup'
4
4
  require 'polyphony'
5
- require 'irb'
6
5
 
7
6
  stdin = IO.open(STDIN.to_i)
8
7
 
File without changes
@@ -2,7 +2,6 @@
2
2
 
3
3
  require 'bundler/setup'
4
4
  require 'polyphony'
5
- require 'polyphony/extensions/backtrace'
6
5
 
7
6
  socket = TCPSocket.new('google.com', 80)
8
7
 
@@ -24,6 +24,7 @@ def calculate_coprocess_memory_cost(count)
24
24
  GC.disable
25
25
  rss0 = mem_usage
26
26
  count.times { spin { :foo } }
27
+ snooze
27
28
  rss1 = mem_usage
28
29
  GC.start
29
30
  cost = (rss1 - rss0).to_f / count
@@ -20,6 +20,8 @@ def bm(fibers, iterations)
20
20
  puts "#{[fibers, iterations].inspect} count: #{count} #{count / dt.to_f}/s"
21
21
  end
22
22
 
23
+ GC.disable
24
+
23
25
  bm(1, 1_000_000)
24
26
  bm(10, 100_000)
25
27
  bm(100, 10_000)
@@ -5,6 +5,8 @@ require 'polyphony'
5
5
 
6
6
  X = 1_000_000
7
7
 
8
+ GC.disable
9
+
8
10
  STDOUT << 'Fiber.yield: '
9
11
  f = Fiber.new do
10
12
  loop { Fiber.yield }
@@ -18,7 +18,7 @@ class Http::Parser
18
18
  end
19
19
  end
20
20
 
21
- async def handle_client(socket)
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
- coproc handle_client(client)
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