Anko

Anko

Hey guys,

I have a pattern I’ve been using on a few projects and I just wanted to share :slight_smile:

Quite often I want to notify a user if something has happened when the browser window is in the background. For my use case, the js Notification API is perfect. This is what I do;

in app.js;

let Hooks = {}

function sendNotification(title, message) {
  if(Notification.permission === "granted") {
    try {
      new Notification(title, {body: message, requireInteraction: false});
    } catch (e) {
      console.debug("notifcation error: " + e)
    }
  }
}

Hooks.Notification = {
  mounted(){
    if(Notification.permission === "default") {
      Notification.requestPermission();
    }
    this.handleEvent("notification", ({title, message}) => sendNotification(title, message));
  }
}

Note that this will ask the user for the notification on mount, which might not be what you want. You could easily have a button that pushes to the client with an event that asks for notification.

To hook it in your need to add the hooks to your liveSocket call like;

let liveSocket = new LiveSocket("/live", Socket, {params: {_csrf_token: csrfToken}, hooks: Hooks})

then on your live view;

<div id="notification" phx-hook="Notification"></div>

And finally in your live view supporting code eg a handle info callback;

{:noreply, push_event(socket, "notification", %{title: title, message: message})}

:slight_smile:

There are lots of enhancements you can do like only send these notifications if the browser is in the background eg. watch for phx-window-blur and phx-window-focus events and set some state so you know when it’s in the background. You could also enhance it by using a service worker and sending the notifcations via gcm/apns but that was an overkill for my use case.

Overall it’s been a nice pattern - I love when i’m uploading a file or processing some work and get a notification when it’s complete.

Cheers,
Anko

Showing Posts 1 to 7

Anko

Anko OP

I noticed something really interesting about this. If your browser doesn’t have focus, Safari and Chrome will disconnect the websocket after about 10 minutes.

A way around this is to push an event from the server to the client, waking it up. phoenix keepalives seem to be from client to server so they do not work for this.

This is what I do;

  @impl true
  def handle_info(:ping_client, socket) do
    IO.puts "ping_client" 

    Process.send_after(self(), :ping_client, 60_000 * 5)
    {:noreply, push_event(socket, "server_ping", %{})}
  end

and in my mount make sure you start with a

if connected? socket do
  Process.send_after(self(), :ping_client, 5000) # time doesn't matter so much
end

Maybe pings should go from server to client? @josevalim @chrismccord

Has anyone else noticed this?

related:
https://github.com/primus/primus/issues/348
https://github.com/socketio/socket.io/issues/2924

josevalim

josevalim

Creator of Elixir

Perhaps we should have a configuration for it. But after 10 minutes unfocused… it probably makes sense to disconnect until focused again? Otherwise you always risk consuming battery on devices, etc.

Anko

Anko OP

It’s not that they are closing the websocket directly; they are stopping the timers running on unfocussed pages which is stopping the client side ping which is closing the websocket.

I agree a configuration would be a good compromise. It’s hard to know the right approach but it seems like getting notifications would be a use case where we don’t mind the battery drain as much - the point of them is to alert you when the web page is not in focus. I guess if it’s abused the browser developers will actively disconnect websockets when they have lost focus.

Anko

Anko OP

You could also argue that the reconnect work is more expensive than just keeping the websocket open!

josevalim

josevalim

Creator of Elixir

Are we reconnecting immediately or only when the user focus again?

Anko

Anko OP

It seems to have some backoff but it doesn’t need user focus. I need to perform more testing.

— All posts loaded —

Where Next? Top

Trending in Discussions Top

AstonJ
As the title says, please share what you’ve been up to with Elixir. Whether that’s been learning it, looking into it, making stuff with i...
2977 94592 917
New
cblavier
Hey there, It’s been more than a year since we started using LiveView as our main UI library and building a whole library of UI componen...
New
caslu
I want to open this thread for you all to discuss and help those who really like Ash but are still hesitant to use it in a real project. ...
New
mudasobwa
I am happy to introduce the very α version of the new programming language compiled to BEAM. Welcome Cure. It has literally three kille...
New
heathen
Quite interesting article Google brought me. Didn’t find any mentions about it here. What do you think in general? Would you use togethe...
New
marciol
It would be helpful to have a list of companies worldwide that hire engineers without prior experience in Elixir. Often, it can be quite ...
New
durvia
Anyone running long-lived stateful processes on BEAM? We’re building an AI agent runtime and would love to compare notes. We’re a small ...
New

Other Trending Topics Top

marciok
Hi there! We created Gust: A task orchestrator inspired by Airflow. For those who have never heard about Aiflow, it’s a Python-based wor...
New
jimsynz
Beam Bots (or just BB for short) is a framework for building fault-tolerant robotics applications in Elixir using familiar OTP patterns. ...
New
Dmk
Xamal is a deployment tool for Elixir apps that deploys native releases to bare metal servers over SSH. It’s a port of GitHub - basecamp/...
New
Damirados
Hello everyone. After busy few months I am happy to announce v0.1.0 of Emerge &amp; Solve. They are GUI (Emerge) and State management (S...
New
netoum
Corex is an accessible, unstyled UI component library for Phoenix that integrates Zag.js state machines using Vanilla JavaScript and Live...
New
webofbits
Aludel - LLM Evaluation Workbench Aludel is an embeddable Phoenix LiveView dashboard for evaluating and comparing LLM prompts across mult...
New

We're in Beta

About us Mission Statement

Options

Thread Display Mode




Thread Preview

Skip Thread Previews