polyphony 0.19 → 0.20
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.
- checksums.yaml +4 -4
 - data/.gitignore +1 -1
 - data/.rubocop.yml +87 -1
 - data/CHANGELOG.md +35 -0
 - data/Gemfile.lock +17 -6
 - data/README.md +200 -139
 - data/Rakefile +4 -4
 - data/TODO.md +35 -7
 - data/bin/poly +11 -0
 - data/docs/getting-started/getting-started.md +1 -1
 - data/docs/summary.md +3 -0
 - data/docs/technical-overview/exception-handling.md +94 -0
 - data/docs/technical-overview/fiber-scheduling.md +99 -0
 - data/examples/core/cancel.rb +8 -4
 - data/examples/core/channel_echo.rb +18 -17
 - data/examples/core/defer.rb +12 -0
 - data/examples/core/enumerator.rb +4 -4
 - data/examples/core/fiber_error.rb +9 -0
 - data/examples/core/fiber_error_with_backtrace.rb +73 -0
 - data/examples/core/fork.rb +6 -6
 - data/examples/core/genserver.rb +16 -8
 - data/examples/core/lock.rb +3 -3
 - data/examples/core/move_on.rb +4 -3
 - data/examples/core/move_on_twice.rb +5 -5
 - data/examples/core/move_on_with_ensure.rb +8 -11
 - data/examples/core/move_on_with_value.rb +14 -0
 - data/examples/core/{multiple_spawn.rb → multiple_spin.rb} +5 -5
 - data/examples/core/nested_cancel.rb +5 -5
 - data/examples/core/{nested_multiple_spawn.rb → nested_multiple_spin.rb} +6 -6
 - data/examples/core/nested_spin.rb +17 -0
 - data/examples/core/pingpong.rb +21 -0
 - data/examples/core/pulse.rb +4 -5
 - data/examples/core/resource.rb +6 -4
 - data/examples/core/resource_cancel.rb +6 -9
 - data/examples/core/resource_delegate.rb +3 -3
 - data/examples/core/sleep.rb +3 -3
 - data/examples/core/sleep_spin.rb +19 -0
 - data/examples/core/snooze.rb +32 -0
 - data/examples/core/spin.rb +14 -0
 - data/examples/core/{spawn_cancel.rb → spin_cancel.rb} +6 -7
 - data/examples/core/spin_error.rb +17 -0
 - data/examples/core/spin_error_backtrace.rb +30 -0
 - data/examples/core/spin_uncaught_error.rb +15 -0
 - data/examples/core/supervisor.rb +8 -8
 - data/examples/core/supervisor_with_cancel_scope.rb +7 -7
 - data/examples/core/supervisor_with_error.rb +8 -8
 - data/examples/core/supervisor_with_manual_move_on.rb +6 -7
 - data/examples/core/suspend.rb +13 -0
 - data/examples/core/thread.rb +1 -1
 - data/examples/core/thread_cancel.rb +9 -11
 - data/examples/core/thread_pool.rb +18 -14
 - data/examples/core/throttle.rb +7 -7
 - data/examples/core/timeout.rb +3 -3
 - data/examples/fs/read.rb +7 -9
 - data/examples/http/config.ru +7 -3
 - data/examples/http/cuba.ru +22 -0
 - data/examples/http/happy_eyeballs.rb +6 -4
 - data/examples/http/http_client.rb +1 -1
 - data/examples/http/http_get.rb +1 -1
 - data/examples/http/http_parse_experiment.rb +21 -16
 - data/examples/http/http_proxy.rb +28 -26
 - data/examples/http/http_server.rb +10 -10
 - data/examples/http/http_server_forked.rb +6 -5
 - data/examples/http/http_server_throttled.rb +3 -3
 - data/examples/http/http_ws_server.rb +11 -11
 - data/examples/http/https_raw_client.rb +1 -1
 - data/examples/http/https_server.rb +8 -8
 - data/examples/http/https_wss_server.rb +13 -11
 - data/examples/http/rack_server.rb +2 -2
 - data/examples/http/rack_server_https.rb +4 -4
 - data/examples/http/rack_server_https_forked.rb +5 -5
 - data/examples/http/websocket_secure_server.rb +6 -6
 - data/examples/http/websocket_server.rb +5 -5
 - data/examples/interfaces/pg_client.rb +4 -4
 - data/examples/interfaces/pg_pool.rb +13 -6
 - data/examples/interfaces/pg_transaction.rb +5 -4
 - data/examples/interfaces/redis_channels.rb +15 -11
 - data/examples/interfaces/redis_client.rb +2 -2
 - data/examples/interfaces/redis_pubsub.rb +2 -1
 - data/examples/interfaces/redis_pubsub_perf.rb +13 -9
 - data/examples/io/backticks.rb +11 -0
 - data/examples/io/cat.rb +4 -5
 - data/examples/io/echo_client.rb +9 -4
 - data/examples/io/echo_client_from_stdin.rb +20 -0
 - data/examples/io/echo_pipe.rb +7 -8
 - data/examples/io/echo_server.rb +8 -6
 - data/examples/io/echo_server_with_timeout.rb +13 -10
 - data/examples/io/echo_stdin.rb +3 -3
 - data/examples/io/httparty.rb +2 -2
 - data/examples/io/httparty_multi.rb +8 -4
 - data/examples/io/httparty_threaded.rb +6 -2
 - data/examples/io/io_read.rb +2 -2
 - data/examples/io/irb.rb +16 -4
 - data/examples/io/net-http.rb +3 -3
 - data/examples/io/open.rb +17 -0
 - data/examples/io/system.rb +3 -3
 - data/examples/io/tcpserver.rb +15 -0
 - data/examples/io/tcpsocket.rb +6 -5
 - data/examples/performance/multi_snooze.rb +29 -0
 - data/examples/performance/{perf_snooze.rb → snooze.rb} +7 -5
 - data/examples/performance/snooze_raw.rb +39 -0
 - data/ext/gyro/async.c +165 -0
 - data/ext/gyro/child.c +167 -0
 - data/ext/{ev → gyro}/extconf.rb +4 -3
 - data/ext/gyro/gyro.c +316 -0
 - data/ext/{ev/ev.h → gyro/gyro.h} +12 -7
 - data/ext/gyro/gyro_ext.c +23 -0
 - data/ext/{ev → gyro}/io.c +65 -57
 - data/ext/{ev → gyro}/libev.h +0 -0
 - data/ext/gyro/signal.c +117 -0
 - data/ext/{ev → gyro}/socket.c +61 -6
 - data/ext/gyro/timer.c +199 -0
 - data/ext/libev/Changes +35 -0
 - data/ext/libev/README +2 -1
 - data/ext/libev/ev.c +213 -151
 - data/ext/libev/ev.h +95 -88
 - data/ext/libev/ev_epoll.c +26 -15
 - data/ext/libev/ev_kqueue.c +11 -5
 - data/ext/libev/ev_linuxaio.c +642 -0
 - data/ext/libev/ev_poll.c +13 -8
 - data/ext/libev/ev_port.c +5 -2
 - data/ext/libev/ev_vars.h +14 -3
 - data/ext/libev/ev_wrap.h +16 -0
 - data/lib/ev_ext.bundle +0 -0
 - data/lib/polyphony.rb +46 -50
 - data/lib/polyphony/auto_run.rb +12 -0
 - data/lib/polyphony/core/cancel_scope.rb +11 -7
 - data/lib/polyphony/core/channel.rb +16 -9
 - data/lib/polyphony/core/coprocess.rb +101 -51
 - data/lib/polyphony/core/exceptions.rb +14 -12
 - data/lib/polyphony/core/resource_pool.rb +21 -8
 - data/lib/polyphony/core/supervisor.rb +10 -5
 - data/lib/polyphony/core/sync.rb +7 -6
 - data/lib/polyphony/core/thread.rb +4 -4
 - data/lib/polyphony/core/thread_pool.rb +4 -4
 - data/lib/polyphony/core/throttler.rb +6 -4
 - data/lib/polyphony/extensions/core.rb +253 -0
 - data/lib/polyphony/extensions/io.rb +28 -16
 - data/lib/polyphony/extensions/openssl.rb +2 -1
 - data/lib/polyphony/extensions/socket.rb +47 -52
 - data/lib/polyphony/http.rb +4 -3
 - data/lib/polyphony/http/agent.rb +68 -57
 - data/lib/polyphony/http/server.rb +5 -5
 - data/lib/polyphony/http/server/http1.rb +268 -0
 - data/lib/polyphony/http/server/http2.rb +62 -0
 - data/lib/polyphony/http/server/http2_stream.rb +104 -0
 - data/lib/polyphony/http/server/rack.rb +64 -0
 - data/lib/polyphony/http/server/request.rb +119 -0
 - data/lib/polyphony/net.rb +26 -15
 - data/lib/polyphony/postgres.rb +17 -13
 - data/lib/polyphony/redis.rb +16 -15
 - data/lib/polyphony/version.rb +1 -1
 - data/lib/polyphony/websocket.rb +11 -4
 - data/polyphony.gemspec +13 -9
 - data/test/eg.rb +27 -0
 - data/test/helper.rb +25 -0
 - data/test/run.rb +5 -0
 - data/test/test_async.rb +33 -0
 - data/test/test_coprocess.rb +239 -77
 - data/test/test_core.rb +95 -61
 - data/test/test_gyro.rb +148 -0
 - data/test/test_http_server.rb +313 -0
 - data/test/test_io.rb +79 -27
 - data/test/test_kernel.rb +22 -12
 - data/test/test_signal.rb +36 -0
 - data/test/test_timer.rb +24 -0
 - metadata +89 -33
 - data/examples/core/nested_async.rb +0 -17
 - data/examples/core/next_tick.rb +0 -12
 - data/examples/core/sleep_spawn.rb +0 -19
 - data/examples/core/spawn.rb +0 -14
 - data/examples/core/spawn_error.rb +0 -28
 - data/examples/performance/perf_multi_snooze.rb +0 -21
 - data/ext/ev/async.c +0 -168
 - data/ext/ev/child.c +0 -169
 - data/ext/ev/ev_ext.c +0 -23
 - data/ext/ev/ev_module.c +0 -242
 - data/ext/ev/signal.c +0 -119
 - data/ext/ev/timer.c +0 -197
 - data/lib/polyphony/core/fiber_pool.rb +0 -98
 - data/lib/polyphony/extensions/kernel.rb +0 -169
 - data/lib/polyphony/http/http1_adapter.rb +0 -254
 - data/lib/polyphony/http/http2_adapter.rb +0 -157
 - data/lib/polyphony/http/rack.rb +0 -25
 - data/lib/polyphony/http/request.rb +0 -66
 - data/test/test_ev.rb +0 -110
 
