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
 
| 
         @@ -7,6 +7,6 @@ app_path = ARGV.first || File.expand_path('./config.ru', __dir__) 
     | 
|
| 
       7 
7 
     | 
    
         
             
            app = Polyphony::HTTP::Rack.load(app_path)
         
     | 
| 
       8 
8 
     | 
    
         
             
            opts = { reuse_addr: true, dont_linger: true }
         
     | 
| 
       9 
9 
     | 
    
         | 
| 
       10 
     | 
    
         
            -
            puts  
     | 
| 
      
 10 
     | 
    
         
            +
            puts 'listening on port 1234'
         
     | 
| 
       11 
11 
     | 
    
         
             
            puts "pid: #{Process.pid}"
         
     | 
| 
       12 
     | 
    
         
            -
            Polyphony::HTTP::Server.serve('0.0.0.0', 1234, opts, &app)
         
     | 
| 
      
 12 
     | 
    
         
            +
            Polyphony::HTTP::Server.serve('0.0.0.0', 1234, opts, &app)
         
     | 
| 
         @@ -9,11 +9,11 @@ app = Polyphony::HTTP::Rack.load(app_path) 
     | 
|
| 
       9 
9 
     | 
    
         | 
| 
       10 
10 
     | 
    
         
             
            authority = Localhost::Authority.fetch
         
     | 
| 
       11 
11 
     | 
    
         
             
            opts = {
         
     | 
| 
       12 
     | 
    
         
            -
              reuse_addr: 
     | 
| 
       13 
     | 
    
         
            -
              dont_linger: 
     | 
| 
      
 12 
     | 
    
         
            +
              reuse_addr:     true,
         
     | 
| 
      
 13 
     | 
    
         
            +
              dont_linger:    true,
         
     | 
| 
       14 
14 
     | 
    
         
             
              secure_context: authority.server_context
         
     | 
| 
       15 
15 
     | 
    
         
             
            }
         
     | 
| 
       16 
16 
     | 
    
         | 
| 
       17 
     | 
    
         
            -
            puts  
     | 
| 
      
 17 
     | 
    
         
            +
            puts 'listening on port 1234'
         
     | 
| 
       18 
18 
     | 
    
         
             
            puts "pid: #{Process.pid}"
         
     | 
| 
       19 
     | 
    
         
            -
            Polyphony::HTTP::Server.serve('0.0.0.0', 1234, opts, &app)
         
     | 
| 
      
 19 
     | 
    
         
            +
            Polyphony::HTTP::Server.serve('0.0.0.0', 1234, opts, &app)
         
     | 
| 
         @@ -9,19 +9,19 @@ app = Polyphony::HTTP::Rack.load(app_path) 
     | 
|
| 
       9 
9 
     | 
    
         | 
| 
       10 
10 
     | 
    
         
             
            authority = Localhost::Authority.fetch
         
     | 
| 
       11 
11 
     | 
    
         
             
            opts = {
         
     | 
| 
       12 
     | 
    
         
            -
              reuse_addr: 
     | 
| 
       13 
     | 
    
         
            -
              dont_linger: 
     | 
| 
      
 12 
     | 
    
         
            +
              reuse_addr:     true,
         
     | 
| 
      
 13 
     | 
    
         
            +
              dont_linger:    true,
         
     | 
| 
       14 
14 
     | 
    
         
             
              secure_context: authority.server_context
         
     | 
| 
       15 
15 
     | 
    
         
             
            }
         
     | 
| 
       16 
16 
     | 
    
         
             
            server = Polyphony::HTTP::Server.listen('0.0.0.0', 1234, opts)
         
     | 
| 
       17 
     | 
    
         
            -
            puts  
     | 
| 
      
 17 
     | 
    
         
            +
            puts 'Listening on port 1234'
         
     | 
| 
       18 
18 
     | 
    
         | 
| 
       19 
19 
     | 
    
         
             
            child_pids = []
         
     | 
| 
       20 
20 
     | 
    
         
             
            4.times do
         
     | 
| 
       21 
21 
     | 
    
         
             
              child_pids << Polyphony.fork do
         
     | 
| 
       22 
22 
     | 
    
         
             
                puts "forked pid: #{Process.pid}"
         
     | 
| 
       23 
     | 
    
         
            -
                 
     | 
| 
      
 23 
     | 
    
         
            +
                server.each(&app)
         
     | 
| 
       24 
24 
     | 
    
         
             
              end
         
     | 
| 
       25 
25 
     | 
    
         
             
            end
         
     | 
| 
       26 
26 
     | 
    
         | 
| 
       27 
     | 
    
         
            -
            child_pids.each { |pid| EV::Child.new(pid).await }
         
     | 
| 
      
 27 
     | 
    
         
            +
            child_pids.each { |pid| EV::Child.new(pid).await }
         
     | 
| 
         @@ -7,23 +7,23 @@ require 'localhost/authority' 
     | 
