MushroomObserver / mushroom-observer

A website for sharing observations of mushrooms.
https://mushroomobserver.org
MIT License
77 stars 25 forks source link

Live comment updates with ActionCable #2107

Closed nimmolo closed 2 months ago

nimmolo commented 3 months ago

This PR lays the groundwork for live updates for any object via turbo_stream.

The first place I'm implementing them is Comments. Comments seem like a low-stakes place to test and get it right — it's not that they are so useful, but they're easy to test.

This PR is intended to clear a path for other uses of live updates on the app. The ones I'm more interested in are namings, user notifications, images (for image transformations that are run as a job) and observations, for the home page. These may require a bit of refactoring and renaming some templates.

Incredibly, it took only a few lines of code, but the configurations took quite some time to figure out.

Comments was the easiest to do because the comments panel has the same structure everywhere, and uses conventionally named partials and ivars.

Easiest way to try it out: use test.mushroomobserver.org in two different browser windows/accounts

Trying it out locally: prepare your local server

  1. Install redis server software locally. Linux: sudo apt-get install redis / Mac: brew install redis. You may also have to start the server: redis-server

  2. Install the gems on this branch, bundle install (installs puma locally)

  3. In one terminal window, run ./bin/dev or otherwise start Solid Queue - creates and updates are run as background jobs.

  4. In another terminal window, run rails server

  5. In a third terminal window, test your redis server connection. Run rails console --sandbox, then

    redis = Redis.new
    redis.ping

    You should get a "PONG". If so, you can exit

  6. In two different browsers, say, Firefox and Chrome, or in a regular window and an "incognito" window, log in as two different users. Visit the same observation.

  7. Start posting comments on the observation in either browser.

  8. The comments should appear pretty quickly in the other browser without a page refresh, even if you have a comment form open.

Notes:

coveralls commented 3 months ago

Coverage Status

coverage: 94.434% (-0.02%) from 94.45% when pulling 2c4ae539fb809f5c084f633a3c23d44843953451 on nimmo-actioncable into 4f69b780094f3d29494250b655b93c1e7582288b on main.

mo-nathan commented 2 months ago

Ran into a problem testing based on the above instructions. After install redis, I think you have to start the server with redis-server in another shell. This could probably get added to the bin/dev stuff. Without it running I wan't able to get the "PONG" described above. Once it was running it seems to work.

mo-nathan commented 2 months ago

Looking over the code, it's pretty slick. Do you know if ActionCable is smart enough to only send messages to browsers that are currently looking at a relevant comment or is it essentially sending to everyone and letting the JS decide if it's relevant or not? The first approach seems a bit less reliable, but the second approach sounds like potentially a lot of traffic.

nimmolo commented 2 months ago

Smart enough to only send messages to browsers that are currently looking at a relevant observation - yes. But the smart part is Turbo.

Turbo "subscribes" to the channel, as a result of us adding turbo_stream_from(channel_name) to the template. This renders a custom HTML tag with the channel name, identified by observation ID and comment ID, encrypted as the signed-stream-name. The HTML tag is picked up client side by Turbo; it sends a request to the websocket to subscribe to that channel.

Here's that element printed in the page. The "connected" attribute is added client side, and means Turbo is in fact subscribed to that channel:

<turbo-cable-stream-source 
  channel="Turbo::StreamsChannel" 
  signed-stream-name="IloybGtPaTh2YlhWemFISnZiMjB0YjJKelpYSjJaWEl2VDJKelpYSjJZWFJwYjI0dk5URTFOekV6OmNvbW1lbnRzIg==--68a9ee9d53f5bafd213604820178ec0ac0720145a73a6bf8ef8799a61c59525f" 
  connected="">
</turbo-cable-stream-source>

We need to have one turbo_stream_from(channel_name) on the page per stream, so for example on show obs we might have separate streams for comments, namings, images and the obs itself (for details). But only clients on that obs would be subscribers.

nimmolo commented 2 months ago

(updated my answer on Github with much more detail, it unfortunately won't come through in the email thread.)

nimmolo commented 2 months ago

Ran into a problem testing based on the above instructions. After install redis, I think you have to start the server with redis-server in another shell. This could probably get added to the bin/dev stuff. Without it running I wan't able to get the "PONG" described above. Once it was running it seems to work.

Thanks. Added to the instrux

nimmolo commented 2 months ago

Now deployed on test.mushroomobserver.org and working.

Steps to deploy on production:

nimmolo commented 2 months ago

This is now working in a "production" environment at test.mushroomobserver.org. You can log in as yourself in a regular and "incognito"/"private" window and check it out.

Be careful if testing... any comments you post as tests will also post to the production database.

nimmolo commented 2 months ago

~Remaining issues~

nimmolo commented 2 months ago

Recent changes: