lorecrafting

lorecrafting

For some reason i’m getting this error:

[error] GenServer KioskTracker_shard10 terminating
** (stop) exited in: GenServer.call(KioskTracker_shard10, {:list, “room:kiosk”}, 5000)
** (EXIT) process attempted to call itself

It’s erroring out on the Phoenix.Tracker.list call.
What is the proper way to access the list of tracked connections within the handle_diff callback function of a Phoenix Tracker?

Thanks!

  def handle_diff(diff, state) do
    kiosks = Phoenix.Tracker.list(__MODULE__, "room:kiosk")
    IO.puts("KIOSKS CONNECTED")
        IO.inspect(kiosks)
    for {topic, {joins, leaves}} <- diff do
      for {key, meta} <- joins do
        IO.puts("presence join: key \"#{key}\" with meta #{inspect(meta)}")
        # This stuff might be for distributed system with more than one node, look into it later
        # msg = {:join, key, meta}
        # Phoenix.PubSub.direct_broadcast!(state.node_name, state.pubsub_server, topic, msg)
      end

      for {key, meta} <- leaves do
        
        
        IO.puts("presence leave: key \"#{key}\" with meta #{inspect(meta)}")
        # This stuff might be for distributed system with more than one node, look into it later
        # msg = {:leave, key, meta}
        # Phoenix.PubSub.direct_broadcast!(state.node_name, state.pubsub_server, topic, msg)
      end
    end

    {:ok, state}
  end

Blockquote

Showing Posts 1 to 10

sb8244

sb8244

Author of Real-Time Phoenix

This might be an XY problem. What are you looking to achieve?

Without knowing much about your use case, you could spawn the with that needs the list of kiosks. However, you can’t do that if you need it for the return of the handle diff (I have a hard time envisioning a use case for that)

lorecrafting

lorecrafting OP

I think you are right, this may be an XY problem and I might just be banging my head with very limited knowledge in Elixir =D

The problem i’m trying to solve is to shut off the ability to place an order on a mobile app if the separate web kiosk is not open.

The way i’m trying to implement it is in the handle_diff callback, whoever ‘leaves’ the channel will have their mobile app ordering shut off via a feature flag platform (LaunchDarkly).

However, there may be two or three different kiosks up at the same time for the same tenant, and wanted it to shut off if only ALL of them were off. So i was going to retrieve the existing list or presence of connections and check if there are no other kiosks of the same tenant on the list.

Is handle_diff the proper place to write all this logic or should I put it in a different module?

Thanks!

lorecrafting

lorecrafting OP

Hmm.. I’m trying to implement spawning another process and calling the Track function inside of it but I get this error:

[error] GenServer KioskTracker_shard10 terminating
** (Protocol.UndefinedError) protocol String.Chars not implemented for {:“$gen_call”, {pid<0.630.0>, reference<0.3898897701.2923167750.135453>}, {:list, “room:kiosk”}} of type Tuple. This protocol is implemented for the following type(s): Postgrex.Copy, Postgrex.Query, Decimal, Float, DateTime, Time, List, Version.Requirement, Atom, Integer, Version, Date, BitString, NaiveDateTime, URI
(elixir 1.10.2) lib/string/chars.ex:3: String.Chars.impl_for!/1
(elixir 1.10.2) lib/string/chars.ex:22: String.Chars.to_string/1
(savor_kiosk 0.1.0) lib/savor_kiosk_web/channels/kiosk_tracker.ex:60: KioskTracker.handle_diff/2
(phoenix_pubsub 1.1.2) lib/phoenix/tracker/shard.ex:485: Phoenix.Tracker.Shard.report_diff_join/5
(phoenix_pubsub 1.1.2) lib/phoenix/tracker/shard.ex:294: Phoenix.Tracker.Shard.put_presence/6
(phoenix_pubsub 1.1.2) lib/phoenix/tracker/shard.ex:228: Phoenix.Tracker.Shard.handle_call/3
(stdlib 3.9) gen_server.erl:661: :gen_server.try_handle_call/4
(stdlib 3.9) gen_server.erl:690: :gen_server.handle_msg/6
(stdlib 3.9) proc_lib.erl:249: :proc_lib.init_p_do_apply/3

Is it saying the second item in the tuple can’t be a string?
If I do Phoenix.Tracker.list(KioskTracker, “room:kiosk”) In iex it works, but that exact function doesn’t work in the spawning function.

Thanks again for the help while i’m diving straight into this world!