|
| 
       7 
7 
     | 
    
         
             
            STDOUT.sync = true
         
     | 
| 
       8 
8 
     | 
    
         | 
| 
       9 
9 
     | 
    
         
             
            def ws_handler(conn)
         
     | 
| 
       10 
     | 
    
         
            -
              while msg = conn.recv
         
     | 
| 
      
 10 
     | 
    
         
            +
              while (msg = conn.recv)
         
     | 
| 
       11 
11 
     | 
    
         
             
                conn << "you said: #{msg}"
         
     | 
| 
       12 
12 
     | 
    
         
             
              end
         
     | 
| 
       13 
13 
     | 
    
         
             
            end
         
     | 
| 
       14 
14 
     | 
    
         | 
| 
       15 
15 
     | 
    
         
             
            authority = Localhost::Authority.fetch
         
     | 
| 
       16 
16 
     | 
    
         
             
            opts = {
         
     | 
| 
       17 
     | 
    
         
            -
              reuse_addr: 
     | 
| 
       18 
     | 
    
         
            -
              dont_linger: 
     | 
| 
       19 
     | 
    
         
            -
              upgrade: 
     | 
| 
      
 17 
     | 
    
         
            +
              reuse_addr:     true,
         
     | 
| 
      
 18 
     | 
    
         
            +
              dont_linger:    true,
         
     | 
| 
      
 19 
     | 
    
         
            +
              upgrade:        {
         
     | 
| 
       20 
20 
     | 
    
         
             
                websocket: Polyphony::Websocket.handler(&method(:ws_handler))
         
     | 
| 
       21 
21 
     | 
    
         
             
              },
         
     | 
| 
       22 
22 
     | 
    
         
             
              secure_context: authority.server_context
         
     | 
| 
       23 
23 
     | 
    
         
             
            }
         
     | 
| 
       24 
24 
     | 
    
         | 
| 
       25 
25 
     | 
    
         
             
            puts "pid: #{Process.pid}"
         
     | 
| 
       26 
     | 
    
         
            -
            puts  
     | 
| 
      
 26 
     | 
    
         
            +
            puts 'Listening on port 1234...'
         
     | 
| 
       27 
27 
     | 
    
         
             
            Polyphony::HTTP::Server.serve('0.0.0.0', 1234, opts) do |req|
         
     | 
| 
       28 
28 
     | 
    
         
             
              req.respond("Hello world!\n")
         
     | 
| 
       29 
     | 
    
         
            -
            end
         
     | 
| 
      
 29 
     | 
    
         
            +
            end
         
     | 
| 
         @@ -6,21 +6,21 @@ require 'polyphony/http' 
     | 
|
| 
       6 
6 
     | 
    
         
             
            STDOUT.sync = true
         
     | 
| 
       7 
7 
     | 
    
         | 
| 
       8 
8 
     | 
    
         
             
            def ws_handler(conn)
         
     | 
| 
       9 
     | 
    
         
            -
              while msg = conn.recv
         
     | 
| 
      
 9 
     | 
    
         
            +
              while (msg = conn.recv)
         
     | 
| 
       10 
10 
     | 
    
         
             
                conn << "you said: #{msg}"
         
     | 
| 
       11 
11 
     | 
    
         
             
              end
         
     | 
| 
       12 
12 
     | 
    
         
             
            end
         
     | 
| 
       13 
13 
     | 
    
         | 
| 
       14 
14 
     | 
    
         
             
            opts = {
         
     | 
| 
       15 
     | 
    
         
            -
              reuse_addr: 
     | 
| 
      
 15 
     | 
    
         
            +
              reuse_addr:  true,
         
     | 
| 
       16 
16 
     | 
    
         
             
              dont_linger: true,
         
     | 
| 
       17 
     | 
    
         
            -
              upgrade: 
     | 
| 
      
 17 
     | 
    
         
            +
              upgrade:     {
         
     | 
| 
       18 
18 
     | 
    
         
             
                websocket: Polyphony::Websocket.handler(&method(:ws_handler))
         
     | 
| 
       19 
19 
     | 
    
         
             
              }
         
     | 
| 
       20 
20 
     | 
    
         
             
            }
         
     | 
| 
       21 
21 
     | 
    
         | 
| 
       22 
22 
     | 
    
         
             
            puts "pid: #{Process.pid}"
         
     | 
| 
       23 
     | 
    
         
            -
            puts  
     | 
| 
      
 23 
     | 
    
         
            +
            puts 'Listening on port 1234...'
         
     | 
| 
       24 
24 
     | 
    
         
             
            Polyphony::HTTP::Server.serve('0.0.0.0', 1234, opts) do |req|
         
     | 
| 
       25 
25 
     | 
    
         
             
              req.respond("Hello world!\n")
         
     | 
| 
       26 
     | 
    
         
            -
            end
         
     | 
