Presence.update loop works once then returns {:error, :nopresence}

Hello all!

I have a function to loop through each presence and update the same key. It works on the first run but then returns {:error, :nopresence} on each subsequent one.

Been banging my head on this one. If anyone has any ideas I would greatly appreciate it!

def update_presence_for_each(key) do
    for presence <- Presence.list_presences(@topic) do
      Presence.update_presence(self(), @topic, presence.user_id, key)

That function calls the below:

  def update_presence(pid, topic, key, payload) do
    metas =
      Presence.get_by_key(topic, key)[:metas]
      |> List.first()
      |> Map.merge(payload)
    Presence.update(pid, topic, key, metas)

  def list_presences(topic) do
    |> {_user_id, data} ->
      |> List.first()

All the right values are being passed each time in the loop, so I’m not sure what it could be.

1 Like

I’ve been doing some digging today and think I discovered what may be causing the problem.

I’ve included a ton of IO.puts so you can see what’s happening.

When I inspect the metas before the update that succeeds, notice it has both phx_ref and phx_ref_prev metas. But on the one that fails, it doesn’t have the phx_ref_prev meta.

I’ve confirmed this pattern happens for every update that fails, even if that update runs first in the loop.

I don’t have the right answer yet but am getting closer and will update you all when I figure it out. I’m assuming there’s an issue with my update_presence function that compiles the metas.

1 Like

OK, I figured it out. Pretty simple in retrospect, here’s what happened:

I am looping through all presences in a single user’s process, calling the update and passing these variables (self(), @topic, user_id, key)

The loop fails because you can’t update a users presence metas by passing the other user’s PID, aka the self() part.

By updating the Presence metas of each user in that user’s own process and passing that user’s PID I was able to get it to work.