Andrey Pavlov

March 27, 2021

Ni bezonas programujo, ĉu ne?

Hodiaŭ ni parolos pro Elixir-programingvo kaj programadaj ŝablonoj.

Estas multaj programadaj ŝablonoj. Unu el ili estas PubSub. PubSub temas pri datuma fluo. Estas produktantoj nomataj "Publishers" kaj ricevantoj nomataj "Subscribers". Pluvo-ricevanto diras "Mi volas ricevi ĉiujn leteroj pri pluvo!" kaj neĝo-ricevanto diras "Mi volas ricevi ĉiujn leteroj pri neĝas!". "pri pluvo" kaj "pri neĝo" estas  temoj. Veterprognozo-produktano produktas veterprognozo "Hodiaŭ estos pluvo" aŭ "Hodiaŭ estos neĝo" kaj sendas ĝin al la taŭga temo. Kiam ricevanto ricevas leteron de temo, ĝi iom laboros kaj sendos leteron al alia temo, kaj tiel plu.

pubsub_eo.png


Kiam oni volas uzi Pubsub en la Elixir, oni iras al la hex.pm kaj serĉas pubsub-programujo:

phoenix_pubsub estos elektitu ĉar ĝi havas la plej multajn elŝutojn.

Sed ni reiru! Ni jam programi en la Elixir, do ni ne bezonas uzi programo-bibliotekon. Ĉion ni bezonas jam estas en la Erlang programo-biblioteko. Ĝi nomiĝas pg. Procezoj kombineblas en grupojn. Grupojn nomojn estas temoj. Produktanto povas trovi ĉiun membron de grupo kaj sendi leteron al ili.

Ekzemple:
$ iex
Erlang/OTP 23 [erts-11.1.8] [source] [64-bit] [smp:16:16] [ds:16:16:10] [async-threads:1] [hipe]

Interactive Elixir (1.11.4) - press Ctrl+C to exit (type h() ENTER for help)
iex(1)> {:ok, _} = :pg.start_link()
{:ok, #PID<0.109.0>}
iex(2)> subscriber = fn topic ->
...(2)>   fn ->
...(2)>     :pg.join(topic, self())
...(2)>      recv = fn loop ->
...(2)>        receive do
...(2)>          msg ->
...(2)>            IO.puts("#{topic} -- #{inspect(msg)}")
...(2)>            loop.(loop)
...(2)>        end
...(2)>      end
...(2)>      recv.(recv)
...(2)>   end
...(2)> end
#Function<44.79398840/1 in :erl_eval.expr/5>
iex(3)> spawn(subscriber.("pluvtemo"))
#PID<0.124.0>
iex(4)> spawn(subscriber.("neĝtemo"))
#PID<0.126.0>
iex(5)> :pg.get_members("pluvtemo") |> Enum.each(fn pid -> send(pid, "Pluvas") end)
:ok
pluvtemo -- "Pluvas"
iex(6)> :pg.get_members("pluvtemo") |> Enum.each(fn pid -> send(pid, "Ne pluvas") end)
pluvtemo -- "Ne pluvas"
:ok
iex(7)> :pg.get_members("neĝtemo") |> Enum.each(fn pid -> send(pid, "Neĝas") end)
neĝtemo -- "Neĝas"
:ok

Tiel ni povas realigi PubSub en la Elixir!