| 
         @@ -1,157 +0,0 @@ 
     | 
|
| 
       1 
     | 
    
         
            -
            # frozen_string_literal: true
         
     | 
| 
       2 
     | 
    
         
            -
             
     | 
| 
       3 
     | 
    
         
            -
            export_default :Protocol
         
     | 
| 
       4 
     | 
    
         
            -
             
     | 
| 
       5 
     | 
    
         
            -
            require 'http/2'
         
     | 
| 
       6 
     | 
    
         
            -
             
     | 
| 
       7 
     | 
    
         
            -
            Request = import('./request')
         
     | 
| 
       8 
     | 
    
         
            -
             
     | 
| 
       9 
     | 
    
         
            -
            class StreamWrapper
         
     | 
| 
       10 
     | 
    
         
            -
              def initialize(stream, parse_fiber)
         
     | 
| 
       11 
     | 
    
         
            -
                @stream = stream
         
     | 
| 
       12 
     | 
    
         
            -
                @parse_fiber = parse_fiber
         
     | 
| 
       13 
     | 
    
         
            -
                @parsing = true
         
     | 
| 
       14 
     | 
    
         
            -
             
     | 
| 
       15 
     | 
    
         
            -
                stream.on(:data) { |data| on_body(data) }
         
     | 
| 
       16 
     | 
    
         
            -
                stream.on(:half_close) { on_message_complete }
         
     | 
