#Unable to get genserver to genserver communication working

1 messages · Page 1 of 1 (latest)

slow cove
#

I am trying to get 1 genserver to send a message to another genserver using Genserver.call/3

but even though both genservers are up, I get ** (EXIT) no process: the process is not alive or there's no process currently associated with the given name, possibly because its application isn't started as an error

I set module names using __MODULE__ and i am passing the module as the first param to call/3 (in this case its BMCServer.PacketHandler)

Any ideas why my stuff isn't working right (i have handle_call() implemented in PacketHandler

#
defp handle_packet(data, socket, address, port) do
    # print the message
    IO.puts("Received: #{String.trim data} from #{:inet_parse.ntoa(address)}:#{port}")
    GenServer.call(BMCServer.PacketHandler, {address, port, data})
    {:noreply, socket}
  end
#
defmodule BMCServer.PacketHandler do
  use GenServer
  def start_link() do
    IO.puts("#{__MODULE__} has started")
    GenServer.start_link(__MODULE__, name: __MODULE__)
  end

  def init(_opts) do
    {:ok, nil}
  end

  def handle_call({address, port, data}, _from, state) do
    <<packetSize::unsigned-integer-16, rest::binary-size(packetSize)>> = data
    IO.puts("Size #{packetSize}")
    {:reply, {address, port, data, packetSize, rest}, state}
  end
end
glacial crescent
#

Are both processes started?

slow cove
#

they should be according to the log output

#
Compiling 1 file (.ex)
Elixir.BMCServer.UDPServer started
Elixir.BMCServer.PacketHandler has started
Received: g from 127.0.0.1:54792

23:26:15.510 [error] GenServer BMCServer.UDPServer terminating
** (stop) exited in: GenServer.call(nil, {{127, 0, 0, 1}, 54792, "g\n"}, 5000)
    ** (EXIT) no process: the process is not alive or there's no process currently associated with the given name, possibly because its application isn't started
    (elixir 1.13.4) lib/gen_server.ex:1019: GenServer.call/3
    (bmcserver 0.1.0) lib/bmcserver/udp_server.ex:49: BMCServer.UDPServer.handle_packet/4
    (stdlib 3.17.2) gen_server.erl:695: :gen_server.try_dispatch/4
    (stdlib 3.17.2) gen_server.erl:771: :gen_server.handle_msg/6
    (stdlib 3.17.2) proc_lib.erl:226: :proc_lib.init_p_do_apply/3
