Kurzusok
/
Elixir
Elixir
/
Tanterv
/
Kapcsolatok
Ka

Kapcsolatok ebben a kurzusban: Elixir

1 feladat

A(z) Kapcsolatok fogalomról

Az Elixir folyamatai izoláltak, és alapértelmezés szerint nem osztanak meg semmit egymással. Amikor egy nem összekapcsolt gyermekfolyamat összeomlik, a szülőfolyamatát ez nem érinti.

parent_pid =
  spawn(fn ->
    spawn(fn -> raise "oops" end)

    receive do
      message -> IO.inspect(message, label: "received message")
    end
  end)

# => 20:03:08.405 [error] Process #PID<0.153.0> raised an exception
#    ** (RuntimeError) oops
#    (stdlib 3.13.2) erl_eval.erl:678: :erl_eval.do_apply/6

Process.alive?(parent_pid)
# => true

Ez a viselkedés megváltoztatható, ha a folyamatokat összekapcsoljuk egymással. Ha két folyamat össze van kapcsolva, az egyik folyamat hibája átterjed a másikra. Az összekapcsolás kétirányú.

parent_pid =
  spawn(fn ->
    spawn_link(fn -> raise "oops" end)

    receive do
      message ->
        IO.inspect(message, label: "received message")
    end
  end)

# => 20:05:34.125 [error] Process #PID<0.171.0> raised an exception
#    ** (RuntimeError) oops
#    (stdlib 3.13.2) erl_eval.erl:678: :erl_eval.do_apply/6

Process.alive?(parent_pid)
# => false

A folyamatokat elindíthatod már eleve a hívó folyamathoz kapcsolva is a spawn_link/1 segítségével, ami atomi művelet, vagy később is összekapcsolhatod őket a Process.link/1 hívással.

A Process.info/1 segítségével megnézheted, mely folyamatok vannak éppen egy adott folyamathoz kapcsolva (és futnak még).

pid = spawn_link(fn -> :timer.sleep(50_000) end)
# => #PID<0.126.0>

self()
|> Process.info()
|> Keyword.get(:links)

# => [#PID<0.126.0>]

A folyamatok összekapcsolása akkor lehet hasznos, ha párhuzamosított munkát végzel, és egy munkarészt nem érdemes folytatni, ha egy másik nem tud befejeződni.

Kilépések elkapása

Az összekapcsolás folyamatok felügyeletére is használható. Ha egy folyamat elkapja a kilépéseket, nem omlik össze, amikor egy vele összekapcsolt folyamat összeomlik. Helyette üzenetet kap az összeomlásról. Így szépen kezelheti az összeomlást, például újraindíthatja az összeomlott folyamatot.

Egy folyamat beállítható úgy, hogy elkapja a kilépéseket, ha meghívod a Process.flag(:trap_exit, true) hívást. Vedd figyelembe, hogy a Process.flag/2 a flag régi értékét adja vissza, nem az újat.

A flag aktuális értékét a Process.info/1 segítségével ellenőrizheted.

pid
|> Process.info()
|> Keyword.get(:trap_exit)

# => false

Az az üzenet, amelyet a folyamat kap, ha egy összekapcsolt folyamat összeomlik, a {:EXIT, from, reason} mintára illeszkedik, ahol a from egy PID. Ha a reason bármi más, mint a :normal atom, az azt jelenti, hogy a folyamat összeomlott, vagy erőszakkal leállították.

parent_pid =
  spawn(fn ->
    Process.flag(:trap_exit, true)

    spawn_link(fn -> raise "oops" end)

    receive do
      message ->
        IO.inspect(message, label: "received message")

        # do something else,
        # to demonstrate that the process stays alive
        :timer.sleep(50_000)
    end
  end)

# => 20:05:34.125 [error] Process #PID<0.295.0> raised an exception
#    ** (RuntimeError) oops
#    (stdlib 3.13.2) erl_eval.erl:678: :erl_eval.do_apply/6

# received message: {:EXIT, #PID<0.295.0>,
#   {%RuntimeError{message: "oops"},
#     [{:erl_eval, :do_apply, 6, [file: 'erl_eval.erl', line: 678]}]}}

Process.alive?(parent_pid)
# => true

Vedd figyelembe, hogy a kilépések elkapása miatt a folyamatot a vele összekapcsolt folyamatok összes összeomlása sem érinti, és a kilépési üzenetek felgyűlhetnek a folyamat postaládájában, ha nem olvassák el őket. Ezért tartsd számon az összes olyan folyamatot, amely egy kilépéseket elkapó folyamathoz van kapcsolva. A kilépéseket elkapó folyamatok általában csak más folyamatok felügyeletéért felelősek, és mással nem foglalkoznak.

A gyakorlatban egy felügyelő folyamatot nem neked kell a nulláról megvalósítanod. Az Elixir egy absztrakciót kínál erre a funkcióra a Supervisor viselkedés formájában.

A folyamatok körüli egyéb absztrakciók, például az Agent, a GenServer vagy a Task, kétféle módon indíthatók el: start vagy start_link hívással.

Szerkesztés GitHubon A hivatkozás új ablakban vagy lapon nyílik meg

Tanuld meg a(z) Kapcsolatok fogalmat