networking - How do I share data between worker processes in Elixir? -
i have 2 workers
worker(mmoserver.messagereceiver, []), worker(mmoserver.main, [])
the messagereceiver wait until messages received on tcp , process them, main loop take information , act on it. how share info obtained worker1 worker2?
mmoserver.ex
main file starts workers
defmodule mmoserver use application def start(_type, _args) import supervisor.spec, warn: false io.puts "listening packets..." children = [ # add our children here later worker(mmoserver.messagereceiver, []), worker(mmoserver.main, []) ] # start main supervisor, , restart failed children individually opts = [strategy: :one_for_one, name: acmeudplogger.supervisor] supervisor.start_link(children, opts) end end
messagereceiver.ex
start tcp listener. should able message, figure out (by it's id) parse data , send specific function in main
defmodule mmoserver.messagereceiver use genserver require logger def start_link(opts \\ []) genserver.start_link(__module__, :ok, opts) end def init (:ok) {:ok, _socket} = :gen_udp.open(21337) end # handle udp data def handle_info({:udp, _socket, _ip, _port, data}, state) parse_packet(data) # logger.info "received secret message! " <> inspect(message) {:noreply, state} end # ignore else def handle_info({_, _socket}, state) {:noreply, state} end def parse_packet(data) # convert data string, split data # warning - split may expensive datastring = kernel.inspect(data) vars = string.split(datastring, ",") # variables packetid = enum.at(vars, 0) x = enum.at(vars, 1) # stuff them io.puts "packet id:" io.puts packetid io.puts x # send data main mmoserver.main.handle_data(vars) end end
main.ex
main loop. process recent data received tcp listener , act on it. update game state too.
defmodule mmoserver.main use genserver @tickdelay 33 def start_link(opts \\ []) genserver.start_link(__module__, [], name: main) end def init (state) io.puts "main server loop started..." # start main loop, parameter initial tick value mainloop(0) # return, why 1?? {:ok, 1} end def handle_data(data) genserver.cast(:main, {:handle_data, data}) end def handle_info({:handle_data, data}, state) # my_function(data) io.puts "got here2" io.puts inspect(data) {:noreply, state} end # calls respective game functions def mainloop(-1) io.inspect "server loop has ended!" # base case, end of loop end def mainloop(times) # shit # io.inspect(times) # operation, or body of loop # sleep :timer.sleep(@tickdelay); # continue loop recursively mainloop(times + 1) end end
because mmoserver.messagereceiver
going send messages mmoserver.main
, main has started in first place, plus, needs have name associated:
worker(mmoserver.main, []), worker(mmoserver.messagereceiver, [])
the easiest way be, in mmoserver.main
, assuming genserver
:
defmodule mmoserver.main use genserver def start_link genserver.start_link(__module__, [], name: :main) end # ... end
you can add convenience function, plus implementation 1 like:
defmodule mmoserver.main # ... def handle_data(data) genserver.cast(:main, {:handle_data, data}) end def handle_info({:handle_data, data}, state) my_function(data) {:noreply, state} end end
so, messagereceiver
, can send message like:
defmodule mmoserver.messagereceiver def when_data_received(data) mmoserver.main.handle_data(data) end end
this assumes mmoserver.messagereceiver
doesn't expect mmoserver.main
respond. i've decided way didn't specify way want handle data , seems easies example of how this.
Comments
Post a Comment