Last message: {:udp, #Port<0.5>, {127, 0, 0, 1}, 54792, "g\n"}
State: #Port<0.5>
BMCServer.UDPServer started```
glacial crescent
#

Important thing - calling GenServer functions against process defined in another module is unidiomatic

#

Also, snake_case for variable names is more idiomatic

slow cove
#

then whats the best way to have 2 GenServers communicate?

glacial crescent
#

Define function in your module that will call the process

slow cove
#

so something like def blah() do Genserver.call(__MODULE__) end and then have the other genserver call blah() ?

glacial crescent
#

Indeed

slow cove
#

seems kind of roundabout, but if thats idiomatic, sure. and sorry about hte variables, coming from Go, so lots of camelcase

magic sundial
tall coral
#

GenServer.call(nil, {{127, 0, 0, 1}, 54792, "g\n"}, 5000) it's getting nil for the name/pid, says so in your logs

glacial crescent
#

And it seems that you call the GenServer.call/2 passing nil as the process name

magic sundial
#

better to stick to having both client and server api in the same place

#

would also reduce repetition in case you make the same function call from different modules

tall coral
slow cove
#

I acually wrote that exact function, but still getting an error

tall coral
#

is it still getting nil for some reason?

magic sundial
#
GenServer.start_link(__MODULE__, name: __MODULE__)
#

that cant work

slow cove
#
BMCServer.PacketHandler.parse_packet(address, port, data)```
```elixir
def parse_packet(address, port, data) do
    GenServer.call(__MODULE__, {address, port, data})
  end
❯ mix run --no-halt
Elixir.BMCServer.UDPServer has started
Elixir.BMCServer.PacketHandler has started
Received: s from 127.0.0.1:54792

23:51:40.966 [error] GenServer BMCServer.UDPServer terminating
** (stop) exited in: GenServer.call(BMCServer.PacketHandler, {{127, 0, 0, 1}, 54792, "s\n"}, 5000)
    ** (EXIT) no process: the process is not alive or there's no process currently associated with the given name, possibly because its application isn't started
    (elixir 1.13.4) lib/gen_server.ex:1019: GenServer.call/3
    (bmcserver 0.1.0) lib/bmcserver/udp_server.ex:48: BMCServer.UDPServer.handle_packet/4
    (stdlib 3.17.2) gen_server.erl:695: :gen_server.try_dispatch/4
    (stdlib 3.17.2) gen_server.erl:771: :gen_server.handle_msg/6
    (stdlib 3.17.2) proc_lib.erl:226: :proc_lib.init_p_do_apply/3
Last message: {:udp, #Port<0.5>, {127, 0, 0, 1}, 54792, "s\n"}
State: #Port<0.5>
Elixir.BMCServer.UDPServer has started
#

no, im not getting nil anymore, that was an old log

magic sundial
#
GenServer.start_link(__MODULE__, [], name: __MODULE__)
#

is what u meant

tall coral
#

yeah, you're missing the initial state

slow cove
#

well that did it. I read a bad guide then, because they had a bunch of start_link calls without that middle part.

#

getting a different error, but its related to the binary pattern matching

tall coral
#

so, GenServer.start_link(__MODULE__, name: __MODULE__) is actually starting your genserver with a random pid and setting it's initial state to [name: __MODULE__]

magic sundial
#

the docs are solid for genserver

tall coral
#

can you link us to the bad guide? curious...

slow cove
#

i dunno which one it was, i looked through a bunch trying to figure stuff out at first.

tall coral
slow cove
#

mostly trying to get syntax right

#

possible

magic sundial
slow cove
#

shoudln't binary pattern matching work on an arbitrary data, even if its being treated as a string?

tall coral
#

well, I meant in that it's a /2 and the second arg takes the process opts

#

yes, strings are binaries, so binary pattern matching works on them

slow cove
#

<<packetSize::unsigned-integer-16, rest::binary-size(packetSize)>> = data does that look correct?

magic sundial
#

yes

slow cove
#

so I am assuming i am getting ** (MatchError) no match of right hand side value: "s\n" because the incoming data is not match the pattern?

magic sundial
#

You can have another handle_call for the same message and inspects it

#

to see what youre receiving

tall coral
#
iex(3)> <<packet_size::unsigned-integer-16, rest::binary-size(packet_size)>> = <<1::16, 2>>
<<0, 1, 2>>
iex(4)> packet_size
1
iex(5)> rest
<<2>>
magic sundial
#
def handle_call({address, port, data}, _from, state) do

should have some identifier

#

not just the tuple size

slow cove
#

ok. thats fine, looks like I need to construct some custom data to send its way

#

you mean like handle_call({:parse, address, port, data}, _from, state)

magic sundial
#

yes

slow cove
#

sounds good.

#

coming from a past history with Akka and other Actor implementations in other languages, idiomatic elixir is definitely different. Need to get in the right mindset

tall coral
#

I might also suggest: {message_name, value}. so: {:parse, {address, port, data}}. i.e.: standardize your message type to a 2-tuple

#

but I dunno, might just be my opinion 😅

slow cove
#

thats fair.

#

its probably good to get hte foundational stuff right, so that when i get into the business logic and db stuff, its more robust

glacial crescent
#

The same error?

#

Error is in lib/bmcserver/udp_server.ex at line 49