| 
      
 26 
     | 
    
         
            +
            end
         
     | 
| 
         @@ -4,9 +4,9 @@ require 'bundler/setup' 
     | 
|
| 
       4 
4 
     | 
    
         
             
            require 'polyphony/postgres'
         
     | 
| 
       5 
5 
     | 
    
         | 
| 
       6 
6 
     | 
    
         
             
            def get_records
         
     | 
| 
       7 
     | 
    
         
            -
               
     | 
| 
      
 7 
     | 
    
         
            +
              $db.query('select 1 as test')
         
     | 
| 
       8 
8 
     | 
    
         
             
              # puts "got #{res.ntuples} records: #{res.to_a}"
         
     | 
| 
       9 
     | 
    
         
            -
            rescue => e
         
     | 
| 
      
 9 
     | 
    
         
            +
            rescue StandardError => e
         
     | 
| 
       10 
10 
     | 
    
         
             
              puts "got error: #{e.inspect}"
         
     | 
| 
       11 
11 
     | 
    
         
             
              puts e.backtrace.join("\n")
         
     | 
| 
       12 
12 
     | 
    
         
             
            end
         
     | 
| 
         @@ -28,9 +28,9 @@ $db = PG.connect( 
     | 
|
| 
       28 
28 
     | 
    
         
             
              sslmode:  'require'
         
     | 
| 
       29 
29 
     | 
    
         
             
            )
         
     | 
| 
       30 
30 
     | 
    
         | 
| 
       31 
     | 
    
         
            -
            X =  
     | 
| 
      
 31 
     | 
    
         
            +
            X = 10_000
         
     | 
| 
       32 
32 
     | 
    
         
             
            t0 = Time.now
         
     | 
| 
       33 
33 
     | 
    
         
             
            X.times { get_records }
         
     | 
| 
       34 
34 
     | 
    
         
             
            puts "query rate: #{X / (Time.now - t0)} reqs/s"
         
     | 
| 
       35 
35 
     | 
    
         | 
| 
       36 
     | 
    
         
            -
            time_printer.stop
         
     | 
| 
      
 36 
     | 
    
         
            +
            time_printer.stop
         
     | 
| 
         @@ -9,14 +9,14 @@ PGOPTS = { 
     | 
|
| 
       9 
9 
     | 
    
         
             
              password: nil,
         
     | 
| 
       10 
10 
     | 
    
         
             
              dbname:   'reality',
         
     | 
| 
       11 
11 
     | 
    
         
             
              sslmode:  'require'
         
     | 
| 
       12 
     | 
    
         
            -
            }
         
     | 
| 
      
 12 
     | 
    
         
            +
            }.freeze
         
     | 
| 
       13 
13 
     | 
    
         | 
| 
       14 
14 
     | 
    
         
             
            DBPOOL = Polyphony::ResourcePool.new(limit: 8) { PG.connect(PGOPTS) }
         
     | 
| 
       15 
15 
     | 
    
         | 
| 
       16 
16 
     | 
    
         
             
            def get_records(db)
         
     | 
| 
       17 
     | 
    
         
            -
               
     | 
| 
      
 17 
     | 
    
         
            +
              db.query('select pg_sleep(0.001) as test')
         
     | 
| 
       18 
18 
     | 
    
         
             
              # puts "got #{res.ntuples} records: #{res.to_a}"
         
     | 
| 
       19 
     | 
    
         
            -
            rescue => e
         
     | 
| 
      
 19 
     | 
    
         
            +
            rescue StandardError => e
         
     | 
| 
       20 
20 
     | 
    
         
             
              puts "got error: #{e.inspect}"
         
     | 
| 
       21 
21 
     | 
    
         
             
              puts e.backtrace.join("\n")
         
     | 
| 
       22 
22 
     | 
    
         
             
            end
         
     | 
| 
         @@ -27,9 +27,16 @@ puts "concurrency: #{CONCURRENCY}" 
     | 
|
| 
       27 
27 
     | 
    
         
             
            DBPOOL.preheat!
         
     | 
| 
       28 
28 
     | 
    
         
             
            t0 = Time.now
         
     | 
| 
       29 
29 
     | 
    
         
             
            count = 0
         
     | 
| 
       30 
     | 
    
         
            -
            coprocs = CONCURRENCY.times.map  
     | 
| 
       31 
     | 
    
         
            -
              spin  
     | 
| 
       32 
     | 
    
         
            -
             
     | 
| 
      
 30 
     | 
    
         
            +
            coprocs = CONCURRENCY.times.map do
         
     | 
| 
      
 31 
     | 
    
         
            +
              spin do
         
     | 
| 
      
 32 
     | 
    
         
            +
                loop do
         
     | 
| 
      
 33 
     | 
    
         
            +
                  DBPOOL.acquire do |db|
         
     | 
| 
      
 34 
     | 
    
         
            +
                    get_records(db)
         
     | 
