kirillplatonov / hotwire-livereload

Live reload gem for Hotwire Rails apps.
MIT License
458 stars 25 forks source link

Websocket disconnects after first reloading in Rails 7.1 #49

Closed kirillplatonov closed 3 weeks ago

kirillplatonov commented 10 months ago

https://github.com/kirillplatonov/hotwire-livereload/assets/839922/35c947d7-52ce-4df9-81c5-d0bc710954d1

imageaid commented 9 months ago

Hi, there,

I wanted to note a follow-up as I had this issue as well. Turns out, for me, it ended up being a problem in my Connection class. I had a scenario in my find_verified_user method that ended up calling reject_unauthorized_connection and killing the connection.

When I added a conditional block to account for a websocket request, all was good and this error no longer appears and, most importantly, reloading happened again :)

Thanks to all for the work on this hugely helpful gem!

kirillplatonov commented 8 months ago

I continue investigating this issue. So far I found out that websocket got disconnected due to ActionCable server restart: https://github.com/rails/rails/blob/main/actioncable/lib/action_cable/engine.rb#L91 But I'm not able to locate what's causing class unloading and restart. We use autoload_once_paths for app/channels folder so it seems not to be related. I'll appreciate any help. Very tricky issue.

mrfullset commented 4 months ago

I've faced the issue too. However, if you go with turbo_stream socket, it doesn't disconnect. I know it's not the best DX, but at least something 🫠

pjg commented 4 months ago

I've run into this issue as well. Using config.hotwire_livereload.reload_method = :turbo_stream fixes the disconnection issue. However, there's a related issue in that a second, quick subsequent edit will not execute a refresh/reload in the browser. Only after some cooldown period any subsequent edit will be reflected in the browser.

mrfullset commented 4 months ago

@pjg did you try setting up a config.hotwire_livereload.debounce_delay_ms = 300?

pjg commented 4 months ago

@mrfullset I tried, but it didn't change anything. I have plain CSS without any preprocessors, so this setting seems to not be applicable to me.

What I'm seeing is that for any change I make in a html or css file, I can see in server's logs it being broadcasted:

[ActionCable] Broadcasting to hotwire-livereload: "<turbo-stream action=\"replace\" target=\"hotwire-livereload\">...

but then it doesn't update on the browser side. And then after a short while I get another request for /cable (with "upgrade"):

Started GET "/cable" for 127.0.0.1 at 2024-05-24 17:17:48 +0200
Started GET "/cable" [WebSocket] for 127.0.0.1 at 2024-05-24 17:17:48 +0200
Successfully upgraded to WebSocket (REQUEST_METHOD: GET, HTTP_CONNECTION: upgrade, HTTP_UPGRADE: websocket)
Turbo::StreamsChannel is transmitting the subscription confirmation
Turbo::StreamsChannel is streaming from hotwire-livereload

And then the next file save will trigger a proper refresh.

Maybe I should file a new issue for this?

pokonski commented 3 months ago

Same problem exists in Rails 7.2 beta 2.

After first file change and refresh it disconnects for a while until ActionCable reconnects again after 10 seconds:

image

LEstradioto commented 1 month ago

I've encountered this issue as well. After debugging ActionCable, it appears the problem isn't isolated to ActionCable alone, but rather an interaction between ActionCable and Turbo. There might be a conflict or a recent Turbo update causing this behavior. I couldn't find the exact reason for the server_restart, but it's possible that Turbo.visit is removing the websocket or cable connection.

The solution I found is implemented in this PR #62 . It introduces an early reconnect, which feels almost instantaneous and is a significant improvement over the 10-second delay. While I'm not certain if this should be considered a permanent fix or a temporary workaround, it effectively addresses the issue.

I found this, Im unsure perhaps is related with

kirillplatonov commented 3 weeks ago

@LEstradioto great work with #62 👏 Let's keep it as a temporary workaround until we'll find out how to prevent ActionCable server restart. But nothing is more permanent than temporary.

From my investigation, the issue is related to classes autoloading changes in Rails 7.1. ActionCable classes are being unloaded which causes server restart. I was able to trace it to this code but, couldn't find what exactly causing the unload: https://github.com/rails/rails/blob/main/actioncable/lib/action_cable/engine.rb#L91