SlideShare ist ein Scribd-Unternehmen logo
1 von 48
Downloaden Sie, um offline zu lesen
GenServer in Action
 Elixir Club 11

Ternopil, 2018
Elixir Process
Process
iex(1)> spawn fn -> 1 + 1 end
#PID<0.90.0>
iex(2)> caller = self()
#PID<0.88.0>
iex(3)> spawn fn -> send caller, {:result, 1 + 1} end
#PID<0.93.0>
iex(4)> receive do
...(4)> {:result, result} -> result
...(4)> end
2
Process
iex(5)> spawn fn ->
...(5)> Process.sleep(6_000)
...(5)> send caller, {:result, 1 + 1}
...(5)> end
#PID<0.106.0>
iex(6)> receive do
...(6)> {:result, result} -> result
...(6)> end
⏳⏳⏳⏳⏳⌛
2
Process
iex(7)> spawn fn ->
...(7)> Process.sleep(666_666_666)
...(7)> send caller, {:result, 1 + 1}
...(7)> end
#PID<0.99.0>
iex(8)> spawn fn -> :nothing end
#PID<0.101.0>
iex(9)> spawn fn -> raise "error" end
#PID<0.103.0>
…
iex(11)> receive do
...(11)> {:result, result} -> result
...(11)> end
⏳⏳⏳⏳⏳⏳⏳⏳⏳⏳⏳⏳⏳⏳⏳⏳⏳⏳⏳⏳⏳⏳⏳⏳⏳⏳⏳⏳⏳⏳⏳⏳⏳⏳⏳⏳⏳⏳⏳
💤 💤 💤 CTRL+C
Process: timeout
iex(1)> caller = self()
#PID<0.88.0>
iex(2)> spawn fn ->
...(2)> Process.sleep(666_666_666)
...(2)> send caller, {:result, 1 + 1}
...(2)> end
#PID<0.94.0>
iex(3)> receive do
...(3)> {:result, result} -> {:ok, result}
...(3)> after
...(3)> 5_000 -> {:error, :timeout}
...(3)> end
⏳⏳⏳⏳⌛{:error, :timeout}
Process: message queue
iex(4)> send self(), {:message, 1}
iex(5)> send self(), {:another_message, 1}
iex(6)> send self(), {:message, 2}
iex(7)> send self(), {:another_message, 2}
iex(8)> send self(), {:message, 3}
iex(9)> send self(), {:another_message, 3}
iex(10)> Process.info(self(), :messages)
{:messages,
[
message: 1,
another_message: 1,
message: 2,
another_message: 2,
message: 3,
another_message: 3
]}
Process: message queue
{:messages,
[
message: 1,
another_message: 10,
message: 2,
another_message: 20,
message: 3,
another_message: 30
]}
iex(11)> receive do {:another_message, n} -> n end
10
iex(12)> receive do {:another_message, n} -> n end
20
iex(13)> Process.info(self(), :messages)
{:messages, [message: 1, message: 2, message: 3, another_message: 30]}
iex(14)> receive do {:message, n} -> n end
1
iex(15)> Process.info(self(), :messages)
{:messages, [message: 2, message: 3, another_message: 30]}
iex(16)> receive do {:something, n} -> n after 0 -> :no_matching_message end
:no_matching_message
When to use
processes?
Concurrent Tasks
Task.async / Task.await
ex(17)> task = Task.async(fn -> 1 + 1 end)
%Task{
owner: #PID<0.88.0>,
pid: #PID<0.106.0>,
ref: #Reference<0.1183799544.2034761732.30152>
}
iex(18)> Task.await(task)
2
Concurrent Tasks
Task.async / Task.await
iex(19)> tasks = Enum.map(1..10, &Task.async(fn ->
...(19)> Process.sleep(3_000)
...(19)> &1 * 100
...(19)> end))
[…]
iex(20)> Process.sleep(5_000)
:ok
iex(21)> Enum.map(tasks, &Task.await(&1))
[100, 200, 300, 400, 500, 600, 700, 800, 900, 1000]
Concurrent Tasks
Task.await timeout
await(task, timeout  5000)
…
A timeout, in milliseconds, can be given with default value
of 5000. If the timeout is exceeded, then the current
process will exit.
…
iex(22)> Task.async(fn -> Process.sleep(6_000) end) |> Task.await()
** (exit) exited in: Task.await(%Task{owner: #PID<0.88.0>, pid:
#PID<0.156.0>, ref: #Reference<0.891801449.431751175.151026>}, 5000)
** (EXIT) time out
(elixir) lib/task.ex:501: Task.await/2
Storing state
defmodule Storage do
def recursive(state) do
receive do
{:add, caller_pid, value} ->
new_state = state + value
send(caller_pid, {:result, new_state})
recursive(new_state)
end
end
end
iex(2)> storage_pid = spawn(fn -> Storage.recursive(0) end)
iex(3)> send(storage_pid, {:add, self(), 2})
iex(4)> send(storage_pid, {:add, self(), 2})
iex(5)> send(storage_pid, {:add, self(), 2})
iex(6)> flush()
{:result, 2}
{:result, 4}
{:result, 6}
Storing state
Agent
iex(7)> {:ok, pid} = Agent.start_link(fn -> 0 end)
{:ok, #PID<0.101.0>}
iex(8)> Agent.update(pid, fn state -> state + 1 end)
:ok
iex(9)> Agent.get(pid, fn state -> state end)
1
update(agent, fun, timeout  5000)
get(agent, module, fun, args, timeout  5000)
GenServer
GenServer
A behaviour module for implementing the server of a client-
server relation.

A GenServer is a process like any other Elixir process and it
can be used to keep state, execute code asynchronously
and so on. 
GenServer
defmodule Stack do
use GenServer
# Client
def start_link(default) do
GenServer.start_link(__MODULE__, default)
end
def push(pid, item) do
GenServer.cast(pid, {:push, item})
end
def pop(pid) do
GenServer.call(pid, :pop)
end
# Server (callbacks)
def handle_call(:pop, _from, [h | t]) do
{:reply, h, t}
end
def handle_cast({:push, item}, state) do
{:noreply, [item | state]}
end
end
GenServer
defmodule Stack do
use GenServer
# Client
def start_link(default) do
GenServer.start_link(__MODULE__, default)
end
def push(pid, item) do
GenServer.cast(pid, {:push, item})
end
def pop(pid) do
GenServer.call(pid, :pop)
end
# Server (callbacks)
def handle_call(:pop, _from, [h | t]) do
{:reply, h, t}
end
def handle_cast({:push, item}, state) do
{:noreply, [item | state]}
end
end
Executed in caller process
GenServer
defmodule Stack do
use GenServer
# Client
def start_link(default) do
GenServer.start_link(__MODULE__, default)
end
def push(pid, item) do
GenServer.cast(pid, {:push, item})
end
def pop(pid) do
GenServer.call(pid, :pop)
end
# Server (callbacks)
def handle_call(:pop, _from, [h | t]) do
{:reply, h, t}
end
def handle_cast({:push, item}, state) do
{:noreply, [item | state]}
end
end
Executed in server process
GenServer: timeout
call(server, request, timeout  5000)
def push(pid, item) do
GenServer.cast(pid, {:push, item})
end
def pop(pid) do
GenServer.call(pid, :pop)
end
# Server (callbacks)
@impl true
def handle_call(:pop, _from, [h | t]) do
Process.sleep(30_000)
{:reply, h, t}
end
@impl true
def handle_cast({:push, item}, state) do
{:noreply, [item | state]}
end
Executed in caller process
Executed in server process
GenServer: timeout
iex(2)> {:ok, pid} = Stack.start_link([])
{:ok, #PID<0.95.0>}
iex(3)> Enum.each(1..5, &Stack.push(pid, &1))
:ok
ex(4)> Stack.pop(pid)
** (exit) exited in: GenServer.call(#PID<0.95.0>, :pop, 5000)
** (EXIT) time out
(elixir) lib/gen_server.ex:836: GenServer.call/3
iex(4)> Stack.pop(pid)
** (exit) exited in: GenServer.call(#PID<0.95.0>, :pop, 5000)
** (EXIT) time out
(elixir) lib/gen_server.ex:836: GenServer.call/3
iex(4)> Stack.pop(pid)
** (exit) exited in: GenServer.call(#PID<0.95.0>, :pop, 5000)
** (EXIT) time out
(elixir) lib/gen_server.ex:836: GenServer.call/3
iex(4)> Stack.pop(pid)
** (exit) exited in: GenServer.call(#PID<0.95.0>, :pop, 5000)
** (EXIT) time out
(elixir) lib/gen_server.ex:836: GenServer.call/3
iex(4)> Process.info(pid, :messages)
{:messages,
[
{:"$gen_call", {#PID<0.88.0>, #Reference<0.3022523149.3093823489.83754>},
:pop},
{:"$gen_call", {#PID<0.88.0>, #Reference<0.3022523149.3093823489.83774>},
:pop},
{:"$gen_call", {#PID<0.88.0>, #Reference<0.3022523149.3093823489.83794>},
:pop}
]}
Executed in caller process
Executed in server process
GenServer: timeout
ex(5)> Process.info(pid, :messages)
{:messages,
[
{:"$gen_call", {#PID<0.88.0>,
#Reference<0.3022523149.3093823489.83794>},
:pop}
]}
ex(6)> Process.info(pid, :messages)
{:messages, []}
iex(7)> flush()
{#Reference<0.3022523149.3093823489.83730>, 5}
{#Reference<0.3022523149.3093823489.83754>, 4}
{#Reference<0.3022523149.3093823489.83774>, 3}
{#Reference<0.3022523149.3093823489.83794>, 2}
:ok
Digital Signature
Microservice
Digital Signature Microservice
• Microservice - part of the Ukrainian eHealth system
infrastructure

• Digital signature validation 

• Ukrainian standard DSTU 4145-2002

• Integration with proprietary C library via NIF
Digital Signature Microservice
Digital Signature
Microservice
NIF
Proprietary
DSTU
4145-2002
LIB
Digitally signed
content
< 5s
Decoded content
Signer info
Signature validation
Certificates
OSCP Server
{:ok, result} =
DigitalSignatureLib.processPKCS7Data(data, certs, true)
result ==
%{
content: "{"hello": "world"}",
is_valid: true,
signer: %{
common_name: "XXX YYY ZZZ",
country_name: "UA",
drfo: "1234567890",
edrpou: "",
given_name: "XX YY",
locality_name: "М. КИЇВ",
organization_name: "ФІЗИЧНА ОСОБА",
organizational_unit_name: "",
state_or_province_name: "",
surname: "XX",
title: ""
},
validation_error_message: ""
}
Sounds easy?
Digital Signature Microservice
DigitalSignatureLib.processPKCS7Data(…)
DigitalSignatureLib.processPKCS7Data(…)
DigitalSignatureLib.processPKCS7Data(…)
DigitalSignatureLib.processPKCS7Data(…)
Elixir Process
Elixir Process
Elixir Process
Elixir Process
Incoming Requests
200 OK
200 OK
200 OK
200 OK
Responses
Problem 1: concurrency
tasks =
Enum.map(1..25, fn _ ->
Task.async(fn ->
DigitalSignatureLib.processPKCS7Data(data, certs, true)
end)
end)
Enum.map(tasks, fn task ->
{:ok, result} = Task.await(task, 30000)
IO.inspect(result)
end)
%{
content: ***
}
%{
content: ***
}
%{
content: ***
}
%{
content: ***
}
*** Error in `/usr/local/lib/erlang/erts-9.3.3/bin/beam.smp': double free or corruption (fasttop): 0x00007f88e401d060 ***
======= Backtrace: =========
/lib/x86_64-linux-gnu/libc.so.6(+0x70bfb)[0x7f8962452bfb]
/lib/x86_64-linux-gnu/libc.so.6(+0x76fc6)[0x7f8962458fc6]
/lib/x86_64-linux-gnu/libc.so.6(+0x7780e)[0x7f896245980e]
/usr/local/lib/libUACryptoQ.so.1(_ZN9DataBlockaSERKS_+0x3c)[0x7f88a7bd785c]
/usr/local/lib/libUACryptoQ.so.1(_ZN4DataaSERKS_+0x11)[0x7f88a7bd6771]
/usr/local/lib/libUACryptoQ.so.1(_ZN7DataSet3NewERK4Data+0x3c)[0x7f88a7bd81cc]
/usr/local/lib/libUACryptoQ.so.1(_ZNK3UAC16ObjectIdentifier10EncodeBodyEv+0x1fc)[0x7f88a7bf238c]
/usr/local/lib/libUACryptoQ.so.1(_ZNK3UAC5Token6EncodeEv+0x46)[0x7f88a7bef236]
/usr/local/lib/libUACryptoQ.so.1(_ZNK3UAC11ObjectToken10EncodeBodyEv+0x17)[0x7f88a7bef3c7]
/usr/local/lib/libUACryptoQ.so.1(_ZNK3UAC5Token6EncodeEv+0x46)[0x7f88a7bef236]
/usr/local/lib/libUACryptoQ.so.1(_ZNK3UAC11Constructed10EncodeBodyEv+0x45)[0x7f88a7be97d5]
/usr/local/lib/libUACryptoQ.so.1(_ZNK3UAC11Constructed6EncodeEv+0x39)[0x7f88a7bec089]
/usr/local/lib/libUACryptoQ.so.1(_ZNK3UAC11Constructed10EncodeBodyEv+0x45)[0x7f88a7be97d5]
/usr/local/lib/libUACryptoQ.so.1(_ZNK3UAC11Constructed6EncodeEv+0x39)[0x7f88a7bec089]
/usr/local/lib/libUACryptoQ.so.1(_ZNK3UAC10CMSContent6EncodeEv+0x95)[0x7f88a7c0a2d5]
/usr/local/lib/libUACryptoQ.so.1(_ZNK3UAC11ObjectToken10EncodeBodyEv+0x3a)[0x7f88a7bef3ea]
/usr/local/lib/libUACryptoQ.so.1(_ZNK3UAC5Token6EncodeEv+0x46)[0x7f88a7bef236]
/usr/local/lib/libUACryptoQ.so.1(_ZNK3UAC11Constructed10EncodeBodyEv+0x45)[0x7f88a7be97d5]
/usr/local/lib/libUACryptoQ.so.1(_ZNK3UAC11Constructed6EncodeEv+0x39)[0x7f88a7bec089]
/usr/local/lib/libUACryptoQ.so.1(_ZNK3UAC10CMSContent6EncodeEv+0x95)[0x7f88a7c0a2d5]
/usr/local/lib/libUACryptoQ.so.1(_ZNK3UAC11ObjectToken10EncodeBodyEv+0x3a)[0x7f88a7bef3ea]
/usr/local/lib/libUACryptoQ.so.1(_ZNK3UAC5Token6EncodeEv+0x46)[0x7f88a7bef236]
/usr/local/lib/libUACryptoQ.so.1(_ZNK3UAC11Constructed10EncodeBodyEv+0x45)[0x7f88a7be97d5]
/usr/local/lib/libUACryptoQ.so.1(_ZNK3UAC11Constructed6EncodeEv+0x39)[0x7f88a7bec089]
/usr/local/lib/libUACryptoQ.so.1(_ZNK3UAC17ObjectWithContent6EncodeEv+0x1b)[0x7f88a7be946b]
/usr/local/lib/libUACryptoQ.so.1(_ZNK3UAC11ObjectToken10EncodeBodyEv+0x3a)[0x7f88a7bef3ea]
/usr/local/lib/libUACryptoQ.so.1(_ZNK3UAC5Token6EncodeEv+0x46)[0x7f88a7bef236]
/usr/local/lib/libUACryptoQ.so.1(_ZNK3UAC11Constructed10EncodeBodyEv+0x45)[0x7f88a7be97d5]
/usr/local/lib/libUACryptoQ.so.1(_ZNK3UAC11Constructed6EncodeEv+0x39)[0x7f88a7bec089]
/usr/local/lib/libUACryptoQ.so.1(_ZN3UAC13CMSSignedData15VerifySignatureEPNS_11CertificateEP11_UAC_STREAM+0x9f5)[0x7f88a7c12965]
/usr/local/lib/libUACryptoQ.so.1(UAC_SignedDataVerify+0x2ba)[0x7f88a7c4ff1a]
/home/digital_signature.lib/_build/test/lib/digital_signature_lib/priv/digital_signature_lib_nif.so(Check+0x3c5)[0x7f891c0fc7f5]
/home/digital_signature.lib/_build/test/lib/digital_signature_lib/priv/digital_signature_lib_nif.so(+0x2bac)[0x7f891c0fbbac]
/usr/local/lib/erlang/erts-9.3.3/bin/beam.smp(erts_call_dirty_nif+0x19c)[0x5ce04c]
/usr/local/lib/erlang/erts-9.3.3/bin/beam.smp(erts_dirty_process_main+0x209)[0x445949]
/usr/local/lib/erlang/erts-9.3.3/bin/beam.smp[0x4f4a4d]
/usr/local/lib/erlang/erts-9.3.3/bin/beam.smp[0x675985]
/lib/x86_64-linux-gnu/libpthread.so.0(+0x7494)[0x7f8962990494]
/lib/x86_64-linux-gnu/libc.so.6(clone+0x3f)[0x7f89624caacf]
======= Memory map: ========
00400000-0073b000 r-xp 00000000 08:01 2376229 /usr/local/lib/erlang/erts-9.3.3/bin/beam.smp
0093a000-0093b000 r--p 0033a000 08:01 2376229 /usr/local/lib/erlang/erts-9.3.3/bin/beam.smp
0093b000-00956000 rw-p 0033b000 08:01 2376229 /usr/local/lib/erlang/erts-9.3.3/bin/beam.smp
00956000-0097d000 rw-p 00000000 00:00 0
0231e000-02349000 rw-p 00000000 00:00 0 [heap]
Problem 1 solution: Gen Server
...
use GenServer
# Callbacks
...
def handle_call({:process_signed_content, signed_content, check}, _from,
{certs_cache_ttl, certs}) do
check = unless is_boolean(check), do: true
processing_result = do_process_signed_content(signed_content, certs, check,
SignedData.new())
{:reply, processing_result, {certs_cache_ttl, certs}}
end
...
# Client
...
def process_signed_content(signed_content, check) do
GenServer.call(__MODULE__, {:process_signed_content, signed_content, check})
end
Problem 1 solution: Gen Server
NifService (GenServer)
NifService.process_signed_content(…)
NifService.process_signed_content(…)
NifService.process_signed_content(…)
NifService.process_signed_content(…)
Requests
Message queue
DigitalSignatureLib.processPKCS7Data(…)
Responses
Problem 2: timeouts
NifService (GenServer)
Multiple concurrent
requests (processes)
2s
2s
2s
2s
Message queue
Sequential
responses
200 OK
2s
200 OK
4s
500 Error
5s
500 Error
5s
call(server, request, timeout  5000)
** (EXIT) time out
** (EXIT) time out
Problem 2: timeouts
NifService (GenServer)
Multiple concurrent
requests (processes)
2s
2s
Message queue
Sequential
responses
call(server, request, timeout  5000)
2s
2s
500 Error
5s
500 Error
5s
Problem 2 solution: architecture
DS
DS
DS
DS DS
DS
DS
DS
Load
Balancer
Reduce pressure on individual MS
Problem 2 solution: catch Exit
def process_signed_content(signed_content, check) do
gen_server_timeout =
Confex.fetch_env(:digital_signature_api,
:nif_service_timeout)
try do
GenServer.call(__MODULE__, {:process_signed_content,
signed_content, check}, gen_server_timeout)
catch
:exit, {:timeout, error} ->
{:error, {:nif_service_timeout, error}}
end
end
424 Failed Dependency
Problem 3: message queue
NifService (GenServer)
Processed requests
2s
2s
2s
2s
Message queue
Sequential
responses
200 OK
2s
200 OK
4s
424
5s
424
5s
2s
2s
Expired requests
New requests
Problem 3 solution: pass
message expiration time
...
# Callbacks
def handle_call({:process_signed_content, signed_content, check, message_exp_time}, _from, certs_cache_ttl, certs})
do
processing_result =
if NaiveDateTime.diff(message_exp_time, NaiveDateTime.utc_now(), :millisecond) > 250 do
check = unless is_boolean(check), do: true
do_process_signed_content(signed_content, certs, check, SignedData.new())
else
{:error, {:nif_service_timeout, "messaqe queue timeout"}}
end
{:reply, processing_result, {certs_cache_ttl, certs}}
End
...
# Client
def process_signed_content(signed_content, check) do
gen_server_timeout = Confex.fetch_env!(:digital_signature_api, :nif_service_timeout)
message_exp_time = NaiveDateTime.add(NaiveDateTime.utc_now(), gen_server_timeout, :millisecond)
try do
GenServer.call(__MODULE__, {:process_signed_content, signed_content, check, message_exp_time}, gen_server_timeout)
catch
:exit, {:timeout, error} ->
{:error, {:nif_service_timeout, error}}
end
end
...
Problem 3 solution: pass
message expiration time
NifService (GenServer)
…
Expired
Expired
Within threshold
Message queue
…
Problem 3 advanced solution:
QueueService
NifService
DigitalSignatureLib.
processPKCS7Data(…)
QueueService
:queue
Monitoring & Control
Memory management
Binary terms which are larger than 64 bytes are not stored in a process private
heap. 

They are called Refc Binary (Reference Counted Binary) and are stored in a
large Shared Heap which is accessible by all processes who have the pointer
of that Refc Binaries. 

That pointer is called ProcBin and is stored in a process private heap.

The GC for the shared heap is reference counting.

Collecting those Refc messages depends on collecting of all ProcBin objects
even ones that are inside the middleware process. 

Unfortunately because ProcBins are just a pointer hence they are so cheap
and it could take so long to happen a GC inside the middleware process.
NifService
Memory management
Shared Heap
Refc Binary
Refc Binary
Refc Binary
Requests Responses
ProcBin
ProcBin
ProcBin
ProcBin
ProcBin
ProcBin
ProcBin
ProcBin
ProcBin
GC
GC
GC
:erlang.garbage_collect(self())
Processes
Garbage Collect
...
# Callbacks
def init(certs_cache_ttl) do
certs = CertAPI.get_certs_map()
Process.send_after(self(), :refresh, certs_cache_ttl)
{:ok, {certs_cache_ttl, certs}}
end
...
def handle_info(:refresh, {certs_cache_ttl, _certs}) do
certs = CertAPI.get_certs_map()
# GC
:erlang.garbage_collect(self())
Process.send_after(self(), :refresh, certs_cache_ttl)
{:noreply, {certs_cache_ttl, certs}}
end
...
Garbage Collect
handle_call(request, from, state)
{:reply, reply, new_state, timeout() | :hibernate}
Hibernating a GenServer causes garbage collection and leaves
a continuous heap that minimises the memory used by the
process
Returning {:reply, reply, new_state, timeout} is similar to
{:reply, reply, new_state} except handle_info(:timeout,
new_state) will be called after timeout milliseconds if no
messages are received
Useful links
Saša Jurić "Elixir in Action, Second Edition”
https://www.manning.com/books/elixir-in-action-second-edition

Andrea Leopardi - Concurrent and Resilient Connections to Outside the
BEAM (ElixirConfEU 2016)
https://www.youtube.com/watch?time_continue=1884&v=U1Ry7STEFiY

GenServer call time-outs
https://cultivatehq.com/posts/genserver-call-timeouts/

Elixir Memory - Not Quite Free
https://stephenbussey.com/2018/05/09/elixir-memory-not-quite-free.html

Erlang Garbage Collection Details and Why It Matters
https://hamidreza-s.github.io/erlang%20garbage%20collection%20memory%20layout%20soft%20realtime/
2015/08/24/erlang-garbage-collection-details-and-why-it-matters.html
Thank You
Yurii Bodarev

https://github.com/ybod
Questions?

Weitere ähnliche Inhalte

Was ist angesagt?

The Ring programming language version 1.5.3 book - Part 19 of 194
The Ring programming language version 1.5.3 book - Part 19 of 194The Ring programming language version 1.5.3 book - Part 19 of 194
The Ring programming language version 1.5.3 book - Part 19 of 194Mahmoud Samir Fayed
 
The Ring programming language version 1.6 book - Part 71 of 189
The Ring programming language version 1.6 book - Part 71 of 189The Ring programming language version 1.6 book - Part 71 of 189
The Ring programming language version 1.6 book - Part 71 of 189Mahmoud Samir Fayed
 
The Ring programming language version 1.6 book - Part 55 of 189
The Ring programming language version 1.6 book - Part 55 of 189The Ring programming language version 1.6 book - Part 55 of 189
The Ring programming language version 1.6 book - Part 55 of 189Mahmoud Samir Fayed
 
JavaScript ∩ WebAssembly
JavaScript ∩ WebAssemblyJavaScript ∩ WebAssembly
JavaScript ∩ WebAssemblyTadeu Zagallo
 
The Ring programming language version 1.10 book - Part 89 of 212
The Ring programming language version 1.10 book - Part 89 of 212The Ring programming language version 1.10 book - Part 89 of 212
The Ring programming language version 1.10 book - Part 89 of 212Mahmoud Samir Fayed
 
The Ring programming language version 1.8 book - Part 84 of 202
The Ring programming language version 1.8 book - Part 84 of 202The Ring programming language version 1.8 book - Part 84 of 202
The Ring programming language version 1.8 book - Part 84 of 202Mahmoud Samir Fayed
 
The Ring programming language version 1.5.2 book - Part 26 of 181
The Ring programming language version 1.5.2 book - Part 26 of 181The Ring programming language version 1.5.2 book - Part 26 of 181
The Ring programming language version 1.5.2 book - Part 26 of 181Mahmoud Samir Fayed
 
Rのスコープとフレームと環境と
Rのスコープとフレームと環境とRのスコープとフレームと環境と
Rのスコープとフレームと環境とTakeshi Arabiki
 
Rデバッグあれこれ
RデバッグあれこれRデバッグあれこれ
RデバッグあれこれTakeshi Arabiki
 
The Ring programming language version 1.4 book - Part 18 of 30
The Ring programming language version 1.4 book - Part 18 of 30The Ring programming language version 1.4 book - Part 18 of 30
The Ring programming language version 1.4 book - Part 18 of 30Mahmoud Samir Fayed
 
QA Fest 2019. Saar Rachamim. Developing Tools, While Testing
QA Fest 2019. Saar Rachamim. Developing Tools, While TestingQA Fest 2019. Saar Rachamim. Developing Tools, While Testing
QA Fest 2019. Saar Rachamim. Developing Tools, While TestingQAFest
 
The Ring programming language version 1.9 book - Part 48 of 210
The Ring programming language version 1.9 book - Part 48 of 210The Ring programming language version 1.9 book - Part 48 of 210
The Ring programming language version 1.9 book - Part 48 of 210Mahmoud Samir Fayed
 
Dts x dicoding #2 memulai pemrograman kotlin
Dts x dicoding #2 memulai pemrograman kotlinDts x dicoding #2 memulai pemrograman kotlin
Dts x dicoding #2 memulai pemrograman kotlinAhmad Arif Faizin
 
The Ring programming language version 1.6 book - Part 15 of 189
The Ring programming language version 1.6 book - Part 15 of 189The Ring programming language version 1.6 book - Part 15 of 189
The Ring programming language version 1.6 book - Part 15 of 189Mahmoud Samir Fayed
 
The Ring programming language version 1.2 book - Part 16 of 84
The Ring programming language version 1.2 book - Part 16 of 84The Ring programming language version 1.2 book - Part 16 of 84
The Ring programming language version 1.2 book - Part 16 of 84Mahmoud Samir Fayed
 
The Ring programming language version 1.10 book - Part 94 of 212
The Ring programming language version 1.10 book - Part 94 of 212The Ring programming language version 1.10 book - Part 94 of 212
The Ring programming language version 1.10 book - Part 94 of 212Mahmoud Samir Fayed
 
The Ring programming language version 1.5.3 book - Part 25 of 184
The Ring programming language version 1.5.3 book - Part 25 of 184The Ring programming language version 1.5.3 book - Part 25 of 184
The Ring programming language version 1.5.3 book - Part 25 of 184Mahmoud Samir Fayed
 
The Ring programming language version 1.7 book - Part 16 of 196
The Ring programming language version 1.7 book - Part 16 of 196The Ring programming language version 1.7 book - Part 16 of 196
The Ring programming language version 1.7 book - Part 16 of 196Mahmoud Samir Fayed
 

Was ist angesagt? (20)

The Ring programming language version 1.5.3 book - Part 19 of 194
The Ring programming language version 1.5.3 book - Part 19 of 194The Ring programming language version 1.5.3 book - Part 19 of 194
The Ring programming language version 1.5.3 book - Part 19 of 194
 
The Ring programming language version 1.6 book - Part 71 of 189
The Ring programming language version 1.6 book - Part 71 of 189The Ring programming language version 1.6 book - Part 71 of 189
The Ring programming language version 1.6 book - Part 71 of 189
 
The Ring programming language version 1.6 book - Part 55 of 189
The Ring programming language version 1.6 book - Part 55 of 189The Ring programming language version 1.6 book - Part 55 of 189
The Ring programming language version 1.6 book - Part 55 of 189
 
JavaScript ∩ WebAssembly
JavaScript ∩ WebAssemblyJavaScript ∩ WebAssembly
JavaScript ∩ WebAssembly
 
The Ring programming language version 1.10 book - Part 89 of 212
The Ring programming language version 1.10 book - Part 89 of 212The Ring programming language version 1.10 book - Part 89 of 212
The Ring programming language version 1.10 book - Part 89 of 212
 
The Ring programming language version 1.8 book - Part 84 of 202
The Ring programming language version 1.8 book - Part 84 of 202The Ring programming language version 1.8 book - Part 84 of 202
The Ring programming language version 1.8 book - Part 84 of 202
 
Erlang/OTP in Riak
Erlang/OTP in RiakErlang/OTP in Riak
Erlang/OTP in Riak
 
The Ring programming language version 1.5.2 book - Part 26 of 181
The Ring programming language version 1.5.2 book - Part 26 of 181The Ring programming language version 1.5.2 book - Part 26 of 181
The Ring programming language version 1.5.2 book - Part 26 of 181
 
Rのスコープとフレームと環境と
Rのスコープとフレームと環境とRのスコープとフレームと環境と
Rのスコープとフレームと環境と
 
Rデバッグあれこれ
RデバッグあれこれRデバッグあれこれ
Rデバッグあれこれ
 
The Ring programming language version 1.4 book - Part 18 of 30
The Ring programming language version 1.4 book - Part 18 of 30The Ring programming language version 1.4 book - Part 18 of 30
The Ring programming language version 1.4 book - Part 18 of 30
 
QA Fest 2019. Saar Rachamim. Developing Tools, While Testing
QA Fest 2019. Saar Rachamim. Developing Tools, While TestingQA Fest 2019. Saar Rachamim. Developing Tools, While Testing
QA Fest 2019. Saar Rachamim. Developing Tools, While Testing
 
The Ring programming language version 1.9 book - Part 48 of 210
The Ring programming language version 1.9 book - Part 48 of 210The Ring programming language version 1.9 book - Part 48 of 210
The Ring programming language version 1.9 book - Part 48 of 210
 
C++ practical
C++ practicalC++ practical
C++ practical
 
Dts x dicoding #2 memulai pemrograman kotlin
Dts x dicoding #2 memulai pemrograman kotlinDts x dicoding #2 memulai pemrograman kotlin
Dts x dicoding #2 memulai pemrograman kotlin
 
The Ring programming language version 1.6 book - Part 15 of 189
The Ring programming language version 1.6 book - Part 15 of 189The Ring programming language version 1.6 book - Part 15 of 189
The Ring programming language version 1.6 book - Part 15 of 189
 
The Ring programming language version 1.2 book - Part 16 of 84
The Ring programming language version 1.2 book - Part 16 of 84The Ring programming language version 1.2 book - Part 16 of 84
The Ring programming language version 1.2 book - Part 16 of 84
 
The Ring programming language version 1.10 book - Part 94 of 212
The Ring programming language version 1.10 book - Part 94 of 212The Ring programming language version 1.10 book - Part 94 of 212
The Ring programming language version 1.10 book - Part 94 of 212
 
The Ring programming language version 1.5.3 book - Part 25 of 184
The Ring programming language version 1.5.3 book - Part 25 of 184The Ring programming language version 1.5.3 book - Part 25 of 184
The Ring programming language version 1.5.3 book - Part 25 of 184
 
The Ring programming language version 1.7 book - Part 16 of 196
The Ring programming language version 1.7 book - Part 16 of 196The Ring programming language version 1.7 book - Part 16 of 196
The Ring programming language version 1.7 book - Part 16 of 196
 

Ähnlich wie GenServer in Action – Yurii Bodarev

Elixir -Tolerância a Falhas para Adultos - GDG Campinas
Elixir  -Tolerância a Falhas para Adultos - GDG CampinasElixir  -Tolerância a Falhas para Adultos - GDG Campinas
Elixir -Tolerância a Falhas para Adultos - GDG CampinasFabio Akita
 
Introducción a Elixir
Introducción a ElixirIntroducción a Elixir
Introducción a ElixirSvet Ivantchev
 
Python profiling
Python profilingPython profiling
Python profilingdreampuf
 
شرح مقرر البرمجة 2 لغة جافا - الوحدة الثالثة
شرح مقرر البرمجة 2   لغة جافا - الوحدة الثالثةشرح مقرر البرمجة 2   لغة جافا - الوحدة الثالثة
شرح مقرر البرمجة 2 لغة جافا - الوحدة الثالثةجامعة القدس المفتوحة
 
«Gevent — быть или не быть?» Александр Мокров, Positive Technologies
«Gevent — быть или не быть?» Александр Мокров, Positive Technologies«Gevent — быть или не быть?» Александр Мокров, Positive Technologies
«Gevent — быть или не быть?» Александр Мокров, Positive Technologiesit-people
 
A deep dive into PEP-3156 and the new asyncio module
A deep dive into PEP-3156 and the new asyncio moduleA deep dive into PEP-3156 and the new asyncio module
A deep dive into PEP-3156 and the new asyncio moduleSaúl Ibarra Corretgé
 
Part 3-functions1-120315220356-phpapp01
Part 3-functions1-120315220356-phpapp01Part 3-functions1-120315220356-phpapp01
Part 3-functions1-120315220356-phpapp01Abdul Samee
 
Think Async: Asynchronous Patterns in NodeJS
Think Async: Asynchronous Patterns in NodeJSThink Async: Asynchronous Patterns in NodeJS
Think Async: Asynchronous Patterns in NodeJSAdam L Barrett
 
Promise: async programming hero
Promise: async programming heroPromise: async programming hero
Promise: async programming heroThe Software House
 
how to reuse code
how to reuse codehow to reuse code
how to reuse codejleed1
 
Java/Scala Lab: Анатолий Кметюк - Scala SubScript: Алгебра для реактивного пр...
Java/Scala Lab: Анатолий Кметюк - Scala SubScript: Алгебра для реактивного пр...Java/Scala Lab: Анатолий Кметюк - Scala SubScript: Алгебра для реактивного пр...
Java/Scala Lab: Анатолий Кметюк - Scala SubScript: Алгебра для реактивного пр...GeeksLab Odessa
 
Can you fix the errors- It isn't working when I try to run import s.pdf
Can you fix the errors- It isn't working when I try to run    import s.pdfCan you fix the errors- It isn't working when I try to run    import s.pdf
Can you fix the errors- It isn't working when I try to run import s.pdfaksachdevahosymills
 
FS2 for Fun and Profit
FS2 for Fun and ProfitFS2 for Fun and Profit
FS2 for Fun and ProfitAdil Akhter
 
JavaScript Advanced - Useful methods to power up your code
JavaScript Advanced - Useful methods to power up your codeJavaScript Advanced - Useful methods to power up your code
JavaScript Advanced - Useful methods to power up your codeLaurence Svekis ✔
 

Ähnlich wie GenServer in Action – Yurii Bodarev (20)

Gevent rabbit rpc
Gevent rabbit rpcGevent rabbit rpc
Gevent rabbit rpc
 
Elixir -Tolerância a Falhas para Adultos - GDG Campinas
Elixir  -Tolerância a Falhas para Adultos - GDG CampinasElixir  -Tolerância a Falhas para Adultos - GDG Campinas
Elixir -Tolerância a Falhas para Adultos - GDG Campinas
 
Introducción a Elixir
Introducción a ElixirIntroducción a Elixir
Introducción a Elixir
 
Python profiling
Python profilingPython profiling
Python profiling
 
شرح مقرر البرمجة 2 لغة جافا - الوحدة الثالثة
شرح مقرر البرمجة 2   لغة جافا - الوحدة الثالثةشرح مقرر البرمجة 2   لغة جافا - الوحدة الثالثة
شرح مقرر البرمجة 2 لغة جافا - الوحدة الثالثة
 
Gevent be or not to be
Gevent be or not to beGevent be or not to be
Gevent be or not to be
 
«Gevent — быть или не быть?» Александр Мокров, Positive Technologies
«Gevent — быть или не быть?» Александр Мокров, Positive Technologies«Gevent — быть или не быть?» Александр Мокров, Positive Technologies
«Gevent — быть или не быть?» Александр Мокров, Positive Technologies
 
Django Celery
Django Celery Django Celery
Django Celery
 
A deep dive into PEP-3156 and the new asyncio module
A deep dive into PEP-3156 and the new asyncio moduleA deep dive into PEP-3156 and the new asyncio module
A deep dive into PEP-3156 and the new asyncio module
 
Unix Programs
Unix ProgramsUnix Programs
Unix Programs
 
Part 3-functions1-120315220356-phpapp01
Part 3-functions1-120315220356-phpapp01Part 3-functions1-120315220356-phpapp01
Part 3-functions1-120315220356-phpapp01
 
Think Async: Asynchronous Patterns in NodeJS
Think Async: Asynchronous Patterns in NodeJSThink Async: Asynchronous Patterns in NodeJS
Think Async: Asynchronous Patterns in NodeJS
 
Promise: async programming hero
Promise: async programming heroPromise: async programming hero
Promise: async programming hero
 
PythonOOP
PythonOOPPythonOOP
PythonOOP
 
how to reuse code
how to reuse codehow to reuse code
how to reuse code
 
Java/Scala Lab: Анатолий Кметюк - Scala SubScript: Алгебра для реактивного пр...
Java/Scala Lab: Анатолий Кметюк - Scala SubScript: Алгебра для реактивного пр...Java/Scala Lab: Анатолий Кметюк - Scala SubScript: Алгебра для реактивного пр...
Java/Scala Lab: Анатолий Кметюк - Scala SubScript: Алгебра для реактивного пр...
 
Can you fix the errors- It isn't working when I try to run import s.pdf
Can you fix the errors- It isn't working when I try to run    import s.pdfCan you fix the errors- It isn't working when I try to run    import s.pdf
Can you fix the errors- It isn't working when I try to run import s.pdf
 
FS2 for Fun and Profit
FS2 for Fun and ProfitFS2 for Fun and Profit
FS2 for Fun and Profit
 
JavaScript Advanced - Useful methods to power up your code
JavaScript Advanced - Useful methods to power up your codeJavaScript Advanced - Useful methods to power up your code
JavaScript Advanced - Useful methods to power up your code
 
Elixir and OTP Apps introduction
Elixir and OTP Apps introductionElixir and OTP Apps introduction
Elixir and OTP Apps introduction
 

Mehr von Elixir Club

Kubernetes + Docker + Elixir - Alexei Sholik, Andrew Dryga | Elixir Club Ukraine
Kubernetes + Docker + Elixir - Alexei Sholik, Andrew Dryga | Elixir Club UkraineKubernetes + Docker + Elixir - Alexei Sholik, Andrew Dryga | Elixir Club Ukraine
Kubernetes + Docker + Elixir - Alexei Sholik, Andrew Dryga | Elixir Club UkraineElixir Club
 
Integrating 3rd parties with Ecto - Eduardo Aguilera | Elixir Club Ukraine
Integrating 3rd parties with Ecto -  Eduardo Aguilera | Elixir Club UkraineIntegrating 3rd parties with Ecto -  Eduardo Aguilera | Elixir Club Ukraine
Integrating 3rd parties with Ecto - Eduardo Aguilera | Elixir Club UkraineElixir Club
 
— An async template - Oleksandr Khokhlov | Elixir Club Ukraine
— An async template  -  Oleksandr Khokhlov | Elixir Club Ukraine— An async template  -  Oleksandr Khokhlov | Elixir Club Ukraine
— An async template - Oleksandr Khokhlov | Elixir Club UkraineElixir Club
 
BEAM architecture handbook - Andrea Leopardi | Elixir Club Ukraine
BEAM architecture handbook - Andrea Leopardi  | Elixir Club UkraineBEAM architecture handbook - Andrea Leopardi  | Elixir Club Ukraine
BEAM architecture handbook - Andrea Leopardi | Elixir Club UkraineElixir Club
 
You ain't gonna need write a GenServer - Ulisses Almeida | Elixir Club Ukraine
You ain't gonna need write a GenServer - Ulisses Almeida  | Elixir Club UkraineYou ain't gonna need write a GenServer - Ulisses Almeida  | Elixir Club Ukraine
You ain't gonna need write a GenServer - Ulisses Almeida | Elixir Club UkraineElixir Club
 
— Knock, knock — An async templates — Who’s there? - Alexander Khokhlov | ...
 — Knock, knock — An async templates — Who’s there? - Alexander Khokhlov  |  ... — Knock, knock — An async templates — Who’s there? - Alexander Khokhlov  |  ...
— Knock, knock — An async templates — Who’s there? - Alexander Khokhlov | ...Elixir Club
 
Performance measurement methodology — Maksym Pugach | Elixir Evening Club 3
Performance measurement methodology — Maksym Pugach | Elixir Evening Club 3Performance measurement methodology — Maksym Pugach | Elixir Evening Club 3
Performance measurement methodology — Maksym Pugach | Elixir Evening Club 3Elixir Club
 
Erlang cluster. How is it? Production experience. — Valerii Vasylkov | Elixi...
Erlang cluster. How is it? Production experience. —  Valerii Vasylkov | Elixi...Erlang cluster. How is it? Production experience. —  Valerii Vasylkov | Elixi...
Erlang cluster. How is it? Production experience. — Valerii Vasylkov | Elixi...Elixir Club
 
Promo Phx4RailsDevs - Volodya Sveredyuk
Promo Phx4RailsDevs - Volodya SveredyukPromo Phx4RailsDevs - Volodya Sveredyuk
Promo Phx4RailsDevs - Volodya SveredyukElixir Club
 
Web of today — Alexander Khokhlov
Web of today —  Alexander KhokhlovWeb of today —  Alexander Khokhlov
Web of today — Alexander KhokhlovElixir Club
 
ElixirConf Eu 2018, what was it like? – Eugene Pirogov
ElixirConf Eu 2018, what was it like? – Eugene PirogovElixirConf Eu 2018, what was it like? – Eugene Pirogov
ElixirConf Eu 2018, what was it like? – Eugene PirogovElixir Club
 
Implementing GraphQL API in Elixir – Victor Deryagin
Implementing GraphQL API in Elixir – Victor DeryaginImplementing GraphQL API in Elixir – Victor Deryagin
Implementing GraphQL API in Elixir – Victor DeryaginElixir Club
 
WebPerformance: Why and How? – Stefan Wintermeyer
WebPerformance: Why and How? – Stefan WintermeyerWebPerformance: Why and How? – Stefan Wintermeyer
WebPerformance: Why and How? – Stefan WintermeyerElixir Club
 
Russian Doll Paradox: Elixir Web without Phoenix - Alex Rozumii
Russian Doll Paradox: Elixir Web without Phoenix - Alex RozumiiRussian Doll Paradox: Elixir Web without Phoenix - Alex Rozumii
Russian Doll Paradox: Elixir Web without Phoenix - Alex RozumiiElixir Club
 
Practical Fault Tolerance in Elixir - Alexei Sholik
Practical Fault Tolerance in Elixir - Alexei SholikPractical Fault Tolerance in Elixir - Alexei Sholik
Practical Fault Tolerance in Elixir - Alexei SholikElixir Club
 
Phoenix and beyond: Things we do with Elixir - Alexander Khokhlov
Phoenix and beyond: Things we do with Elixir - Alexander KhokhlovPhoenix and beyond: Things we do with Elixir - Alexander Khokhlov
Phoenix and beyond: Things we do with Elixir - Alexander KhokhlovElixir Club
 
Monads are just monoids in the category of endofunctors - Ike Kurghinyan
Monads are just monoids in the category of endofunctors - Ike KurghinyanMonads are just monoids in the category of endofunctors - Ike Kurghinyan
Monads are just monoids in the category of endofunctors - Ike KurghinyanElixir Club
 
Craft effective API with GraphQL and Absinthe - Ihor Katkov
Craft effective API with GraphQL and Absinthe - Ihor KatkovCraft effective API with GraphQL and Absinthe - Ihor Katkov
Craft effective API with GraphQL and Absinthe - Ihor KatkovElixir Club
 
Elixir in a service of government - Alex Troush
Elixir in a service of government - Alex TroushElixir in a service of government - Alex Troush
Elixir in a service of government - Alex TroushElixir Club
 
Pattern matching in Elixir by example - Alexander Khokhlov
Pattern matching in Elixir by example - Alexander KhokhlovPattern matching in Elixir by example - Alexander Khokhlov
Pattern matching in Elixir by example - Alexander KhokhlovElixir Club
 

Mehr von Elixir Club (20)

Kubernetes + Docker + Elixir - Alexei Sholik, Andrew Dryga | Elixir Club Ukraine
Kubernetes + Docker + Elixir - Alexei Sholik, Andrew Dryga | Elixir Club UkraineKubernetes + Docker + Elixir - Alexei Sholik, Andrew Dryga | Elixir Club Ukraine
Kubernetes + Docker + Elixir - Alexei Sholik, Andrew Dryga | Elixir Club Ukraine
 
Integrating 3rd parties with Ecto - Eduardo Aguilera | Elixir Club Ukraine
Integrating 3rd parties with Ecto -  Eduardo Aguilera | Elixir Club UkraineIntegrating 3rd parties with Ecto -  Eduardo Aguilera | Elixir Club Ukraine
Integrating 3rd parties with Ecto - Eduardo Aguilera | Elixir Club Ukraine
 
— An async template - Oleksandr Khokhlov | Elixir Club Ukraine
— An async template  -  Oleksandr Khokhlov | Elixir Club Ukraine— An async template  -  Oleksandr Khokhlov | Elixir Club Ukraine
— An async template - Oleksandr Khokhlov | Elixir Club Ukraine
 
BEAM architecture handbook - Andrea Leopardi | Elixir Club Ukraine
BEAM architecture handbook - Andrea Leopardi  | Elixir Club UkraineBEAM architecture handbook - Andrea Leopardi  | Elixir Club Ukraine
BEAM architecture handbook - Andrea Leopardi | Elixir Club Ukraine
 
You ain't gonna need write a GenServer - Ulisses Almeida | Elixir Club Ukraine
You ain't gonna need write a GenServer - Ulisses Almeida  | Elixir Club UkraineYou ain't gonna need write a GenServer - Ulisses Almeida  | Elixir Club Ukraine
You ain't gonna need write a GenServer - Ulisses Almeida | Elixir Club Ukraine
 
— Knock, knock — An async templates — Who’s there? - Alexander Khokhlov | ...
 — Knock, knock — An async templates — Who’s there? - Alexander Khokhlov  |  ... — Knock, knock — An async templates — Who’s there? - Alexander Khokhlov  |  ...
— Knock, knock — An async templates — Who’s there? - Alexander Khokhlov | ...
 
Performance measurement methodology — Maksym Pugach | Elixir Evening Club 3
Performance measurement methodology — Maksym Pugach | Elixir Evening Club 3Performance measurement methodology — Maksym Pugach | Elixir Evening Club 3
Performance measurement methodology — Maksym Pugach | Elixir Evening Club 3
 
Erlang cluster. How is it? Production experience. — Valerii Vasylkov | Elixi...
Erlang cluster. How is it? Production experience. —  Valerii Vasylkov | Elixi...Erlang cluster. How is it? Production experience. —  Valerii Vasylkov | Elixi...
Erlang cluster. How is it? Production experience. — Valerii Vasylkov | Elixi...
 
Promo Phx4RailsDevs - Volodya Sveredyuk
Promo Phx4RailsDevs - Volodya SveredyukPromo Phx4RailsDevs - Volodya Sveredyuk
Promo Phx4RailsDevs - Volodya Sveredyuk
 
Web of today — Alexander Khokhlov
Web of today —  Alexander KhokhlovWeb of today —  Alexander Khokhlov
Web of today — Alexander Khokhlov
 
ElixirConf Eu 2018, what was it like? – Eugene Pirogov
ElixirConf Eu 2018, what was it like? – Eugene PirogovElixirConf Eu 2018, what was it like? – Eugene Pirogov
ElixirConf Eu 2018, what was it like? – Eugene Pirogov
 
Implementing GraphQL API in Elixir – Victor Deryagin
Implementing GraphQL API in Elixir – Victor DeryaginImplementing GraphQL API in Elixir – Victor Deryagin
Implementing GraphQL API in Elixir – Victor Deryagin
 
WebPerformance: Why and How? – Stefan Wintermeyer
WebPerformance: Why and How? – Stefan WintermeyerWebPerformance: Why and How? – Stefan Wintermeyer
WebPerformance: Why and How? – Stefan Wintermeyer
 
Russian Doll Paradox: Elixir Web without Phoenix - Alex Rozumii
Russian Doll Paradox: Elixir Web without Phoenix - Alex RozumiiRussian Doll Paradox: Elixir Web without Phoenix - Alex Rozumii
Russian Doll Paradox: Elixir Web without Phoenix - Alex Rozumii
 
Practical Fault Tolerance in Elixir - Alexei Sholik
Practical Fault Tolerance in Elixir - Alexei SholikPractical Fault Tolerance in Elixir - Alexei Sholik
Practical Fault Tolerance in Elixir - Alexei Sholik
 
Phoenix and beyond: Things we do with Elixir - Alexander Khokhlov
Phoenix and beyond: Things we do with Elixir - Alexander KhokhlovPhoenix and beyond: Things we do with Elixir - Alexander Khokhlov
Phoenix and beyond: Things we do with Elixir - Alexander Khokhlov
 
Monads are just monoids in the category of endofunctors - Ike Kurghinyan
Monads are just monoids in the category of endofunctors - Ike KurghinyanMonads are just monoids in the category of endofunctors - Ike Kurghinyan
Monads are just monoids in the category of endofunctors - Ike Kurghinyan
 
Craft effective API with GraphQL and Absinthe - Ihor Katkov
Craft effective API with GraphQL and Absinthe - Ihor KatkovCraft effective API with GraphQL and Absinthe - Ihor Katkov
Craft effective API with GraphQL and Absinthe - Ihor Katkov
 
Elixir in a service of government - Alex Troush
Elixir in a service of government - Alex TroushElixir in a service of government - Alex Troush
Elixir in a service of government - Alex Troush
 
Pattern matching in Elixir by example - Alexander Khokhlov
Pattern matching in Elixir by example - Alexander KhokhlovPattern matching in Elixir by example - Alexander Khokhlov
Pattern matching in Elixir by example - Alexander Khokhlov
 

Kürzlich hochgeladen

TrustArc Webinar - Unlock the Power of AI-Driven Data Discovery
TrustArc Webinar - Unlock the Power of AI-Driven Data DiscoveryTrustArc Webinar - Unlock the Power of AI-Driven Data Discovery
TrustArc Webinar - Unlock the Power of AI-Driven Data DiscoveryTrustArc
 
Strategize a Smooth Tenant-to-tenant Migration and Copilot Takeoff
Strategize a Smooth Tenant-to-tenant Migration and Copilot TakeoffStrategize a Smooth Tenant-to-tenant Migration and Copilot Takeoff
Strategize a Smooth Tenant-to-tenant Migration and Copilot Takeoffsammart93
 
ProductAnonymous-April2024-WinProductDiscovery-MelissaKlemke
ProductAnonymous-April2024-WinProductDiscovery-MelissaKlemkeProductAnonymous-April2024-WinProductDiscovery-MelissaKlemke
ProductAnonymous-April2024-WinProductDiscovery-MelissaKlemkeProduct Anonymous
 
Automating Google Workspace (GWS) & more with Apps Script
Automating Google Workspace (GWS) & more with Apps ScriptAutomating Google Workspace (GWS) & more with Apps Script
Automating Google Workspace (GWS) & more with Apps Scriptwesley chun
 
Scaling API-first – The story of a global engineering organization
Scaling API-first – The story of a global engineering organizationScaling API-first – The story of a global engineering organization
Scaling API-first – The story of a global engineering organizationRadu Cotescu
 
Partners Life - Insurer Innovation Award 2024
Partners Life - Insurer Innovation Award 2024Partners Life - Insurer Innovation Award 2024
Partners Life - Insurer Innovation Award 2024The Digital Insurer
 
Boost PC performance: How more available memory can improve productivity
Boost PC performance: How more available memory can improve productivityBoost PC performance: How more available memory can improve productivity
Boost PC performance: How more available memory can improve productivityPrincipled Technologies
 
Handwritten Text Recognition for manuscripts and early printed texts
Handwritten Text Recognition for manuscripts and early printed textsHandwritten Text Recognition for manuscripts and early printed texts
Handwritten Text Recognition for manuscripts and early printed textsMaria Levchenko
 
Finology Group – Insurtech Innovation Award 2024
Finology Group – Insurtech Innovation Award 2024Finology Group – Insurtech Innovation Award 2024
Finology Group – Insurtech Innovation Award 2024The Digital Insurer
 
Histor y of HAM Radio presentation slide
Histor y of HAM Radio presentation slideHistor y of HAM Radio presentation slide
Histor y of HAM Radio presentation slidevu2urc
 
Data Cloud, More than a CDP by Matt Robison
Data Cloud, More than a CDP by Matt RobisonData Cloud, More than a CDP by Matt Robison
Data Cloud, More than a CDP by Matt RobisonAnna Loughnan Colquhoun
 
Apidays Singapore 2024 - Building Digital Trust in a Digital Economy by Veron...
Apidays Singapore 2024 - Building Digital Trust in a Digital Economy by Veron...Apidays Singapore 2024 - Building Digital Trust in a Digital Economy by Veron...
Apidays Singapore 2024 - Building Digital Trust in a Digital Economy by Veron...apidays
 
[2024]Digital Global Overview Report 2024 Meltwater.pdf
[2024]Digital Global Overview Report 2024 Meltwater.pdf[2024]Digital Global Overview Report 2024 Meltwater.pdf
[2024]Digital Global Overview Report 2024 Meltwater.pdfhans926745
 
2024: Domino Containers - The Next Step. News from the Domino Container commu...
2024: Domino Containers - The Next Step. News from the Domino Container commu...2024: Domino Containers - The Next Step. News from the Domino Container commu...
2024: Domino Containers - The Next Step. News from the Domino Container commu...Martijn de Jong
 
Connector Corner: Accelerate revenue generation using UiPath API-centric busi...
Connector Corner: Accelerate revenue generation using UiPath API-centric busi...Connector Corner: Accelerate revenue generation using UiPath API-centric busi...
Connector Corner: Accelerate revenue generation using UiPath API-centric busi...DianaGray10
 
Exploring the Future Potential of AI-Enabled Smartphone Processors
Exploring the Future Potential of AI-Enabled Smartphone ProcessorsExploring the Future Potential of AI-Enabled Smartphone Processors
Exploring the Future Potential of AI-Enabled Smartphone Processorsdebabhi2
 
HTML Injection Attacks: Impact and Mitigation Strategies
HTML Injection Attacks: Impact and Mitigation StrategiesHTML Injection Attacks: Impact and Mitigation Strategies
HTML Injection Attacks: Impact and Mitigation StrategiesBoston Institute of Analytics
 
What Are The Drone Anti-jamming Systems Technology?
What Are The Drone Anti-jamming Systems Technology?What Are The Drone Anti-jamming Systems Technology?
What Are The Drone Anti-jamming Systems Technology?Antenna Manufacturer Coco
 
Powerful Google developer tools for immediate impact! (2023-24 C)
Powerful Google developer tools for immediate impact! (2023-24 C)Powerful Google developer tools for immediate impact! (2023-24 C)
Powerful Google developer tools for immediate impact! (2023-24 C)wesley chun
 
AWS Community Day CPH - Three problems of Terraform
AWS Community Day CPH - Three problems of TerraformAWS Community Day CPH - Three problems of Terraform
AWS Community Day CPH - Three problems of TerraformAndrey Devyatkin
 

Kürzlich hochgeladen (20)

TrustArc Webinar - Unlock the Power of AI-Driven Data Discovery
TrustArc Webinar - Unlock the Power of AI-Driven Data DiscoveryTrustArc Webinar - Unlock the Power of AI-Driven Data Discovery
TrustArc Webinar - Unlock the Power of AI-Driven Data Discovery
 
Strategize a Smooth Tenant-to-tenant Migration and Copilot Takeoff
Strategize a Smooth Tenant-to-tenant Migration and Copilot TakeoffStrategize a Smooth Tenant-to-tenant Migration and Copilot Takeoff
Strategize a Smooth Tenant-to-tenant Migration and Copilot Takeoff
 
ProductAnonymous-April2024-WinProductDiscovery-MelissaKlemke
ProductAnonymous-April2024-WinProductDiscovery-MelissaKlemkeProductAnonymous-April2024-WinProductDiscovery-MelissaKlemke
ProductAnonymous-April2024-WinProductDiscovery-MelissaKlemke
 
Automating Google Workspace (GWS) & more with Apps Script
Automating Google Workspace (GWS) & more with Apps ScriptAutomating Google Workspace (GWS) & more with Apps Script
Automating Google Workspace (GWS) & more with Apps Script
 
Scaling API-first – The story of a global engineering organization
Scaling API-first – The story of a global engineering organizationScaling API-first – The story of a global engineering organization
Scaling API-first – The story of a global engineering organization
 
Partners Life - Insurer Innovation Award 2024
Partners Life - Insurer Innovation Award 2024Partners Life - Insurer Innovation Award 2024
Partners Life - Insurer Innovation Award 2024
 
Boost PC performance: How more available memory can improve productivity
Boost PC performance: How more available memory can improve productivityBoost PC performance: How more available memory can improve productivity
Boost PC performance: How more available memory can improve productivity
 
Handwritten Text Recognition for manuscripts and early printed texts
Handwritten Text Recognition for manuscripts and early printed textsHandwritten Text Recognition for manuscripts and early printed texts
Handwritten Text Recognition for manuscripts and early printed texts
 
Finology Group – Insurtech Innovation Award 2024
Finology Group – Insurtech Innovation Award 2024Finology Group – Insurtech Innovation Award 2024
Finology Group – Insurtech Innovation Award 2024
 
Histor y of HAM Radio presentation slide
Histor y of HAM Radio presentation slideHistor y of HAM Radio presentation slide
Histor y of HAM Radio presentation slide
 
Data Cloud, More than a CDP by Matt Robison
Data Cloud, More than a CDP by Matt RobisonData Cloud, More than a CDP by Matt Robison
Data Cloud, More than a CDP by Matt Robison
 
Apidays Singapore 2024 - Building Digital Trust in a Digital Economy by Veron...
Apidays Singapore 2024 - Building Digital Trust in a Digital Economy by Veron...Apidays Singapore 2024 - Building Digital Trust in a Digital Economy by Veron...
Apidays Singapore 2024 - Building Digital Trust in a Digital Economy by Veron...
 
[2024]Digital Global Overview Report 2024 Meltwater.pdf
[2024]Digital Global Overview Report 2024 Meltwater.pdf[2024]Digital Global Overview Report 2024 Meltwater.pdf
[2024]Digital Global Overview Report 2024 Meltwater.pdf
 
2024: Domino Containers - The Next Step. News from the Domino Container commu...
2024: Domino Containers - The Next Step. News from the Domino Container commu...2024: Domino Containers - The Next Step. News from the Domino Container commu...
2024: Domino Containers - The Next Step. News from the Domino Container commu...
 
Connector Corner: Accelerate revenue generation using UiPath API-centric busi...
Connector Corner: Accelerate revenue generation using UiPath API-centric busi...Connector Corner: Accelerate revenue generation using UiPath API-centric busi...
Connector Corner: Accelerate revenue generation using UiPath API-centric busi...
 
Exploring the Future Potential of AI-Enabled Smartphone Processors
Exploring the Future Potential of AI-Enabled Smartphone ProcessorsExploring the Future Potential of AI-Enabled Smartphone Processors
Exploring the Future Potential of AI-Enabled Smartphone Processors
 
HTML Injection Attacks: Impact and Mitigation Strategies
HTML Injection Attacks: Impact and Mitigation StrategiesHTML Injection Attacks: Impact and Mitigation Strategies
HTML Injection Attacks: Impact and Mitigation Strategies
 
What Are The Drone Anti-jamming Systems Technology?
What Are The Drone Anti-jamming Systems Technology?What Are The Drone Anti-jamming Systems Technology?
What Are The Drone Anti-jamming Systems Technology?
 
Powerful Google developer tools for immediate impact! (2023-24 C)
Powerful Google developer tools for immediate impact! (2023-24 C)Powerful Google developer tools for immediate impact! (2023-24 C)
Powerful Google developer tools for immediate impact! (2023-24 C)
 
AWS Community Day CPH - Three problems of Terraform
AWS Community Day CPH - Three problems of TerraformAWS Community Day CPH - Three problems of Terraform
AWS Community Day CPH - Three problems of Terraform
 

GenServer in Action – Yurii Bodarev

  • 1. GenServer in Action  Elixir Club 11 Ternopil, 2018
  • 3. Process iex(1)> spawn fn -> 1 + 1 end #PID<0.90.0> iex(2)> caller = self() #PID<0.88.0> iex(3)> spawn fn -> send caller, {:result, 1 + 1} end #PID<0.93.0> iex(4)> receive do ...(4)> {:result, result} -> result ...(4)> end 2
  • 4. Process iex(5)> spawn fn -> ...(5)> Process.sleep(6_000) ...(5)> send caller, {:result, 1 + 1} ...(5)> end #PID<0.106.0> iex(6)> receive do ...(6)> {:result, result} -> result ...(6)> end ⏳⏳⏳⏳⏳⌛ 2
  • 5. Process iex(7)> spawn fn -> ...(7)> Process.sleep(666_666_666) ...(7)> send caller, {:result, 1 + 1} ...(7)> end #PID<0.99.0> iex(8)> spawn fn -> :nothing end #PID<0.101.0> iex(9)> spawn fn -> raise "error" end #PID<0.103.0> … iex(11)> receive do ...(11)> {:result, result} -> result ...(11)> end ⏳⏳⏳⏳⏳⏳⏳⏳⏳⏳⏳⏳⏳⏳⏳⏳⏳⏳⏳⏳⏳⏳⏳⏳⏳⏳⏳⏳⏳⏳⏳⏳⏳⏳⏳⏳⏳⏳⏳ 💤 💤 💤 CTRL+C
  • 6. Process: timeout iex(1)> caller = self() #PID<0.88.0> iex(2)> spawn fn -> ...(2)> Process.sleep(666_666_666) ...(2)> send caller, {:result, 1 + 1} ...(2)> end #PID<0.94.0> iex(3)> receive do ...(3)> {:result, result} -> {:ok, result} ...(3)> after ...(3)> 5_000 -> {:error, :timeout} ...(3)> end ⏳⏳⏳⏳⌛{:error, :timeout}
  • 7. Process: message queue iex(4)> send self(), {:message, 1} iex(5)> send self(), {:another_message, 1} iex(6)> send self(), {:message, 2} iex(7)> send self(), {:another_message, 2} iex(8)> send self(), {:message, 3} iex(9)> send self(), {:another_message, 3} iex(10)> Process.info(self(), :messages) {:messages, [ message: 1, another_message: 1, message: 2, another_message: 2, message: 3, another_message: 3 ]}
  • 8. Process: message queue {:messages, [ message: 1, another_message: 10, message: 2, another_message: 20, message: 3, another_message: 30 ]} iex(11)> receive do {:another_message, n} -> n end 10 iex(12)> receive do {:another_message, n} -> n end 20 iex(13)> Process.info(self(), :messages) {:messages, [message: 1, message: 2, message: 3, another_message: 30]} iex(14)> receive do {:message, n} -> n end 1 iex(15)> Process.info(self(), :messages) {:messages, [message: 2, message: 3, another_message: 30]} iex(16)> receive do {:something, n} -> n after 0 -> :no_matching_message end :no_matching_message
  • 10. Concurrent Tasks Task.async / Task.await ex(17)> task = Task.async(fn -> 1 + 1 end) %Task{ owner: #PID<0.88.0>, pid: #PID<0.106.0>, ref: #Reference<0.1183799544.2034761732.30152> } iex(18)> Task.await(task) 2
  • 11. Concurrent Tasks Task.async / Task.await iex(19)> tasks = Enum.map(1..10, &Task.async(fn -> ...(19)> Process.sleep(3_000) ...(19)> &1 * 100 ...(19)> end)) […] iex(20)> Process.sleep(5_000) :ok iex(21)> Enum.map(tasks, &Task.await(&1)) [100, 200, 300, 400, 500, 600, 700, 800, 900, 1000]
  • 12. Concurrent Tasks Task.await timeout await(task, timeout 5000) … A timeout, in milliseconds, can be given with default value of 5000. If the timeout is exceeded, then the current process will exit. … iex(22)> Task.async(fn -> Process.sleep(6_000) end) |> Task.await() ** (exit) exited in: Task.await(%Task{owner: #PID<0.88.0>, pid: #PID<0.156.0>, ref: #Reference<0.891801449.431751175.151026>}, 5000) ** (EXIT) time out (elixir) lib/task.ex:501: Task.await/2
  • 13. Storing state defmodule Storage do def recursive(state) do receive do {:add, caller_pid, value} -> new_state = state + value send(caller_pid, {:result, new_state}) recursive(new_state) end end end iex(2)> storage_pid = spawn(fn -> Storage.recursive(0) end) iex(3)> send(storage_pid, {:add, self(), 2}) iex(4)> send(storage_pid, {:add, self(), 2}) iex(5)> send(storage_pid, {:add, self(), 2}) iex(6)> flush() {:result, 2} {:result, 4} {:result, 6}
  • 14. Storing state Agent iex(7)> {:ok, pid} = Agent.start_link(fn -> 0 end) {:ok, #PID<0.101.0>} iex(8)> Agent.update(pid, fn state -> state + 1 end) :ok iex(9)> Agent.get(pid, fn state -> state end) 1 update(agent, fun, timeout 5000) get(agent, module, fun, args, timeout 5000)
  • 16. GenServer A behaviour module for implementing the server of a client- server relation. A GenServer is a process like any other Elixir process and it can be used to keep state, execute code asynchronously and so on. 
  • 17. GenServer defmodule Stack do use GenServer # Client def start_link(default) do GenServer.start_link(__MODULE__, default) end def push(pid, item) do GenServer.cast(pid, {:push, item}) end def pop(pid) do GenServer.call(pid, :pop) end # Server (callbacks) def handle_call(:pop, _from, [h | t]) do {:reply, h, t} end def handle_cast({:push, item}, state) do {:noreply, [item | state]} end end
  • 18. GenServer defmodule Stack do use GenServer # Client def start_link(default) do GenServer.start_link(__MODULE__, default) end def push(pid, item) do GenServer.cast(pid, {:push, item}) end def pop(pid) do GenServer.call(pid, :pop) end # Server (callbacks) def handle_call(:pop, _from, [h | t]) do {:reply, h, t} end def handle_cast({:push, item}, state) do {:noreply, [item | state]} end end Executed in caller process
  • 19. GenServer defmodule Stack do use GenServer # Client def start_link(default) do GenServer.start_link(__MODULE__, default) end def push(pid, item) do GenServer.cast(pid, {:push, item}) end def pop(pid) do GenServer.call(pid, :pop) end # Server (callbacks) def handle_call(:pop, _from, [h | t]) do {:reply, h, t} end def handle_cast({:push, item}, state) do {:noreply, [item | state]} end end Executed in server process
  • 20. GenServer: timeout call(server, request, timeout 5000) def push(pid, item) do GenServer.cast(pid, {:push, item}) end def pop(pid) do GenServer.call(pid, :pop) end # Server (callbacks) @impl true def handle_call(:pop, _from, [h | t]) do Process.sleep(30_000) {:reply, h, t} end @impl true def handle_cast({:push, item}, state) do {:noreply, [item | state]} end Executed in caller process Executed in server process
  • 21. GenServer: timeout iex(2)> {:ok, pid} = Stack.start_link([]) {:ok, #PID<0.95.0>} iex(3)> Enum.each(1..5, &Stack.push(pid, &1)) :ok ex(4)> Stack.pop(pid) ** (exit) exited in: GenServer.call(#PID<0.95.0>, :pop, 5000) ** (EXIT) time out (elixir) lib/gen_server.ex:836: GenServer.call/3 iex(4)> Stack.pop(pid) ** (exit) exited in: GenServer.call(#PID<0.95.0>, :pop, 5000) ** (EXIT) time out (elixir) lib/gen_server.ex:836: GenServer.call/3 iex(4)> Stack.pop(pid) ** (exit) exited in: GenServer.call(#PID<0.95.0>, :pop, 5000) ** (EXIT) time out (elixir) lib/gen_server.ex:836: GenServer.call/3 iex(4)> Stack.pop(pid) ** (exit) exited in: GenServer.call(#PID<0.95.0>, :pop, 5000) ** (EXIT) time out (elixir) lib/gen_server.ex:836: GenServer.call/3 iex(4)> Process.info(pid, :messages) {:messages, [ {:"$gen_call", {#PID<0.88.0>, #Reference<0.3022523149.3093823489.83754>}, :pop}, {:"$gen_call", {#PID<0.88.0>, #Reference<0.3022523149.3093823489.83774>}, :pop}, {:"$gen_call", {#PID<0.88.0>, #Reference<0.3022523149.3093823489.83794>}, :pop} ]} Executed in caller process Executed in server process
  • 22. GenServer: timeout ex(5)> Process.info(pid, :messages) {:messages, [ {:"$gen_call", {#PID<0.88.0>, #Reference<0.3022523149.3093823489.83794>}, :pop} ]} ex(6)> Process.info(pid, :messages) {:messages, []} iex(7)> flush() {#Reference<0.3022523149.3093823489.83730>, 5} {#Reference<0.3022523149.3093823489.83754>, 4} {#Reference<0.3022523149.3093823489.83774>, 3} {#Reference<0.3022523149.3093823489.83794>, 2} :ok
  • 24. Digital Signature Microservice • Microservice - part of the Ukrainian eHealth system infrastructure • Digital signature validation • Ukrainian standard DSTU 4145-2002 • Integration with proprietary C library via NIF
  • 25. Digital Signature Microservice Digital Signature Microservice NIF Proprietary DSTU 4145-2002 LIB Digitally signed content < 5s Decoded content Signer info Signature validation Certificates OSCP Server
  • 26. {:ok, result} = DigitalSignatureLib.processPKCS7Data(data, certs, true) result == %{ content: "{"hello": "world"}", is_valid: true, signer: %{ common_name: "XXX YYY ZZZ", country_name: "UA", drfo: "1234567890", edrpou: "", given_name: "XX YY", locality_name: "М. КИЇВ", organization_name: "ФІЗИЧНА ОСОБА", organizational_unit_name: "", state_or_province_name: "", surname: "XX", title: "" }, validation_error_message: "" }
  • 27. Sounds easy? Digital Signature Microservice DigitalSignatureLib.processPKCS7Data(…) DigitalSignatureLib.processPKCS7Data(…) DigitalSignatureLib.processPKCS7Data(…) DigitalSignatureLib.processPKCS7Data(…) Elixir Process Elixir Process Elixir Process Elixir Process Incoming Requests 200 OK 200 OK 200 OK 200 OK Responses
  • 28.
  • 29. Problem 1: concurrency tasks = Enum.map(1..25, fn _ -> Task.async(fn -> DigitalSignatureLib.processPKCS7Data(data, certs, true) end) end) Enum.map(tasks, fn task -> {:ok, result} = Task.await(task, 30000) IO.inspect(result) end)
  • 30. %{ content: *** } %{ content: *** } %{ content: *** } %{ content: *** } *** Error in `/usr/local/lib/erlang/erts-9.3.3/bin/beam.smp': double free or corruption (fasttop): 0x00007f88e401d060 *** ======= Backtrace: ========= /lib/x86_64-linux-gnu/libc.so.6(+0x70bfb)[0x7f8962452bfb] /lib/x86_64-linux-gnu/libc.so.6(+0x76fc6)[0x7f8962458fc6] /lib/x86_64-linux-gnu/libc.so.6(+0x7780e)[0x7f896245980e] /usr/local/lib/libUACryptoQ.so.1(_ZN9DataBlockaSERKS_+0x3c)[0x7f88a7bd785c] /usr/local/lib/libUACryptoQ.so.1(_ZN4DataaSERKS_+0x11)[0x7f88a7bd6771] /usr/local/lib/libUACryptoQ.so.1(_ZN7DataSet3NewERK4Data+0x3c)[0x7f88a7bd81cc] /usr/local/lib/libUACryptoQ.so.1(_ZNK3UAC16ObjectIdentifier10EncodeBodyEv+0x1fc)[0x7f88a7bf238c] /usr/local/lib/libUACryptoQ.so.1(_ZNK3UAC5Token6EncodeEv+0x46)[0x7f88a7bef236] /usr/local/lib/libUACryptoQ.so.1(_ZNK3UAC11ObjectToken10EncodeBodyEv+0x17)[0x7f88a7bef3c7] /usr/local/lib/libUACryptoQ.so.1(_ZNK3UAC5Token6EncodeEv+0x46)[0x7f88a7bef236] /usr/local/lib/libUACryptoQ.so.1(_ZNK3UAC11Constructed10EncodeBodyEv+0x45)[0x7f88a7be97d5] /usr/local/lib/libUACryptoQ.so.1(_ZNK3UAC11Constructed6EncodeEv+0x39)[0x7f88a7bec089] /usr/local/lib/libUACryptoQ.so.1(_ZNK3UAC11Constructed10EncodeBodyEv+0x45)[0x7f88a7be97d5] /usr/local/lib/libUACryptoQ.so.1(_ZNK3UAC11Constructed6EncodeEv+0x39)[0x7f88a7bec089] /usr/local/lib/libUACryptoQ.so.1(_ZNK3UAC10CMSContent6EncodeEv+0x95)[0x7f88a7c0a2d5] /usr/local/lib/libUACryptoQ.so.1(_ZNK3UAC11ObjectToken10EncodeBodyEv+0x3a)[0x7f88a7bef3ea] /usr/local/lib/libUACryptoQ.so.1(_ZNK3UAC5Token6EncodeEv+0x46)[0x7f88a7bef236] /usr/local/lib/libUACryptoQ.so.1(_ZNK3UAC11Constructed10EncodeBodyEv+0x45)[0x7f88a7be97d5] /usr/local/lib/libUACryptoQ.so.1(_ZNK3UAC11Constructed6EncodeEv+0x39)[0x7f88a7bec089] /usr/local/lib/libUACryptoQ.so.1(_ZNK3UAC10CMSContent6EncodeEv+0x95)[0x7f88a7c0a2d5] /usr/local/lib/libUACryptoQ.so.1(_ZNK3UAC11ObjectToken10EncodeBodyEv+0x3a)[0x7f88a7bef3ea] /usr/local/lib/libUACryptoQ.so.1(_ZNK3UAC5Token6EncodeEv+0x46)[0x7f88a7bef236] /usr/local/lib/libUACryptoQ.so.1(_ZNK3UAC11Constructed10EncodeBodyEv+0x45)[0x7f88a7be97d5] /usr/local/lib/libUACryptoQ.so.1(_ZNK3UAC11Constructed6EncodeEv+0x39)[0x7f88a7bec089] /usr/local/lib/libUACryptoQ.so.1(_ZNK3UAC17ObjectWithContent6EncodeEv+0x1b)[0x7f88a7be946b] /usr/local/lib/libUACryptoQ.so.1(_ZNK3UAC11ObjectToken10EncodeBodyEv+0x3a)[0x7f88a7bef3ea] /usr/local/lib/libUACryptoQ.so.1(_ZNK3UAC5Token6EncodeEv+0x46)[0x7f88a7bef236] /usr/local/lib/libUACryptoQ.so.1(_ZNK3UAC11Constructed10EncodeBodyEv+0x45)[0x7f88a7be97d5] /usr/local/lib/libUACryptoQ.so.1(_ZNK3UAC11Constructed6EncodeEv+0x39)[0x7f88a7bec089] /usr/local/lib/libUACryptoQ.so.1(_ZN3UAC13CMSSignedData15VerifySignatureEPNS_11CertificateEP11_UAC_STREAM+0x9f5)[0x7f88a7c12965] /usr/local/lib/libUACryptoQ.so.1(UAC_SignedDataVerify+0x2ba)[0x7f88a7c4ff1a] /home/digital_signature.lib/_build/test/lib/digital_signature_lib/priv/digital_signature_lib_nif.so(Check+0x3c5)[0x7f891c0fc7f5] /home/digital_signature.lib/_build/test/lib/digital_signature_lib/priv/digital_signature_lib_nif.so(+0x2bac)[0x7f891c0fbbac] /usr/local/lib/erlang/erts-9.3.3/bin/beam.smp(erts_call_dirty_nif+0x19c)[0x5ce04c] /usr/local/lib/erlang/erts-9.3.3/bin/beam.smp(erts_dirty_process_main+0x209)[0x445949] /usr/local/lib/erlang/erts-9.3.3/bin/beam.smp[0x4f4a4d] /usr/local/lib/erlang/erts-9.3.3/bin/beam.smp[0x675985] /lib/x86_64-linux-gnu/libpthread.so.0(+0x7494)[0x7f8962990494] /lib/x86_64-linux-gnu/libc.so.6(clone+0x3f)[0x7f89624caacf] ======= Memory map: ======== 00400000-0073b000 r-xp 00000000 08:01 2376229 /usr/local/lib/erlang/erts-9.3.3/bin/beam.smp 0093a000-0093b000 r--p 0033a000 08:01 2376229 /usr/local/lib/erlang/erts-9.3.3/bin/beam.smp 0093b000-00956000 rw-p 0033b000 08:01 2376229 /usr/local/lib/erlang/erts-9.3.3/bin/beam.smp 00956000-0097d000 rw-p 00000000 00:00 0 0231e000-02349000 rw-p 00000000 00:00 0 [heap]
  • 31. Problem 1 solution: Gen Server ... use GenServer # Callbacks ... def handle_call({:process_signed_content, signed_content, check}, _from, {certs_cache_ttl, certs}) do check = unless is_boolean(check), do: true processing_result = do_process_signed_content(signed_content, certs, check, SignedData.new()) {:reply, processing_result, {certs_cache_ttl, certs}} end ... # Client ... def process_signed_content(signed_content, check) do GenServer.call(__MODULE__, {:process_signed_content, signed_content, check}) end
  • 32. Problem 1 solution: Gen Server NifService (GenServer) NifService.process_signed_content(…) NifService.process_signed_content(…) NifService.process_signed_content(…) NifService.process_signed_content(…) Requests Message queue DigitalSignatureLib.processPKCS7Data(…) Responses
  • 33. Problem 2: timeouts NifService (GenServer) Multiple concurrent requests (processes) 2s 2s 2s 2s Message queue Sequential responses 200 OK 2s 200 OK 4s 500 Error 5s 500 Error 5s call(server, request, timeout 5000) ** (EXIT) time out ** (EXIT) time out
  • 34. Problem 2: timeouts NifService (GenServer) Multiple concurrent requests (processes) 2s 2s Message queue Sequential responses call(server, request, timeout 5000) 2s 2s 500 Error 5s 500 Error 5s
  • 35. Problem 2 solution: architecture DS DS DS DS DS DS DS DS Load Balancer Reduce pressure on individual MS
  • 36. Problem 2 solution: catch Exit def process_signed_content(signed_content, check) do gen_server_timeout = Confex.fetch_env(:digital_signature_api, :nif_service_timeout) try do GenServer.call(__MODULE__, {:process_signed_content, signed_content, check}, gen_server_timeout) catch :exit, {:timeout, error} -> {:error, {:nif_service_timeout, error}} end end 424 Failed Dependency
  • 37. Problem 3: message queue NifService (GenServer) Processed requests 2s 2s 2s 2s Message queue Sequential responses 200 OK 2s 200 OK 4s 424 5s 424 5s 2s 2s Expired requests New requests
  • 38. Problem 3 solution: pass message expiration time ... # Callbacks def handle_call({:process_signed_content, signed_content, check, message_exp_time}, _from, certs_cache_ttl, certs}) do processing_result = if NaiveDateTime.diff(message_exp_time, NaiveDateTime.utc_now(), :millisecond) > 250 do check = unless is_boolean(check), do: true do_process_signed_content(signed_content, certs, check, SignedData.new()) else {:error, {:nif_service_timeout, "messaqe queue timeout"}} end {:reply, processing_result, {certs_cache_ttl, certs}} End ... # Client def process_signed_content(signed_content, check) do gen_server_timeout = Confex.fetch_env!(:digital_signature_api, :nif_service_timeout) message_exp_time = NaiveDateTime.add(NaiveDateTime.utc_now(), gen_server_timeout, :millisecond) try do GenServer.call(__MODULE__, {:process_signed_content, signed_content, check, message_exp_time}, gen_server_timeout) catch :exit, {:timeout, error} -> {:error, {:nif_service_timeout, error}} end end ...
  • 39. Problem 3 solution: pass message expiration time NifService (GenServer) … Expired Expired Within threshold Message queue …
  • 40. Problem 3 advanced solution: QueueService NifService DigitalSignatureLib. processPKCS7Data(…) QueueService :queue Monitoring & Control
  • 41.
  • 42. Memory management Binary terms which are larger than 64 bytes are not stored in a process private heap. They are called Refc Binary (Reference Counted Binary) and are stored in a large Shared Heap which is accessible by all processes who have the pointer of that Refc Binaries. That pointer is called ProcBin and is stored in a process private heap. The GC for the shared heap is reference counting. Collecting those Refc messages depends on collecting of all ProcBin objects even ones that are inside the middleware process. Unfortunately because ProcBins are just a pointer hence they are so cheap and it could take so long to happen a GC inside the middleware process.
  • 43. NifService Memory management Shared Heap Refc Binary Refc Binary Refc Binary Requests Responses ProcBin ProcBin ProcBin ProcBin ProcBin ProcBin ProcBin ProcBin ProcBin GC GC GC :erlang.garbage_collect(self()) Processes
  • 44. Garbage Collect ... # Callbacks def init(certs_cache_ttl) do certs = CertAPI.get_certs_map() Process.send_after(self(), :refresh, certs_cache_ttl) {:ok, {certs_cache_ttl, certs}} end ... def handle_info(:refresh, {certs_cache_ttl, _certs}) do certs = CertAPI.get_certs_map() # GC :erlang.garbage_collect(self()) Process.send_after(self(), :refresh, certs_cache_ttl) {:noreply, {certs_cache_ttl, certs}} end ...
  • 45. Garbage Collect handle_call(request, from, state) {:reply, reply, new_state, timeout() | :hibernate} Hibernating a GenServer causes garbage collection and leaves a continuous heap that minimises the memory used by the process Returning {:reply, reply, new_state, timeout} is similar to {:reply, reply, new_state} except handle_info(:timeout, new_state) will be called after timeout milliseconds if no messages are received
  • 46. Useful links Saša Jurić "Elixir in Action, Second Edition” https://www.manning.com/books/elixir-in-action-second-edition Andrea Leopardi - Concurrent and Resilient Connections to Outside the BEAM (ElixirConfEU 2016) https://www.youtube.com/watch?time_continue=1884&v=U1Ry7STEFiY GenServer call time-outs https://cultivatehq.com/posts/genserver-call-timeouts/ Elixir Memory - Not Quite Free https://stephenbussey.com/2018/05/09/elixir-memory-not-quite-free.html Erlang Garbage Collection Details and Why It Matters https://hamidreza-s.github.io/erlang%20garbage%20collection%20memory%20layout%20soft%20realtime/ 2015/08/24/erlang-garbage-collection-details-and-why-it-matters.html