54) ElixirConf US 2018 – Closing Keynote – Chris McCord

This reminds me the idea which was never implemented, but it might be good to remind (there are some notes about it in Drab thread on this forum, but it is too long to be useful as a data source).

What happens while disconnection during handler process running

In normal case, the event handler process (the one which runs when you operate the JS even with drab-click=handler_name) dies, as it is linked to the drab genserver, which is linked to the channel process.
If you want your event handler to persist, the best way is to run the background process and pass the socket to it. Imagine that disconnection happens when this background process operates:

poke socket, status: "Starting DB update..."
# perform long DB operation
poke socket, status: "DB update finished."
# more

poke returns {:error, :disconnected} in case of disconnection so you should handle it and react accordingly.

But what if, during the long DB operation, the client will disconnect and reconnect again? In this case, Drab still return :disconnected on the second poke, as after reconnection the brand new socket is used.

Idea: should Drab handle this?

The idea was to use the unique browser id to identify the connections

  • sockets are stored somewhere on the server and linked to the browser IDs
  • instead of socket, all Drab functions receives own data structure (%Drut{browser_id: binary}) with the ID
  • normal event handlers operates as previously, but introduce the new event handler function, the task, which is not linked with channel process anymore
  • on disconnect, Drab removes the socket from the global browser_id => [socket] storage (note that it may be more than 1 socket for the browser)
  • Drab functions returns {:error, :disconnected} only when there is no more sockets on the list for this id

After this, Drab functions may be changed to the way that they queue changes to the frontend. Consider:

poke drut, status: "Starting DB update..."
# perform long DB operation
poke drut, status: "Step 1 finished."
# perform long DB operation
poke drut, status: "Step 2 finished."
# perform long DB operation
poke drut, status: "All steps completed."
# more

Let’s say we don’t really care if the status was updated - db changes are more important - so we do not check the poke return value. All the changes will be applied when the browser reconnects. You could even close the browser and, after the next connection, have a correct status of the job.

Of course in this case we need to have a cleaning mechanism, with timeouts and so on.

I’ve announced this idea here before, but the answer of the community was - not worth to do it, if you want to have it, handle it yourself. So I postponed the implementation to the future versions of Drab. But I still like the idea. Imagine you are coming from the other world (lets say Rails) and have persistent task with live status updates for free with that ease.

2 Likes