| 
       17 
     | 
    
         
            -
              end
         
     | 
| 
       18 
     | 
    
         
            -
             
     | 
| 
       19 
     | 
    
         
            -
              # Reads body chunk from connection
         
     | 
| 
       20 
     | 
    
         
            -
              def get_body_chunk
         
     | 
| 
       21 
     | 
    
         
            -
                @calling_fiber = Fiber.current
         
     | 
| 
       22 
     | 
    
         
            -
                @read_body = true
         
     | 
| 
       23 
     | 
    
         
            -
                @parse_fiber.safe_transfer
         
     | 
| 
       24 
     | 
    
         
            -
              end
         
     | 
| 
       25 
     | 
    
         
            -
             
     | 
| 
       26 
     | 
    
         
            -
              # Wait for request to finish
         
     | 
| 
       27 
     | 
    
         
            -
              def consume_request
         
     | 
| 
       28 
     | 
    
         
            -
                return unless @parsing
         
     | 
| 
       29 
     | 
    
         
            -
             
     | 
| 
       30 
     | 
    
         
            -
                @calling_fiber = Fiber.current
         
     | 
| 
       31 
     | 
    
         
            -
                @read_body = false
         
     | 
| 
       32 
     | 
    
         
            -
                @parse_fiber.safe_transfer while @parsing
         
     | 
| 
       33 
     | 
    
         
            -
              end
         
     | 
| 
       34 
     | 
    
         
            -
             
     | 
| 
       35 
     | 
    
         
            -
              def on_body(data)
         
     | 
| 
       36 
     | 
    
         
            -
                @calling_fiber.transfer(data) if @read_body
         
     | 
| 
       37 
     | 
    
         
            -
              end
         
     | 
| 
       38 
     | 
    
         
            -
             
     | 
| 
       39 
     | 
    
         
            -
              def on_message_complete
         
     | 
| 
       40 
     | 
    
         
            -
                @parsing = false
         
     | 
| 
       41 
     | 
    
         
            -
                @calling_fiber.transfer nil
         
     | 
| 
       42 
     | 
    
         
            -
              end
         
     | 
| 
       43 
     | 
    
         
            -
             
     | 
| 
       44 
     | 
    
         
            -
              # response API
         
     | 
| 
       45 
     | 
    
         
            -
              def respond(chunk, headers)
         
     | 
| 
       46 
     | 
    
         
            -
                consume_request if @parsing
         
     | 
| 
       47 
     | 
    
         
            -
             
     | 
| 
       48 
     | 
    
         
            -
                headers[':status'] ||= '200'
         
     | 
| 
       49 
     | 
    
         
            -
                @stream.headers(headers, end_stream: false)
         
     | 
| 
       50 
     | 
    
         
            -
                @stream.data(chunk, end_stream: true)
         
     | 
| 
       51 
     | 
    
         
            -
                @headers_sent = true
         
     | 
| 
       52 
     | 
    
         
            -
              end
         
     | 
| 
       53 
     | 
    
         
            -
             
     | 
| 
       54 
     | 
    
         
            -
              def send_headers(headers, empty_response = false)
         
     | 
| 
       55 
     | 
    
         
            -
                return if @headers_sent
         
     | 
| 
       56 
     | 
    
         
            -
             
     | 
| 
       57 
     | 
    
         
            -
                consume_request if @parsing
         
     | 
| 
       58 
     | 
    
         
            -
             
     | 
| 
       59 
     | 
    
         
            -
                headers[':status'] ||= (empty_response ? 204 : 200).to_s
         
     | 
| 
       60 
     | 
    
         
            -
                @stream.headers(headers, end_stream: false)
         
     | 
| 
       61 
     | 
    
         
            -
                @headers_sent = true
         
     | 
| 
       62 
     | 
    
         
            -
              end
         
     | 
| 
       63 
     | 
    
         
            -
             
     | 
| 
       64 
     | 
    
         
            -
              def send_body_chunk(chunk, done: false)
         
     | 
| 
       65 
     | 
    
         
            -
                send_headers({}, false) unless @headers_sent
         
     | 
| 
       66 
     | 
    
         
            -
                @stream.data(chunk, end_stream: done)
         
     | 
| 
       67 
     | 
    
         
            -
              end
         
     | 
| 
       68 
     | 
    
         
            -
              
         
     | 
| 
       69 
     | 
    
         
            -
              def finish
         
     | 
| 
       70 
     | 
    
         
            -
                consume_request if @parsing
         
     | 
| 
       71 
     | 
    
         
            -
             
     | 
| 
       72 
     | 
    
         
            -
                unless @headers_sent
         
     | 
| 
       73 
     | 
    
         
            -
                  headers[':status'] ||= '204'
         
     | 
| 
       74 
     | 
    
         
            -
                  @stream.headers(headers, end_stream: true)
         
     | 
| 
       75 
     | 
    
         
            -
                else
         
     | 
| 
       76 
     | 
    
         
            -
                  @stream.close
         
     | 
| 
       77 
     | 
    
         
            -
                end
         
     | 
| 
       78 
     | 
    
         
            -
              end
         
     | 
| 
       79 
     | 
    
         
            -
            end
         
     | 
| 
       80 
     | 
    
         
            -
             
     | 
| 
       81 
     | 
    
         
            -
            class Protocol
         
     | 
| 
       82 
     | 
    
         
            -
              def self.upgrade_each(socket, opts, headers, &block)
         
     | 
| 
       83 
     | 
    
         
            -
                adapter = new(socket, opts, headers)
         
     | 
| 
       84 
     | 
    
         
            -
                adapter.each(&block)
         
     | 
| 
       85 
     | 
    
         
            -
              end
         
     | 
| 
       86 
     | 
    
         
            -
             
     | 
| 
       87 
     | 
    
         
            -
              def initialize(conn, opts, upgrade_headers = nil)
         
     | 
| 
       88 
     | 
    
         
            -
                @conn = conn  
         
     | 
| 
       89 
     | 
    
         
            -
                @opts = opts
         
     | 
| 
       90 
     | 
    
         
            -
             
     | 
| 
       91 
     | 
    
         
            -
                @interface = ::HTTP2::Server.new
         
     | 
| 
       92 
     | 
    
         
            -
                @interface.on(:frame) { |bytes| conn << bytes }
         
     | 
| 
       93 
     | 
    
         
            -
                @interface.on(:stream) { |stream| start_stream(stream) }
         
     | 
| 
       94 
     | 
    
         
            -
                @parse_fiber = Fiber.new { parse_loop(upgrade_headers) }
         
     | 
| 
       95 
     | 
    
         
            -
              end
         
     | 
| 
       96 
     | 
    
         
            -
             
     | 
| 
       97 
     | 
    
         
            -
              def start_stream(stream)
         
     | 
| 
       98 
     | 
    
         
            -
                stream.on(:headers) do |headers|
         
     | 
| 
       99 
     | 
    
         
            -
                  @calling_fiber.transfer([stream, headers.to_h])
         
     | 
| 
       100 
     | 
    
         
            -
                end
         
     | 
| 
       101 
     | 
    
         
            -
              end
         
     | 
| 
       102 
     | 
    
         
            -
             
     | 
| 
       103 
     | 
    
         
            -
              def protocol
         
     | 
| 
       104 
     | 
    
         
            -
                'h2'
         
     | 
| 
       105 
     | 
    
         
            -
              end
         
     | 
| 
       106 
     | 
    
         
            -
             
     | 
| 
       107 
     | 
    
         
            -
              def parse_loop(upgrade_headers)
         
     | 
| 
       108 
     | 
    
         
            -
                upgrade(upgrade_headers) if upgrade_headers
         
     | 
| 
       109 
     | 
    
         
            -
                  
         
     | 
| 
       110 
     | 
    
         
            -
                while (data = @conn.readpartial(8192))
         
     | 
| 
       111 
     | 
    
         
            -
                  @interface << data
         
     | 
| 
       112 
     | 
    
         
            -
                  snooze
         
     | 
| 
       113 
     | 
    
         
            -
                end
         
     | 
| 
       114 
     | 
    
         
            -
                @calling_fiber.transfer nil
         
     | 
