How best to push events to Elm?

Hi, I’m working on a photo upload feature that will have a resize pipeline on the backend. I’d like to push a notification to the client when the pipeline is done.

I’m hoping someone here has built something similar in Elm and can share their experiences.

For example, is the Open Sensors Elm library solid? Or did you keep things simple and setup polling with an Elm subscription and the Time module?

Thanks!

1 Like

not good.

SSE [server-sent event] opens a stream to the client with no content length and sends packets down it when they become available. Here’s the rub though, it uses Transfer Encoding which only guarantees the method of delivery to the next node in the chain.

Any old proxy in the middle of the connection between your server and the client’s device can legally just store all those packets up and wait for the stream to close before forwarding them. It will do that because it sees no Content-Length and thinks - my client want’s to know how big it is. Maybe the code predates text/event-stream that needs no Content-Length, who knows, but they are out there

To push events to Elm, I often used (long)-polling. I also used this in real-time online games as it allows for minimal message delays.
For the general approach of long-polling, there is an explanation at https://github.com/elm-time/elm-time/blob/6a484c7d7ff1dd478bf0278e2ea414c7782a0b3e/implement/example-apps/rich-chat-room/README.md#fast-distribution-of-messages-in-the-chat-room-using-long-polling

In the ‘rich chat room’ example app, new messages sent by one user appear almost immediately for other users. But this example uses HTTP for communication between backend and frontends, a protocol that does not support pushing a message to a client. How do messages arrive so quickly despite the use of HTTP?

The trick we use here is called ‘long-polling’. It means the backend does not always respond to the HTTP request immediately but waits until there is a change in the room that we should broadcast. As soon as a change happens in the room, the backend completes the HTTP response. The wait time is limited, so the backend will eventually respond with the same state if nothing changes in the chat room. You can see this when you open the network inspection in the web browser’s ‘devtools’. Here you will find that the backend often takes a long time to answer an HTTP request. When a user sends a new message into the chat room, this HTTP response time becomes shorter to ensure the immediate broadcast.

To implement long-polling, we expand the HTTP request from the client and the state on the backend. The client tells the backend about the last message it has already seen, so the backend knows if the room’s current state is new to this particular client. If the client is already up-to-date, the backend needs to remember the pending HTTP request. When any client sends a new message, the backend uses this list of pending requests to send the corresponding HTTP responses.

You can see an Elm app implementing long-polling at https://github.com/elm-time/elm-time/blob/6a484c7d7ff1dd478bf0278e2ea414c7782a0b3e/implement/example-apps/rich-chat-room/src/Frontend/Main.elm#L240-L263

Another way to push server events to the web is websockets. But that would be better for a more chatty interface, one that remains open for a long time, and sends lots of events in both directions.

In your case, it seems like you are waiting a single DONE event after requesting an image pipeline be run. So just set that up on a URL, and poll it. You likely also need a retry mechanism in case the long poll times out and you need to try again until you get the DONE event.

Thanks @Viir for the code links, very helpful.

Agreed @rupert and thanks. BTW, thinking / searching about long-polling and AWS Lambda’s led me to your work on migrating elm-serverless to 0.19. Since AWS is HTTP all the way down, that way of using Elm is pretty interesting. Seems like with some Elm libraries to interact with common AWS services via HTTP that would be a productive dev setup.

There are some published Elm stubs for AWS services:

https://package.elm-lang.org/packages/the-sett/elm-aws-cognito/latest/
https://package.elm-lang.org/packages/the-sett/elm-aws-elastic-containers/latest/

These are generated Elm code from the AWS service descriptors. Not all service descriptors are supported yet, but many are. You can find the code generator here:

2 Likes

I’m using Elm with a RabbitMQ server using the MQTT protocol. In the client, Elm is communicating via ports via the Paho JavaScript library.

But it’s a complicated setup, and a lot of things have to be handled in JS, like reconnects, connection failures, etc.

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