How to detect channel disconnection

Question

Is there a way to detect that some Eliom_comet channel became disconnected? I would like to warn the user if the server becomes unreachable.

Answer

If you are using Ocsigen-start, you probably have nothing to do. Ocsigen-start will monitor the life of sessions and close the process when needed.

If you are not using Ocsigen-start, you must catch exceptions Eliom_comet.Channel_full, Eliom_comet.Channel_closed (and Eliom_comet.Process_closed on Eliom < 5). Have a look at module Os_comet in Ocsigen-start.

explanation pasted from Ocsigen mailing list, 2014-08-06:

I assume that you want to know that from client side (It is also possible to know that on server side). Since there are quite a lot of different kind of channels, there are different variations of 'disconnected' for them. You receive this information through an exception when you try to read from the Lwt_stream. The different exceptions you have to handle depending on the case are:

Eliom_comet.Channel_full
For global channel. Those are never closed on server side and are not attached to a particular session. The server maintain a limited buffer of previous values to avoid memory leak. If a client reconnects to the network and too many messages have been sent to the channel, since its last update, he will receive that exception.
Eliom_comet.Process_closed (Eliom < 5)
For a channel associated to a client process. If the process is explicitely closed on the server, the server is rebooted, it timeouted, ...
Eliom_comet.Channel_closed
The channel was not maintained alive on the server (garbage collected).

Usualy it is just simpler to not distinguish and just catch on all those exception and consider their meaning to be 'disconnected'.

To handle that reliably, you must be careful: an Lwt_stream raises an exception only once. One way to ensure that you can't miss an exception is to map your channel through Lwt_stream.map_exn and handle the exceptions at that point.

Depending on your case the strategies I would recommend would be either:

  • If you maintain a global state between the client and the server, it is usualy easier to rebuild it from scratch than to rebuild only the missing parts: i.e. the braindead/failure proof solution is to reload the complete contents (Eliom_client.exit_to ~service.Eliom_service.reload_action () ()).
  • If you only want to follow a stream of events and missing a few in the middle isn't a problem, you can just provides a Caml service that sends a channel, and when your channel disconnects, you just fetch a new one. (You may have to use Lwt_stream.concat to do the plumbing)