| 
       115 
     | 
    
         
            -
              rescue SystemCallError, IOError
         
     | 
| 
       116 
     | 
    
         
            -
                # ignore
         
     | 
| 
       117 
     | 
    
         
            -
                @calling_fiber.transfer nil
         
     | 
| 
       118 
     | 
    
         
            -
              rescue => error
         
     | 
| 
       119 
     | 
    
         
            -
                # an error return value will be raised by the receiving fiber
         
     | 
| 
       120 
     | 
    
         
            -
                @calling_fiber.transfer error
         
     | 
| 
       121 
     | 
    
         
            -
              end
         
     | 
| 
       122 
     | 
    
         
            -
             
     | 
| 
       123 
     | 
    
         
            -
              # request API
         
     | 
| 
       124 
     | 
    
         
            -
              
         
     | 
| 
       125 
     | 
    
         
            -
              UPGRADE_MESSAGE = <<~HTTP.gsub("\n", "\r\n")
         
     | 
| 
       126 
     | 
    
         
            -
              HTTP/1.1 101 Switching Protocols
         
     | 
| 
       127 
     | 
    
         
            -
              Connection: Upgrade
         
     | 
| 
       128 
     | 
    
         
            -
              Upgrade: h2c
         
     | 
| 
       129 
     | 
    
         
            -
             
     | 
| 
       130 
     | 
    
         
            -
              HTTP
         
     | 
| 
       131 
     | 
    
         
            -
             
     | 
| 
       132 
     | 
    
         
            -
            def upgrade(headers)
         
     | 
| 
       133 
     | 
    
         
            -
                settings = headers['HTTP2-Settings']
         
     | 
| 
       134 
     | 
    
         
            -
                @conn << UPGRADE_MESSAGE
         
     | 
| 
       135 
     | 
    
         
            -
                @interface.upgrade(settings, headers, '')
         
     | 
| 
       136 
     | 
    
         
            -
              end
         
     | 
| 
       137 
     | 
    
         
            -
             
     | 
| 
       138 
     | 
    
         
            -
              # Iterates over incoming requests
         
     | 
| 
       139 
     | 
    
         
            -
              def each(&block)
         
     | 
| 
       140 
     | 
    
         
            -
                can_upgrade = true
         
     | 
| 
       141 
     | 
    
         
            -
                while @parse_fiber.alive?
         
     | 
| 
       142 
     | 
    
         
            -
                  stream, headers = get_headers
         
     | 
| 
       143 
     | 
    
         
            -
                  break unless stream
         
     | 
| 
       144 
     | 
    
         
            -
                  wrapper = StreamWrapper.new(stream, @parse_fiber)
         
     | 
| 
       145 
     | 
    
         
            -
                  request = Request.new(headers, wrapper)
         
     | 
| 
       146 
     | 
    
         
            -
                  Fiber.new { block.(request) }.resume
         
     | 
| 
       147 
     | 
    
         
            -
                end
         
     | 
| 
       148 
     | 
    
         
            -
              ensure
         
     | 
| 
       149 
     | 
    
         
            -
                @conn.close rescue nil
         
     | 
| 
       150 
     | 
    
         
            -
              end
         
     | 
| 
       151 
     | 
    
         
            -
             
     | 
| 
       152 
     | 
    
         
            -
              # Reads headers from connection
         
     | 
| 
       153 
     | 
    
         
            -
              def get_headers
         
     | 
| 
       154 
     | 
    
         
            -
                @calling_fiber = Fiber.current
         
     | 
| 
       155 
     | 
    
         
            -
                @parse_fiber.safe_transfer
         
     | 
| 
       156 
     | 
    
         
            -
              end
         
     | 
| 
       157 
     | 
    
         
            -
            end
         
     | 
    
        data/lib/polyphony/http/rack.rb
    DELETED
    
    | 
         @@ -1,25 +0,0 @@ 
     | 
|
| 
       1 
     | 
    
         
            -
            # frozen_string_literal: true
         
     | 
| 
       2 
     | 
    
         
            -
             
     | 
| 
       3 
     | 
    
         
            -
            export :load
         
     | 
| 
       4 
     | 
    
         
            -
             
     | 
| 
       5 
     | 
    
         
            -
            def run(app)
         
     | 
| 
       6 
     | 
    
         
            -
              ->(req) {
         
     | 
| 
       7 
     | 
    
         
            -
                response = app.(env(req))
         
     | 
| 
       8 
     | 
    
         
            -
                respond(req, response)
         
     | 
| 
       9 
     | 
    
         
            -
              }
         
     | 
| 
       10 
     | 
    
         
            -
            end
         
     | 
| 
       11 
     | 
    
         
            -
             
     | 
| 
       12 
     | 
    
         
            -
            def load(path)
         
     | 
| 
       13 
     | 
    
         
            -
              src = IO.read(path)
         
     | 
| 
       14 
     | 
    
         
            -
              instance_eval(src)
         
     | 
| 
       15 
     | 
    
         
            -
            end
         
     | 
| 
       16 
     | 
    
         
            -
             
     | 
| 
       17 
     | 
    
         
            -
            def env(request)
         
     | 
