LiteFS and Rails Action Cable

Hi, I’m trying to run a Rails app that’s using LiteFS and I’ve run into some problems with websocket connections. It looks like they are not being passed through the built in proxy in LiteFS. When I modify my fly.toml to go around the proxy (the proxy listens at 3000, and my rails app is at 3001, so I changed my config to expose the http service on 3001) then my websocket connections begin working.

I’m not sure how to get around this while still taking advantage of LiteFS. I tried exposing both 3000 and 3001 with this configuration, but the 3001 port is not accepting websocket connections for some reason:

[http_service]
  internal_port = 3000
  force_https = true
  auto_stop_machines = false
  auto_start_machines = true
  min_machines_running = 0
  processes = ["app"]

[[services]]
  internal_port = 3001
  protocol = "tcp"
  auto_stop_machines = false
  auto_start_machines = true
  min_machines_running = 0
  processes = ["app"]
  [[services.ports]]
    port = 3001
    handlers = ["tls", "http"]

The LiteFS proxy doesn’t support redirecting websocket connections since they’re persistent and the primary can change. Unfortunately, you’ll need to do some internal RPC if you want to redirect writes by determining the current primary.

FYI: a common use case of Rails is broadcast only websockets (i.e., no requests from the client, everything is push from the server). With Turbo 8, another common pattern will be messages (again unsolicited from the server) to the client informing them of the need to do a refresh, to which the client will respond with a HTTP GET.

2 Likes

That makes sense that it can’t support proxying a persistent connection without failing to uphold it’s guarantee of sending write requests to the primary. However, I configured my /cable endpoint to be ignored by the proxy and to always allow it to go through. I had hoped that in that case it might be able to work.

And what Sam said is correct, in my case I’m not using any writes over the websocket connection. I am using Turbo 8, and so it’s only purpose is to broadcast from the server to the client when the client needs to refresh the current page.

So what is the best way to handle this situation, assuming that the proxy will not be supporting websocket connections? I thought my above solution would work of exposing 3 ports (80, 443 and 3001) and having the normal web requests use 80/443 as usual but direct the websocket connections over 3001 was going to work, but I never landed on a configuration that worked. My client would never connect to the 3001 port. I did realize I needed a dedicated IP, but even still it did not work.

So as of right now, I’m completely side stepping the proxy, and just handling all the traffic on a single server to prevent any write issues.

This topic was automatically closed 7 days after the last reply. New replies are no longer allowed.