def handle_diff(diff, state) do
    
    IO.inspect(diff)

    parent = self()
    
    spawn(fn() ->
      IO.puts("SPAWNING****")
      kiosks = Phoenix.Tracker.list(KioskTracker, "room:kiosk")
      IO.puts("KIOSKS CONNECTED")
      IO.inspect(kiosks)
      send(parent, 'ohai')
    end)

    receive do
      random -> IO.puts("Received #{random}")
    end


    for {topic, {joins, leaves}} <- diff do
      for {key, meta} <- joins do
        IO.puts("presence join: key \"#{key}\" with meta #{inspect(meta)}")
        # This stuff might be for distributed system with more than one node, look into it later
        # msg = {:join, key, meta}
        # Phoenix.PubSub.direct_broadcast!(state.node_name, state.pubsub_server, topic, msg)
      end

      for {key, meta} <- leaves do
        IO.puts("presence leave: key \"#{key}\" with meta #{inspect(meta)}")
        # This stuff might be for distributed system with more than one node, look into it later
        # msg = {:leave, key, meta}
        # Phoenix.PubSub.direct_broadcast!(state.node_name, state.pubsub_server, topic, msg)
      end
    end

    {:ok, state}
  end
end
sb8244

sb8244

Author of Real-Time Phoenix

I’m pretty sure that’s from the receive. The line number will tell you exactly

Regardless, you can’t block the receive like that. When I recommended a spawn, I was talking purely about for side effect code. If you want the tracker result as part of processing the diff, then I think you’re blocked.

What are you trying to do? I’m almost certain that you shouldn’t go down this path.

lorecrafting

lorecrafting OP

I’ll take your advice and rethink the solution. I may need help with it as my knowledge is very limited.

Within the receive, or once I somehow have the list of connected kiosks, i wanted to make sure there aren’t any identical kiosks in the list to the one that just disconnected. This is solving for the case that there are two or more kiosks up that belong to the same tenant.

Only when all kiosks of the a specific tenant has disconnected, only then do I want to fire off instructions that turn off mobile ordering functionality.

So in the handle_diff i need two pieces of information:

  1. The entity that disconnected
  2. The list of connected kiosks
    So that I can check the list to see if there are any other kiosks out there belonging to the same tenant. If there aren’t, then i’ll fire off the instructions to shut off mobile ordering. If there is then do nothing.

Would the alternate solution be to send a message from the handle_diff to another process to handle all the logic?

Again, thanks!

lorecrafting

lorecrafting OP

Yup you’re right, it errors out in the receive.

lorecrafting

lorecrafting OP

Ah! I’ve uncommented out PhoenixPubSub.direct_broadcast! functions and an now trying to do the logic in the Channels. Going to play around with that and think this may be a better direction!

sb8244

sb8244

Author of Real-Time Phoenix

The one thing to consider with handle_diff is that it will execute on every node in the cluster for a given change. This means that if there’s some logic you want to do once, it will actually run N times.

The Channel approach may work here (especially if intercepting handle_diff). You can execute code to check the kiosks and shut down in that case. I normally recommend Tracker, but Presence would actually fit pretty well if you’re intercepting handle_diff. It’s just tracker + broadcasting the diff to that topic.

lorecrafting

lorecrafting OP

Awesome, thanks for guidance!

vbroskas

vbroskas

How did you end up solving this issue? Im getting the same error when trying to call Phoenix.Tracker.list(tracker_name, topic) from either inside my handle_diff() callback or another module.

I thought of intercepting presence_diff in my channel, and each time there was a leave I could make a call to Phoenix.Tracker.list(). However Im finding that while intercepting prescence_diff it doesn’t seem to fire when the last person subscribed to a topic leaves (I assume this is because the last person leaving kills the presence for that topic)

— All posts loaded —

Where Next? Top

Trending in Questions Top

RSP87
I’m working on a project that simulates the bumbl example in the programming phoenix book. It acts almost like an email client. We have a...
New
kszambelanczyk
Hello! Could someone please give me a help/sample code, how to delete a file from s3 using waffle/waffle_ecto from Phoenix app. I creat...
New
RemyXRenard
I’m seeing that a list inside a Kino.DataTable will be interpreted as a charlist, even if the Kino.configure() is set to charlists: :as_l...
New
velrest
So my question is quite simple and i have found no conclusive answer on forum, google or AI. Should we use :erlang.float for Integer to ...
New
samoloth
Hi, I’ve just set up an application with ash_authentication. There is only magic link strategy for now, so there is no confirmation add o...
New
FlyingNoodle
If a change or preparation module uses Ash.Changeset.get_argument/2 or Ash.Query.get_argument/2 (or any of the other get_argument functio...
New
nseaSeb
Hello, I know there is an approach for handling lists that allows for optimized traversal, but I can’t recall the specific method (somet...
New

Other Trending Topics Top

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
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

We're in Beta

About us Mission Statement

Options

Thread Display Mode




Thread Preview

Skip Thread Previews