| 
      
 35 
     | 
    
         
            +
                    count += 1
         
     | 
| 
      
 36 
     | 
    
         
            +
                  end
         
     | 
| 
      
 37 
     | 
    
         
            +
                end
         
     | 
| 
      
 38 
     | 
    
         
            +
              end
         
     | 
| 
      
 39 
     | 
    
         
            +
            end
         
     | 
| 
       33 
40 
     | 
    
         
             
            sleep 5
         
     | 
| 
       34 
41 
     | 
    
         
             
            puts "count: #{count} query rate: #{count / (Time.now - t0)} queries/s"
         
     | 
| 
       35 
42 
     | 
    
         
             
            coprocs.each(&:interrupt)
         
     | 
| 
         @@ -12,17 +12,18 @@ DB = PG.connect( 
     | 
|
| 
       12 
12 
     | 
    
         
             
            )
         
     | 
| 
       13 
13 
     | 
    
         | 
| 
       14 
14 
     | 
    
         
             
            def perform(error)
         
     | 
| 
       15 
     | 
    
         
            -
              puts  
     | 
| 
      
 15 
     | 
    
         
            +
              puts '*' * 40
         
     | 
| 
       16 
16 
     | 
    
         
             
              DB.transaction do
         
     | 
| 
       17 
     | 
    
         
            -
                res = DB.query( 
     | 
| 
      
 17 
     | 
    
         
            +
                res = DB.query('select 1 as test')
         
     | 
| 
       18 
18 
     | 
    
         
             
                puts "result: #{res.to_a}"
         
     | 
| 
       19 
19 
     | 
    
         
             
                raise 'hello' if error
         
     | 
| 
      
 20 
     | 
    
         
            +
             
     | 
| 
       20 
21 
     | 
    
         
             
                DB.transaction do
         
     | 
| 
       21 
     | 
    
         
            -
                  res = DB.query( 
     | 
| 
      
 22 
     | 
    
         
            +
                  res = DB.query('select 2 as test')
         
     | 
| 
       22 
23 
     | 
    
         
             
                  puts "result: #{res.to_a}"
         
     | 
| 
       23 
24 
     | 
    
         
             
                end
         
     | 
| 
       24 
25 
     | 
    
         
             
              end
         
     | 
| 
       25 
     | 
    
         
            -
            rescue => e
         
     | 
| 
      
 26 
     | 
    
         
            +
            rescue StandardError => e
         
     | 
| 
       26 
27 
     | 
    
         
             
              puts "error: #{e.inspect}"
         
     | 
| 
       27 
28 
     | 
    
         
             
            end
         
     | 
| 
       28 
29 
     | 
    
         | 
| 
         @@ -1,6 +1,7 @@ 
     | 
|
| 
       1 
1 
     | 
    
         
             
            # frozen_string_literal: true
         
     | 
| 
       2 
2 
     | 
    
         | 
| 
       3 
3 
     | 
    
         
             
            require 'bundler/setup'
         
     | 
| 
      
 4 
     | 
    
         
            +
            require 'polyphony/auto_run'
         
     | 
| 
       4 
5 
     | 
    
         
             
            require 'polyphony/redis'
         
     | 
| 
       5 
6 
     | 
    
         | 
| 
       6 
7 
     | 
    
         
             
            class RedisChannel < Polyphony::Channel
         
     | 
| 
         @@ -20,8 +21,11 @@ class RedisChannel < Polyphony::Channel 
     | 
|
| 
       20 
21 
     | 
    
         
             
                  subscribe_connection.subscribe(CHANNEL_MASTER_TOPIC) do |on|
         
     | 
| 
       21 
22 
     | 
    
         
             
                    on.message do |topic, message|
         
     | 
| 
       22 
23 
     | 
    
         
             
                      message = Marshal.load(message)
         
     | 
| 
       23 
     | 
    
         
            -
                      topic == CHANNEL_MASTER_TOPIC 
     | 
| 
       24 
     | 
    
         
            -
             
     | 
| 
      
 24 
     | 
    
         
            +
                      topic == if CHANNEL_MASTER_TOPIC
         
     | 
| 
      
 25 
     | 
    
         
            +
                                 handle_master_message(message)
         
     | 
| 
      
 26 
     | 
    
         
            +
                               else
         
     | 
| 
      
 27 
     | 
    
         
            +
                                 handle_channel_message(topic, message)
         
     | 
| 
      
 28 
     | 
    
         
            +
                               end
         
     | 
| 
       25 
29 
     | 
    
         
             
                    end
         
     | 
| 
       26 
30 
     | 
    
         
             
                  end
         
     | 
| 
       27 
31 
     | 
    
         
             
                end
         
     | 
| 
         @@ -48,20 +52,20 @@ class RedisChannel < Polyphony::Channel 
     | 
|
| 
       48 
52 
     | 
    
         
             
              def self.watch(channel)
         
     | 
| 
       49 
53 
     | 
    
         
             
                @channels[channel.topic] = channel
         
     | 
| 
       50 
54 
     | 
    
         
             
                spin do
         
     | 
| 
       51 
     | 
    
         
            -
                  publish_connection.publish(CHANNEL_MASTER_TOPIC, Marshal.dump( 
     | 
| 
       52 
     | 
    
         
            -
             
     | 
| 
       53 
     | 
    
         
            -
             
     | 
| 
       54 
     | 
    
         
            -
             
     | 
| 
      
 55 
     | 
    
         
            +
                  publish_connection.publish(CHANNEL_MASTER_TOPIC, Marshal.dump(
         
     | 
| 
      
 56 
     | 
    
         
            +
                                                                     kind:  :subscribe,
         
     | 
| 
      
 57 
     | 
    
         
            +
                                                                     topic: channel.topic
         
     | 
| 
      
 58 
     | 
    
         
            +
                                                                   ))
         
     | 
| 
       55 
59 
     | 
    
         
             
                end
         
     | 
| 
       56 
60 
     | 
    
         
             
              end
         
     | 
| 
       57 
61 
     | 
    
         | 
| 
       58 
62 
     | 
    
         
             
              def self.unwatch(channel)
         
     | 
| 
       59 
63 
     | 
    
         
             
                @channels.delete(channel.topic)
         
     | 
| 
       60 
64 
     | 
    
         
             
                spin do
         
     | 
| 
       61 
     | 
    
         
            -
                  publish_connection.publish(CHANNEL_MASTER_TOPIC, Marshal.dump( 
     | 
| 
       62 
     | 
    
         
            -
             
     | 
| 
       63 
     | 
    
         
            -
             
     | 
| 
       64 
     | 
    
         
            -
             
     | 
| 
      
 65 
     | 
    
         
            +
                  publish_connection.publish(CHANNEL_MASTER_TOPIC, Marshal.dump(
         
     | 
| 
      
 66 
     | 
    
         
            +
                                                                     kind:  :unsubscribe,
         
     | 
| 
      
 67 
     | 
    
         
            +
                                                                     topic: channel.topic
         
     | 
| 
      
 68 
     | 
    
         
            +
                                                                   ))
         
     | 
| 
       65 
69 
     | 
    
         
             
                end
         
     | 
| 
       66 
70 
     | 
    
         
             
              end
         
     | 
| 
       67 
71 
     | 
    
         | 
| 
         @@ -114,4 +118,4 @@ spin do 
     | 
|
| 
       114 
118 
     | 
    
         
             
              end
         
     | 
| 
       115 
119 
     | 
    
         
             
              channel.close
         
     | 
| 
       116 
120 
     | 
    
         
             
              RedisChannel.stop_monitor
         
     | 
| 
       117 
     | 
    
         
            -
            end
         
     | 
| 
      
 121 
     | 
    
         
            +
            end
         
     | 
| 
         @@ -5,7 +5,7 @@ require 'polyphony/redis' 
     | 
|
| 
       5 
5 
     | 
    
         | 
| 
       6 
6 
     | 
    
         
             
            redis = Redis.new
         
     | 
| 
       7 
7 
     | 
    
         | 
| 
       8 
     | 
    
         
            -
            X =  
     | 
| 
      
 8 
     | 
    
         
            +
            X = 10
         
     | 
| 
       9 
9 
     | 
    
         | 
| 
       10 
10 
     | 
    
         
             
            t0 = Time.now
         
     | 
| 
       11 
11 
     | 
    
         
             
            X.times { redis.get('abc') }
         
     | 
| 
         @@ -13,7 +13,7 @@ puts "get rate: #{X / (Time.now - t0)} reqs/s" 
     | 
|
| 
       13 
13 
     | 
    
         | 
| 
       14 
14 
     | 
    
         
             
            puts "abc = #{redis.get('abc')}"
         
     | 
| 
       15 
15 
     | 
    
         | 
| 
       16 
     | 
    
         
            -
            puts  
     | 
| 
      
 16 
     | 
    
         
            +
            puts 'updating value...'
         
     | 
| 
       17 
17 
     | 
    
         
             
            redis.set('abc', Time.now.to_s)
         
     | 
| 
       18 
18 
     | 
    
         | 
| 
       19 
19 
     | 
    
         
             
            puts "abc = #{redis.get('abc')}"
         
     | 
| 
         @@ -1,6 +1,7 @@ 
     | 
|
| 
       1 
1 
     | 
    
         
             
            # frozen_string_literal: true
         
     | 
| 
       2 
2 
     | 
    
         | 
| 
       3 
3 
     | 
    
         
             
            require 'bundler/setup'
         
     | 
| 
      
 4 
     | 
    
         
            +
            require 'polyphony/auto_run'
         
     | 
| 
       4 
5 
     | 
    
         
             
            require 'polyphony/redis'
         
     | 
| 
       5 
6 
     | 
    
         | 
| 
       6 
7 
     | 
    
         
             
            spin do
         
     | 
| 
         @@ -8,7 +9,7 @@ spin do 
     | 
|
| 
       8 
9 
     | 
    
         
             
              redis.subscribe('redis-channel') do |on|
         
     | 
| 
       9 
10 
     | 
    
         
             
                on.message do |channel, message|
         
     | 
| 
       10 
11 
     | 
    
         
             
                  puts "##{channel}: #{message}"
         
     | 
| 
       11 
     | 
    
         
            -
                  redis.unsubscribe if message ==  
     | 
| 
      
 12 
     | 
    
         
            +
                  redis.unsubscribe if message == 'exit'
         
     | 
| 
       12 
13 
     | 
    
         
             
                end
         
     | 
| 
       13 
14 
     | 
    
         
             
              end
         
     | 
| 
       14 
15 
     | 
    
         
             
            end
         
     | 
| 
         @@ -1,19 +1,20 @@ 
     | 
|
| 
       1 
1 
     | 
    
         
             
            # frozen_string_literal: true
         
     | 
| 
       2 
2 
     | 
    
         | 
| 
       3 
3 
     | 
    
         
             
            require 'bundler/setup'
         
     | 
| 
      
 4 
     | 
    
         
            +
            require 'polyphony/auto_run'
         
     | 
| 
       4 
5 
     | 
    
         
             
            require 'polyphony/redis'
         
     | 
| 
       5 
6 
     | 
    
         
             
            require 'json'
         
     | 
| 
       6 
7 
     | 
    
         | 
| 
       7 
8 
     | 
    
         
             
            X_SESSIONS = 1000
         
     | 
| 
       8 
     | 
    
         
            -
            X_NODES =  
     | 
| 
      
 9 
     | 
    
         
            +
            X_NODES = 10_000
         
     | 
| 
       9 
10 
     | 
    
         
             
            X_SUBSCRIPTIONS_PER_SESSION = 100
         
     | 
| 
       10 
11 
     | 
    
         | 
| 
       11 
12 
     | 
    
         
             
            $sessions = []
         
     | 
| 
       12 
13 
     | 
    
         
             
            X_SESSIONS.times do
         
     | 
| 
       13 
14 
     | 
    
         
             
              $sessions << {
         
     | 
| 
       14 
     | 
    
         
            -
                subscriptions: X_SUBSCRIPTIONS_PER_SESSION.times.map  
     | 
| 
      
 15 
     | 
    
         
            +
                subscriptions: X_SUBSCRIPTIONS_PER_SESSION.times.map do
         
     | 
| 
       15 
16 
     | 
    
         
             
                  "node#{rand(X_NODES)}"
         
     | 
| 
       16 
     | 
    
         
            -
                 
     | 
| 
      
 17 
     | 
    
         
            +
                end.uniq
         
     | 
| 
       17 
18 
     | 
    
         
             
              }
         
     | 
| 
       18 
19 
     | 
    
         
             
            end
         
     | 
| 
       19 
20 
     | 
    
         | 
| 
         @@ -30,20 +31,20 @@ $update_count = 0 
     | 
|
| 
       30 
31 
     | 
    
         | 
| 
       31 
32 
     | 
    
         
             
            def distribute_event(event)
         
     | 
| 
       32 
33 
     | 
    
         
             
              $update_count += 1
         
     | 
| 
       33 
     | 
    
         
            -
              t0 = Time.now
         
     | 
| 
      
 34 
     | 
    
         
            +
              # t0 = Time.now
         
     | 
| 
       34 
35 
     | 
    
         
             
              count = 0
         
     | 
| 
       35 
36 
     | 
    
         
             
              $sessions.each do |s|
         
     | 
| 
       36 
37 
     | 
    
         
             
                count += 1 if s[:subscriptions].include?(event[:path])
         
     | 
| 
       37 
38 
     | 
    
         
             
              end
         
     | 
| 
       38 
     | 
    
         
            -
              elapsed = Time.now - t0
         
     | 
| 
       39 
     | 
    
         
            -
              rate = X_SESSIONS / elapsed
         
     | 
| 
      
 39 
     | 
    
         
            +
              # elapsed = Time.now - t0
         
     | 
| 
      
 40 
     | 
    
         
            +
              # rate = X_SESSIONS / elapsed
         
     | 
| 
       40 
41 
     | 
    
         
             
              # puts "elapsed: #{elapsed} (#{rate}/s)" if $update_count % 100 == 0
         
     | 
| 
       41 
42 
     | 
    
         
             
            end
         
     | 
| 
       42 
43 
     | 
    
         | 
| 
       43 
44 
     | 
    
         
             
            spin do
         
     | 
| 
       44 
45 
     | 
    
         
             
              redis = Redis.new
         
     | 
| 
       45 
46 
     | 
    
         
             
              throttled_loop(1000) do
         
     | 
| 
       46 
     | 
    
         
            -
                redis.publish('events', {path: "node#{rand(X_NODES)}"}.to_json)
         
     | 
| 
      
 47 
     | 
    
         
            +
                redis.publish('events', { path: "node#{rand(X_NODES)}" }.to_json)
         
     | 
| 
       47 
48 
     | 
    
         
             
              end
         
     | 
| 
       48 
49 
     | 
    
         
             
            end
         
     | 
| 
       49 
50 
     | 
    
         | 
| 
         @@ -54,10 +55,13 @@ spin do 
     | 
|
| 
       54 
55 
     | 
    
         
             
                now = Time.now
         
     | 
| 
       55 
56 
     | 
    
         
             
                elapsed = now - last_stamp
         
     | 
| 
       56 
57 
     | 
    
         
             
                delta = $update_count - last_count
         
     | 
| 
       57 
     | 
    
         
            -
                puts "update rate: #{delta.to_f/elapsed}"
         
     | 
| 
      
 58 
     | 
    
         
            +
                puts "update rate: #{delta.to_f / elapsed}"
         
     | 
| 
       58 
59 
     | 
    
         
             
                last_stamp = now
         
     | 
| 
       59 
60 
     | 
    
         
             
                last_count = $update_count
         
     | 
| 
       60 
61 
     | 
    
         
             
              end
         
     | 
| 
       61 
62 
     | 
    
         
             
            end
         
     | 
| 
       62 
63 
     | 
    
         | 
| 
       63 
     | 
    
         
            -
            Polyphony.trap(:int)  
     | 
| 
      
 64 
     | 
    
         
            +
            Polyphony.trap(:int) do
         
     | 
| 
      
 65 
     | 
    
         
            +
              puts 'bye...'
         
     | 
| 
      
 66 
     | 
    
         
            +
              exit!
         
     | 
| 
      
 67 
     | 
    
         
            +
            end
         
     | 
    
        data/examples/io/cat.rb
    CHANGED
    
    | 
         @@ -1,13 +1,12 @@ 
     | 
|
| 
       1 
1 
     | 
    
         
             
            # frozen_string_literal: true
         
     | 
| 
       2 
2 
     | 
    
         | 
| 
       3 
3 
     | 
    
         
             
            require 'bundler/setup'
         
     | 
| 
       4 
     | 
    
         
            -
            require 'polyphony'
         
     | 
| 
      
 4 
     | 
    
         
            +
            require 'polyphony/auto_run'
         
     | 
| 
       5 
5 
     | 
    
         | 
| 
       6 
     | 
    
         
            -
             
     | 
| 
      
 6 
     | 
    
         
            +
            File.open(__FILE__, 'r') do |f|
         
     | 
| 
       7 
7 
     | 
    
         
             
              line_number = 1
         
     | 
| 
       8 
8 
     | 
    
         
             
              while (l = f.gets)
         
     | 
| 
       9 
     | 
    
         
            -
                puts  
     | 
| 
       10 
     | 
    
         
            -
                STDOUT.puts '%03d %s' % [line_number, l]
         
     | 
| 
      
 9 
     | 
    
         
            +
                puts format('%03d %s', line_number, l)
         
     | 
| 
       11 
10 
     | 
    
         
             
                line_number += 1
         
     | 
| 
       12 
11 
     | 
    
         
             
              end
         
     | 
| 
       13 
     | 
    
         
            -
            end
         
     | 
| 
      
 12 
     | 
    
         
            +
            end
         
     | 
    
        data/examples/io/echo_client.rb
    CHANGED
    
    | 
         @@ -1,17 +1,22 @@ 
     | 
|
| 
       1 
1 
     | 
    
         
             
            # frozen_string_literal: true
         
     | 
| 
       2 
2 
     | 
    
         | 
| 
       3 
3 
     | 
    
         
             
            require 'bundler/setup'
         
     | 
| 
       4 
     | 
    
         
            -
            require 'polyphony'
         
     | 
| 
      
 4 
     | 
    
         
            +
            require 'polyphony/auto_run'
         
     | 
| 
      
 5 
     | 
    
         
            +
            require 'polyphony/extensions/backtrace'
         
     | 
| 
       5 
6 
     | 
    
         | 
| 
       6 
7 
     | 
    
         
             
            socket = Polyphony::Net.tcp_connect('127.0.0.1', 1234)
         
     | 
| 
       7 
8 
     | 
    
         | 
| 
       8 
9 
     | 
    
         
             
            writer = spin do
         
     | 
| 
       9 
     | 
    
         
            -
              throttled_loop(1)  
     | 
| 
      
 10 
     | 
    
         
            +
              throttled_loop(1) do
         
     | 
| 
      
 11 
     | 
    
         
            +
                socket << "#{Time.now}\n"
         
     | 
| 
      
 12 
     | 
    
         
            +
              rescue StandardError
         
     | 
| 
      
 13 
     | 
    
         
            +
                nil
         
     | 
| 
      
 14 
     | 
    
         
            +
              end
         
     | 
| 
       10 
15 
     | 
    
         
             
            end
         
     | 
| 
       11 
16 
     | 
    
         | 
| 
       12 
17 
     | 
    
         
             
            reader = spin do
         
     | 
| 
       13 
     | 
    
         
            -
              puts  
     | 
| 
       14 
     | 
    
         
            -
              while data = socket.readpartial(8192)
         
     | 
| 
      
 18 
     | 
    
         
            +
              puts 'received from echo server:'
         
     | 
| 
      
 19 
     | 
    
         
            +
              while (data = socket.readpartial(8192))
         
     | 
| 
       15 
20 
     | 
    
         
             
                STDOUT << data
         
     | 
| 
       16 
21 
     | 
    
         
             
              end
         
     | 
| 
       17 
22 
     | 
    
         
             
            end
         
     | 
| 
         @@ -0,0 +1,20 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            # frozen_string_literal: true
         
     | 
| 
      
 2 
     | 
    
         
            +
             
     | 
| 
      
 3 
     | 
    
         
            +
            require 'bundler/setup'
         
     | 
| 
      
 4 
     | 
    
         
            +
            require 'polyphony/auto_run'
         
     | 
| 
      
 5 
     | 
    
         
            +
            require 'polyphony/extensions/backtrace'
         
     | 
| 
      
 6 
     | 
    
         
            +
             
     | 
| 
      
 7 
     | 
    
         
            +
            socket = Polyphony::Net.tcp_connect('127.0.0.1', 1234)
         
     | 
| 
      
 8 
     | 
    
         
            +
             
     | 
| 
      
 9 
     | 
    
         
            +
            writer = spin do
         
     | 
| 
      
 10 
     | 
    
         
            +
              while (data = gets)
         
     | 
| 
      
 11 
     | 
    
         
            +
                socket << data
         
     | 
| 
      
 12 
     | 
    
         
            +
              end
         
     | 
| 
      
 13 
     | 
    
         
            +
            end
         
     | 
| 
      
 14 
     | 
    
         
            +
             
     | 
| 
      
 15 
     | 
    
         
            +
            spin do
         
     | 
| 
      
 16 
     | 
    
         
            +
              while (data = socket.readpartial(8192))
         
     | 
| 
      
 17 
     | 
    
         
            +
                STDOUT << 'received: ' + data
         
     | 
| 
      
 18 
     | 
    
         
            +
              end
         
     | 
| 
      
 19 
     | 
    
         
            +
              writer.interrupt
         
     | 
| 
      
 20 
     | 
    
         
            +
            end
         
     | 
    
        data/examples/io/echo_pipe.rb
    CHANGED
    
    | 
         @@ -1,17 +1,16 @@ 
     | 
|
| 
       1 
1 
     | 
    
         
             
            # frozen_string_literal: true
         
     | 
| 
       2 
2 
     | 
    
         | 
| 
       3 
3 
     | 
    
         
             
            require 'bundler/setup'
         
     | 
| 
       4 
     | 
    
         
            -
            require 'polyphony'
         
     | 
| 
      
 4 
     | 
    
         
            +
            require 'polyphony/auto_run'
         
     | 
| 
       5 
5 
     | 
    
         | 
| 
       6 
6 
     | 
    
         
             
            i, o = IO.pipe
         
     | 
| 
       7 
7 
     | 
    
         | 
| 
       8 
     | 
    
         
            -
            puts  
     | 
| 
       9 
     | 
    
         
            -
            spin  
     | 
| 
       10 
     | 
    
         
            -
               
     | 
| 
      
 8 
     | 
    
         
            +
            puts 'Say something:'
         
     | 
| 
      
 9 
     | 
    
         
            +
            spin do
         
     | 
| 
      
 10 
     | 
    
         
            +
              loop { o << STDIN.gets }
         
     | 
| 
       11 
11 
     | 
    
         
             
              o.close
         
     | 
| 
       12 
     | 
    
         
            -
            }
         
     | 
| 
       13 
     | 
    
         
            -
             
     | 
| 
       14 
     | 
    
         
            -
            while data = i.readpartial(8192)
         
     | 
| 
       15 
     | 
    
         
            -
              STDOUT << "You wrote: #{data}"
         
     | 
| 
       16 
12 
     | 
    
         
             
            end
         
     | 
| 
       17 
13 
     | 
    
         | 
| 
      
 14 
     | 
    
         
            +
            while (data = i.readpartial(8192))
         
     | 
| 
      
 15 
     | 
    
         
            +
              STDOUT << "You said: #{data}"
         
     | 
| 
      
 16 
     | 
    
         
            +
            end
         
     |