| 
       18 
     | 
    
         
            -
              { }
         
     | 
| 
       19 
     | 
    
         
            -
            end
         
     | 
| 
       20 
     | 
    
         
            -
             
     | 
| 
       21 
     | 
    
         
            -
            def respond(request, (status_code, headers, body))
         
     | 
| 
       22 
     | 
    
         
            -
              headers[':status'] = status_code.to_s
         
     | 
| 
       23 
     | 
    
         
            -
              body = body.first
         
     | 
| 
       24 
     | 
    
         
            -
              request.respond(body, headers)
         
     | 
| 
       25 
     | 
    
         
            -
            end
         
     | 
| 
         @@ -1,66 +0,0 @@ 
     | 
|
| 
       1 
     | 
    
         
            -
            # frozen_string_literal: true
         
     | 
| 
       2 
     | 
    
         
            -
             
     | 
| 
       3 
     | 
    
         
            -
            export_default :Request
         
     | 
| 
       4 
     | 
    
         
            -
             
     | 
| 
       5 
     | 
    
         
            -
            require 'uri'
         
     | 
| 
       6 
     | 
    
         
            -
             
     | 
| 
       7 
     | 
    
         
            -
            class Request
         
     | 
| 
       8 
     | 
    
         
            -
              attr_reader :headers, :adapter
         
     | 
| 
       9 
     | 
    
         
            -
             
     | 
| 
       10 
     | 
    
         
            -
              def initialize(headers, adapter)
         
     | 
| 
       11 
     | 
    
         
            -
                @headers  = headers
         
     | 
| 
       12 
     | 
    
         
            -
                @adapter  = adapter
         
     | 
| 
       13 
     | 
    
         
            -
              end
         
     | 
| 
       14 
     | 
    
         
            -
             
     | 
| 
       15 
     | 
    
         
            -
              def protocol
         
     | 
| 
       16 
     | 
    
         
            -
                @adapter.protocol
         
     | 
| 
       17 
     | 
    
         
            -
              end
         
     | 
| 
       18 
     | 
    
         
            -
             
     | 
| 
       19 
     | 
    
         
            -
              def method
         
     | 
| 
       20 
     | 
    
         
            -
                @method ||= @headers[':method']
         
     | 
| 
       21 
     | 
    
         
            -
              end
         
     | 
| 
       22 
     | 
    
         
            -
             
     | 
| 
       23 
     | 
    
         
            -
              def scheme
         
     | 
| 
       24 
     | 
    
         
            -
                @scheme ||= @headers[':scheme']
         
     | 
| 
       25 
     | 
    
         
            -
              end
         
     | 
| 
       26 
     | 
    
         
            -
             
     | 
| 
       27 
     | 
    
         
            -
              def uri
         
     | 
| 
       28 
     | 
    
         
            -
                @uri ||= URI.parse(@headers[':path'] || '')
         
     | 
| 
       29 
     | 
    
         
            -
              end
         
     | 
| 
       30 
     | 
    
         
            -
             
     | 
| 
       31 
     | 
    
         
            -
              def path
         
     | 
| 
       32 
     | 
    
         
            -
                @path ||= uri.path
         
     | 
| 
       33 
     | 
    
         
            -
              end
         
     | 
| 
       34 
     | 
    
         
            -
             
     | 
| 
       35 
     | 
    
         
            -
              def query
         
     | 
| 
       36 
     | 
    
         
            -
                @uri ||= URI.parse(@headers[':path'] || '')
         
     | 
| 
       37 
     | 
    
         
            -
                return @query if @query
         
     | 
| 
       38 
     | 
    
         
            -
              
         
     | 
| 
       39 
     | 
    
         
            -
                if (q = uri.query)
         
     | 
| 
       40 
     | 
    
         
            -
                  @query = q.split('&').each_with_object({}) do |kv, h|
         
     | 
| 
       41 
     | 
    
         
            -
                    k, v = kv.split('=')
         
     | 
| 
       42 
     | 
    
         
            -
                    h[k.to_sym] = URI.decode_www_form_component(v)
         
     | 
| 
       43 
     | 
    
         
            -
                  end
         
     | 
| 
       44 
     | 
    
         
            -
                else
         
     | 
| 
       45 
     | 
    
         
            -
                  @query = {}
         
     | 
| 
       46 
     | 
    
         
            -
                end
         
     | 
| 
       47 
     | 
    
         
            -
              end
         
     | 
| 
       48 
     | 
    
         
            -
             
     | 
| 
       49 
     | 
    
         
            -
              EMPTY_HASH = {}
         
     | 
| 
       50 
     | 
    
         
            -
             
     | 
| 
       51 
     | 
    
         
            -
              def respond(chunk, headers = EMPTY_HASH)
         
     | 
| 
       52 
     | 
    
         
            -
                @adapter.respond(chunk, headers)
         
     | 
| 
       53 
     | 
    
         
            -
              end
         
     | 
| 
       54 
     | 
    
         
            -
             
     | 
| 
       55 
     | 
    
         
            -
              def send_headers(headers = EMPTY_HASH, empty_response = false)
         
     | 
