digital-fabric / tipi

Tipi - the All-in-one Web Server for Ruby Apps
MIT License
244 stars 7 forks source link

Forked example doesn't work? #8

Closed dbackeus closed 3 years ago

dbackeus commented 3 years ago

When running the forked http example I only ever get responses from a single pid, so can't seem to utilize more than a single core on my machine.

System: MacOS Big Sur on a 2020 intel Macbook Pro Ruby: 2.7.2 Tipi version: 0.33 Polyphony version: 0.47.5.1 (noticeably not the latest version, due to how the tipi dependency is configured)

dbackeus commented 3 years ago

Made another attempt using the HEAD version of tipi which uses a later version of polyphony. However still just a single ruby process responding to requests.

Also this new version appears to detach / "daemonize" the server so I can't CTRL+C to shut everything down but have to hunt the forked processes via activity monitor or similar to kill them.

I also made a fork to use the latest (0.51) version of polyphony but its behaviour was identical to tipi head.

dbackeus commented 3 years ago

Update: When trying this on Ubuntu 20.10 instead of MacOS, the forked example worked nicely. So I guess this is a MacOS related issue?

noteflakes commented 3 years ago

Most probably. I don't have access access to a Mac, so I'll appreciate any help in that regard.

timhatch commented 3 years ago

Hi,

I've also been working my way through the examples. Ruby = 3.0.1, Gem versions are polyphony = 0.55.0 and tipi = 0.32. I didn't specify gem versions when I ran bundler and am not sure why tipi 0.32 was installed rather than the latest version. I'm running Big Sur on an M1 Mini. Anyway...

The forked example from the gem's examples folder initially didn't work, which I guessed was down to an obsolete call to Polyphony::HTTP::Server.listen. Changing that over to Tipi.listen fixed the issue and had the Gem's example serving across 8 forks as expected.

When I tested the example from the GitHub repo (but sticking with 0.32 as the installed Gem) the server responds only on a single fork so I looked at the differences between the two examples. The key difference appears to be where/how the server is initialised, i.e.

Gem (0.32)

server = Tipi.listen('0.0.0.0', 1234, opts)

child_pids = []
8.times do
  pid = Polyphony.fork do
    puts "forked pid: #{Process.pid}"
    server.each do |req|
      req.respond("Hello world! from pid: #{Process.pid}\n")
    end
  rescue Interrupt
  end
  child_pids << pid
end

Github (0.38)

child_pids = []
8.times do  
  pid = Polyphony.fork do    
    puts "forked pid: #{Process.pid}"    
    Tipi.serve('0.0.0.0', 1234, opts) do |req|      
      req.respond("Hello world! from pid: #{Process.pid}\n")
    end
  rescue Interrupt
  end
  child_pids << pid
end

I haven't yet worked through the tipi source to figure out what's going on, but this may help.

Addendum Thought I'd see what happened if I went closer to the bleeding edge and created a new project folder using Tipi 0.38. Pretty much every example fails now with an argument error in http1_adapter.rb

noteflakes commented 3 years ago

Thanks for reporting this. I've been doing a lot of work around Tipi in the last few month (including extracting the request/response API into a separate gem). I'll try to update the examples so they'll work again as soon as possible.

noteflakes commented 3 years ago

I went over all of the included examples, fixing any problems, so they should all work. Please check out version 0.39 and let me know if you find any more problems.

timhatch commented 3 years ago

@circonia Super-fast getting those examples redone!

I ran through most of them, leaving aside only tests requiring a secure server (I don't have the localhost gem installed and would like to get familiar with that separately).

The following examples ran successfully straight off:

The _routingserver.rb example runs though I'm not sure that r.redirect is working? If root redirects to '/hello' then I would have expected some response back as the /hello route should return "hello"?

On MacOS the _http_serverforked example misbehaves as previously reported. 8 forks are started up, but all responses (to a curl request) come from just one fork. Modifying the code to follow the same pattern as the earlier (v0.32) example fixes the issue much as I reported above, i.e.

server = Tipi.listen('0.0.0.0', 1234, opts)

child_pids = []
8.times do
  pid = Polyphony.fork do
    puts "forked pid: #{Process.pid}"
    server.each do |req|
      req.respond("Hello world! from pid: #{Process.pid}\n")
    end
  rescue Interrupt
  end
  child_pids << pid
end

I haven't spent enough time with Tipi to understand the difference between the two patterns, so I'm unsure why/how this reformatting has any effect.

For the _http_wsserver.rb example I needed to change the URL in _wspage.html from "wss://dev.realiteq.net/" to "ws://localhost:4411" but other than that the example worked perfectly with Brave and Firefox as clients. With Safari as the client the connections errored out <Errno::ECONNRESET: Connection reset by peer - Connection reset by peer>. I'm not sure that Tipi can be blamed for differences between clients and I haven't had the time yet to explore why Safari doesn't behave, but Apple...

For the _websocketdemo.rb example I needed to change the requires from

require 'bundler/inline'

gemfile do
  source 'https://rubygems.org'
  gem 'polyphony', '~> 0.44'
  gem 'tipi', '~> 0.31'
end

require 'tipi/websocket'

to

require 'bundler/setup'
require 'tipi'
require 'tipi/websocket'

That may be down to how I've installed Tipi (I keep "experiments" in self contained directories rather than installing the gems globally), but the example itself worked without problem.

Nice work.

timhatch commented 3 years ago

Follow up to the above. After digging around to figure out why Safari was having problems connecting, I came across this SO link: https://stackoverflow.com/questions/62352790/websockets-not-working-on-ios-and-safari-ossstatus-error-9837

After I had enabled the NSURLSession Websocket experimental option I was able to connect to the _http_wsserver.rb example without problems with Safari as the client. As the problem appears to be linked to TLS, I'll to check out the https/wss examples also.