| 
       56 
     | 
    
         
            -
                @adapter.send_headers(headers, empty_response)
         
     | 
| 
       57 
     | 
    
         
            -
              end
         
     | 
| 
       58 
     | 
    
         
            -
             
     | 
| 
       59 
     | 
    
         
            -
              def send_body_chunk(body, done: false)
         
     | 
| 
       60 
     | 
    
         
            -
                @adapter.send_body_chunk(body, done: done)
         
     | 
| 
       61 
     | 
    
         
            -
              end
         
     | 
| 
       62 
     | 
    
         
            -
             
     | 
| 
       63 
     | 
    
         
            -
              def finish
         
     | 
| 
       64 
     | 
    
         
            -
                @adapter.finish
         
     | 
| 
       65 
     | 
    
         
            -
              end
         
     | 
| 
       66 
     | 
    
         
            -
            end
         
     | 
    
        data/test/test_ev.rb
    DELETED
    
    | 
         @@ -1,110 +0,0 @@ 
     | 
|
| 
       1 
     | 
    
         
            -
            require 'minitest/autorun'
         
     | 
| 
       2 
     | 
    
         
            -
            require 'bundler/setup'
         
     | 
| 
       3 
     | 
    
         
            -
            require 'polyphony'
         
     | 
| 
       4 
     | 
    
         
            -
             
     | 
| 
       5 
     | 
    
         
            -
            class EVRunTest < Minitest::Test
         
     | 
| 
       6 
     | 
    
         
            -
              def setup
         
     | 
| 
       7 
     | 
    
         
            -
                EV.rerun
         
     | 
| 
       8 
     | 
    
         
            -
              end
         
     | 
| 
       9 
     | 
    
         
            -
             
     | 
| 
       10 
     | 
    
         
            -
              def test_that_run_loop_returns_immediately_if_no_watchers
         
     | 
| 
       11 
     | 
    
         
            -
                t0 = Time.now
         
     | 
| 
       12 
     | 
    
         
            -
                suspend
         
     | 
| 
       13 
     | 
    
         
            -
                t1 = Time.now
         
     | 
| 
       14 
     | 
    
         
            -
                assert (t1 - t0) < 0.001
         
     | 
| 
       15 
     | 
    
         
            -
              end
         
     | 
| 
       16 
     | 
    
         
            -
            end
         
     | 
| 
       17 
     | 
    
         
            -
             
     | 
| 
       18 
     | 
    
         
            -
            class EVTimerTest < MiniTest::Test
         
     | 
| 
       19 
     | 
    
         
            -
              def setup
         
     | 
| 
       20 
     | 
    
         
            -
                EV.rerun
         
     | 
| 
       21 
     | 
    
         
            -
              end
         
     | 
| 
       22 
     | 
    
         
            -
             
     | 
| 
       23 
     | 
    
         
            -
              def test_that_one_shot_timer_works
         
     | 
| 
       24 
     | 
    
         
            -
                count = 0
         
     | 
| 
       25 
     | 
    
         
            -
                t = EV::Timer.new(0.01, 0)
         
     | 
| 
       26 
     | 
    
         
            -
                t.start { count += 1}
         
     | 
| 
       27 
     | 
    
         
            -
                suspend
         
     | 
| 
       28 
     | 
    
         
            -
                assert_equal(1, count)
         
     | 
| 
       29 
     | 
    
         
            -
              end
         
     | 
| 
       30 
     | 
    
         
            -
             
     | 
| 
       31 
     | 
    
         
            -
              def test_that_repeating_timer_works
         
     | 
| 
       32 
     | 
    
         
            -
                count = 0
         
     | 
| 
       33 
     | 
    
         
            -
                t = EV::Timer.new(0.001, 0.001)
         
     | 
| 
       34 
     | 
    
         
            -
                t.start { count += 1; t.stop if count >= 3}
         
     | 
| 
       35 
     | 
    
         
            -
                suspend
         
     | 
| 
       36 
     | 
    
         
            -
                assert_equal(3, count)
         
     | 
| 
       37 
     | 
    
         
            -
              end
         
     | 
| 
       38 
     | 
    
         
            -
            end
         
     | 
| 
       39 
     | 
    
         
            -
             
     | 
| 
       40 
     | 
    
         
            -
            class EVIOTest < MiniTest::Test
         
     | 
| 
       41 
     | 
    
         
            -
              def setup
         
     | 
| 
       42 
     | 
    
         
            -
                EV.rerun
         
     | 
| 
       43 
     | 
    
         
            -
              end
         
     | 
| 
       44 
     | 
    
         
            -
             
     | 
| 
       45 
     | 
    
         
            -
              def test_that_reading_works
         
     | 
| 
       46 
     | 
    
         
            -
                i, o = IO.pipe
         
     | 
| 
       47 
     | 
    
         
            -
                data = +''
         
     | 
| 
       48 
     | 
    
         
            -
                w = EV::IO.new(i, :r)
         
     | 
| 
       49 
     | 
    
         
            -
                w.start do
         
     | 
| 
       50 
     | 
    
         
            -
                  i.read_nonblock(8192, data)
         
     | 
| 
       51 
     | 
    
         
            -
                  w.stop unless data.empty?
         
     | 
| 
       52 
     | 
    
         
            -
                end
         
     | 
| 
       53 
     | 
    
         
            -
                EV::Timer.new(0, 0).start { o << 'hello' }
         
     | 
| 
       54 
     | 
    
         
            -
                suspend
         
     | 
| 
       55 
     | 
    
         
            -
                assert_equal('hello', data)
         
     | 
| 
       56 
     | 
    
         
            -
              end
         
     | 
| 
       57 
     | 
    
         
            -
            end
         
     | 
| 
       58 
     | 
    
         
            -
             
     | 
| 
       59 
     | 
    
         
            -
            class EVSignalTest < MiniTest::Test
         
     | 
| 
       60 
     | 
    
         
            -
              def setup
         
     | 
| 
       61 
     | 
    
         
            -
                EV.rerun
         
     | 
| 
       62 
     | 
    
         
            -
                EV.restart
         
     | 
| 
       63 
     | 
    
         
            -
              end
         
     | 
| 
       64 
     | 
    
         
            -
             
     | 
| 
       65 
     | 
    
         
            -
              def test_that_signal_watcher_receives_signal
         
     | 
| 
       66 
     | 
    
         
            -
                sig = Signal.list['USR1']
         
     | 
| 
       67 
     | 
    
         
            -
                count = 0
         
     | 
| 
       68 
     | 
    
         
            -
                w = EV::Signal.new(sig) { count += 1; w.stop }
         
     | 
| 
       69 
     | 
    
         
            -
                Thread.new { sync_sleep 0.001; Process.kill(:USR1, Process.pid) }
         
     | 
| 
       70 
     | 
    
         
            -
                suspend
         
     | 
| 
       71 
     | 
    
         
            -
                assert_equal(1, count)
         
     | 
| 
       72 
     | 
    
         
            -
              end
         
     | 
| 
       73 
     | 
    
         
            -
             
     | 
| 
       74 
     | 
    
         
            -
              def test_that_signal_watcher_receives_signal
         
     | 
| 
       75 
     | 
    
         
            -
                count = 0
         
     | 
| 
       76 
     | 
    
         
            -
                w = Polyphony.trap(:usr1, true) { count += 1; w.stop }
         
     | 
| 
       77 
     | 
    
         
            -
                assert_kind_of(EV::Signal, w)
         
     | 
| 
       78 
     | 
    
         
            -
                Thread.new { sync_sleep 0.001; Process.kill(:USR1, Process.pid) }
         
     | 
| 
       79 
     | 
    
         
            -
                suspend
         
     | 
| 
       80 
     | 
    
         
            -
                assert_equal(1, count)
         
     | 
| 
       81 
     | 
    
         
            -
              end
         
     | 
| 
       82 
     | 
    
         
            -
            end
         
     | 
| 
       83 
     | 
    
         
            -
             
     | 
| 
       84 
     | 
    
         
            -
            class EVAsyncTest < MiniTest::Test
         
     | 
| 
       85 
     | 
    
         
            -
              def setup
         
     | 
| 
       86 
     | 
    
         
            -
                EV.rerun
         
     | 
| 
       87 
     | 
    
         
            -
              end
         
     | 
| 
       88 
     | 
    
         
            -
             
     | 
| 
       89 
     | 
    
         
            -
              def test_that_async_watcher_receives_signal_across_threads
         
     | 
| 
       90 
     | 
    
         
            -
                count = 0
         
     | 
| 
       91 
     | 
    
         
            -
                a = EV::Async.new { count += 1; a.stop }
         
     | 
| 
       92 
     | 
    
         
            -
                Thread.new { sync_sleep 0.001; a.signal! }
         
     | 
| 
       93 
     | 
    
         
            -
                suspend
         
     | 
| 
       94 
     | 
    
         
            -
                assert_equal(1, count)
         
     | 
| 
       95 
     | 
    
         
            -
              end
         
     | 
| 
       96 
     | 
    
         
            -
             
     | 
| 
       97 
     | 
    
         
            -
              def test_that_async_watcher_coalesces_signals
         
     | 
| 
       98 
     | 
    
         
            -
                count = 0
         
     | 
| 
       99 
     | 
    
         
            -
                a = EV::Async.new do
         
     | 
| 
       100 
     | 
    
         
            -
                  count += 1
         
     | 
| 
       101 
     | 
    
         
            -
                  EV::Timer.new(0.01, 0).start { a.stop }
         
     | 
| 
       102 
     | 
    
         
            -
                end
         
     | 
| 
       103 
     | 
    
         
            -
                Thread.new do
         
     | 
| 
       104 
     | 
    
         
            -
                  sync_sleep 0.001
         
     | 
| 
       105 
     | 
    
         
            -
                  3.times { a.signal! }
         
     | 
| 
       106 
     | 
    
         
            -
                end
         
     | 
| 
       107 
     | 
    
         
            -
                suspend
         
     | 
| 
       108 
     | 
    
         
            -
                assert_equal(1, count)
         
     | 
| 
       109 
     | 
    
         
            -
              end
         
     | 
| 
       110 
     | 
    
         
            -
            end
         
     |