51
ELIXIR Tolerância a Falhas para Adultos Fabio Akita

Elixir -Tolerância a Falhas para Adultos - GDG Campinas

Embed Size (px)

Citation preview

ELIXIRTolerância a Falhas para Adultos

Fabio Akita

Sintaxe

defmodule Teste dodef say(name) doIO.puts("Hello #{name}")

endend

Teste.say("Fabio")# => "Hello Fabio"

defmodule Teste do@spec say(String.t)def say(name) when is_string(name) doIO.puts "Hello " <> name

endend

Tip

os

e Pa

rên

tese

sO

pci

on

ais

defmodule Teste dodef factorial(n) doif n == 0 do

1else

n * factorial(n - 1)end

endend

Teste.factorial(10)# => 3628800

defmodule Teste dodef factorial(1), do: 1def factorial(n) don * factorial(n - 1)

endend

Teste.factorial(10)# => 3628800

Cal

l by

Patt

ern

%{last_name: name} = registro# => ** (MatchError) no match of right hand side value: %{foo: {:ok, [1, 2, 3, 4]}, name: "Fabio", year: 2017}

registro = %{name: "Fabio", year: 2017, foo: {:ok, [1,2,3,4]}}%{name: name, foo: {:ok, result}} = registroIO.puts Enum.join([name|result], ", ")# => Fabio, 1, 2, 3, 4

registro = {:ok, %{name: "Fabio", last_name: "Akita"}}{:ok, %{name: name}} = registroIO.puts name# => Fabio

{:ok, result} = Enum.fetch([1,2,3,4,5], 3)IO.puts result# => 4

registro = {:ok, %{name: "Fabio", last_name: "Akita"}}{:ok, %{name: name}} = registroIO.puts name# => Fabio

registro = %{name: "Fabio", year: 2017, foo: {:ok, [1,2,3,4]}}%{name: name, foo: {:ok, result}} = registroIO.puts Enum.join([name|result], ", ")# => Fabio, 1, 2, 3, 4

%{last_name: name} = registro# => ** (MatchError) no match of right hand side value: %{foo: {:ok, [1, 2, 3, 4]}, name: "Fabio", year: 2017}

Patt

ern

Mat

chin

g

range = (1..100)# => 1..100interval = Enum.slice(range, 30, 10)# => [31, 32, 33, 34, 35, 36, 37, 38, 39, 40]evens = Enum.filter(interval, &(rem(&1,2) == 0))# => [32, 34, 36, 38, 40]multiplied = Enum.map(evens, &(&1 * 10))# => [320, 340, 360, 380, 400]Enum.take(multiplied, 2)# => [320, 340]

range = (1..100)interval = Enum.slice(range, 30, 10)evens = Enum.filter(interval, fn(n) -> rem(n, 2) ==0 end)multiplied = Enum.map(evens, fn(n) -> n * 10 end)Enum.take(multiplied, 2)

range = (1..100)# => 1..100interval = Enum.slice(range, 30, 10)# => [31, 32, 33, 34, 35, 36, 37, 38, 39, 40]evens = Enum.filter(interval, &(rem(&1,2) == 0))# => [32, 34, 36, 38, 40]multiplied = Enum.map(evens, &(&1 * 10))# => [320, 340, 360, 380, 400]Enum.take(multiplied, 2)# => [320, 340]

range = (1..100)interval = Enum.slice(range, 30, 10)evens = Enum.filter(interval, fn(n) -> rem(n, 2) ==0 end)multiplied = Enum.map(evens, fn(n) -> n * 10 end)Enum.take(multiplied, 2)

Enum.take(Enum.map(Enum.filter(

Enum.slice((1..100), 30, 10), &(rem(&1,2) == 0)), &(&1 * 10)

), 2)

range = (1..100)interval = Enum.slice(range, 30, 10)evens = Enum.filter(interval, fn(n) -> rem(n, 2) ==0 end)multiplied = Enum.map(evens, fn(n) -> n * 10 end)Enum.take(multiplied, 2)

(1..100)|> Enum.slice(30, 10)|> Enum.filter(&(rem(&1, 2)))|> Enum.map(&(&1 * 10))|> Enum.take(2)

Pip

e O

per

ato

r |>

Fundações

iex(22)> function = fn -> IO.puts("Hello from function") end#Function<20.99386804/0 in :erl_eval.expr/5>iex(23)> function.()Hello from function:okiex(24)> pid = spawn(function)Hello from function#PID<0.112.0>iex(25)> Process.alive?(pid)falseiex(26)> Process.alive?(self)trueiex(27)> self#PID<0.85.0>

iex(22)> function = fn -> IO.puts("Hello from function") end#Function<20.99386804/0 in :erl_eval.expr/5>iex(23)> function.()Hello from function:okiex(24)> pid = spawn(function)Hello from function#PID<0.112.0>iex(25)> Process.alive?(pid)falseiex(26)> Process.alive?(self)trueiex(27)> self#PID<0.85.0>

iex(1)> pid = spawn(fn ->...(1)> receive do...(1)> {:say, from} -> send(from, "say what?")...(1)> _ -> Process.exit(self, :normal)...(1)> end...(1)> end)#PID<0.92.0>iex(2)> Process.alive?(pid)trueiex(3)> send(pid, {:say, self}){:say, #PID<0.85.0>}iex(4)> flush"say what?":okiex(5)> send(pid, "blabla")"blabla"iex(6)> Process.alive?(pid)false

iex(1)> pid = spawn(fn ->...(1)> receive do...(1)> {:say, from} -> send(from, "say what?")...(1)> _ -> Process.exit(self, :normal)...(1)> end...(1)> end)#PID<0.92.0>iex(2)> Process.alive?(pid)trueiex(3)> send(pid, {:say, self}){:say, #PID<0.85.0>}iex(4)> flush"say what?":okiex(5)> send(pid, "blabla")"blabla"iex(6)> Process.alive?(pid)false

Processos

• Hiper-leves (pode subir milhares)

• Totalmente isoladas (Process.send(pid, :kill))

• Comunicação por passagem de mensagens

• Um mailbox por processo (receive)

• Garbage Collector separado por Processo!

iex(1)> pid = spawn(fn ->...(1)> receive do...(1)> {:say, from} -> send(from, "say what?")...(1)> _ -> Process.exit(self, :normal)...(1)> end...(1)> end)

iex(2)> Process.flag(:trap_exit, true)falseiex(3)> send(pid, "blabla")"blabla"iex(4)> flush{:EXIT, #PID<0.92.0>, :normal}:ok

iex(1)> pid = spawn_link(fn ->...(1)> receive do...(1)> {:say, from} -> send(from, "say what?")...(1)> _ -> Process.exit(self, :normal)...(1)> end...(1)> end)#PID<0.92.0>

iex(2)> Process.flag(:trap_exit, true)falseiex(3)> send(pid, "blabla")"blabla"iex(4)> flush{:EXIT, #PID<0.92.0>, :normal}:ok

ASY

NC

HR

ON

OU

SEX

CEP

TIO

NS

defmodule Stack dodef start_link doAgent.start_link(fn -> [] end, name: __MODULE__)

end

def push(new_value) doAgent.update(__MODULE__,fn(state) ->

[new_value|state]end)

end

def pop doAgent.get_and_update(__MODULE__,fn(state) ->

[head|tail] = state{head, tail}

end)end

end

iex(8)> Stack.start_link{:ok, #PID<0.123.0>}iex(9)> Stack.push "hello":okiex(10)> Stack.push "world":okiex(11)> Stack.pop"world"iex(12)> Stack.pop"hello"iex(13)> Process.list |> Enum.reverse |> Enum.at(0) |> Process.exit(:kill)** (EXIT from #PID<0.85.0>) evaluator process exited with reason: killed

Interactive Elixir (1.5.2) - press Ctrl+C to exit (type h() ENTER for help)iex(1)> Stack.push "foo"** (exit) exited in: GenServer.call(Stack, {:update, #Function<1.117587580/1 in Stack.push/1>}, 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) lib/gen_server.ex:766: GenServer.call/3

iex(8)> Stack.start_link{:ok, #PID<0.123.0>}iex(9)> Stack.push "hello":okiex(10)> Stack.push "world":okiex(11)> Stack.pop"world"iex(12)> Stack.pop"hello"iex(13)> Process.list |> Enum.reverse |> Enum.at(0) |> Process.exit(:kill)** (EXIT from #PID<0.85.0>) evaluator process exited with reason: killed

Interactive Elixir (1.5.2) - press Ctrl+C to exit (type h() ENTER for help)iex(1)> Stack.push "foo"** (exit) exited in: GenServer.call(Stack, {:update, #Function<1.117587580/1 in Stack.push/1>}, 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) lib/gen_server.ex:766: GenServer.call/3

defmodule Stack.Supervisor douse Supervisor

def start_link doSupervisor.start_link(__MODULE__, :ok)

end

def init(:ok) dochildren = [ worker(Stack, []) ]supervise(children, strategy: :one_for_one)

endend

iex(3)> Stack.Supervisor.start_link{:ok, #PID<0.127.0>}iex(4)> Stack.push "hello":okiex(5)> Stack.push "world":okiex(6)> Stack.pop"world"iex(7)> Process.list |> Enum.reverse |> hd |> Process.exit(:kill)trueiex(8)> Stack.push "foo":okiex(9)> Stack.push "bar":okiex(10)> Stack.pop"bar"iex(11)> Stack.pop"foo"

iex(3)> Stack.Supervisor.start_link{:ok, #PID<0.127.0>}iex(4)> Stack.push "hello":okiex(5)> Stack.push "world":okiex(6)> Stack.pop"world"iex(7)> Process.list |> Enum.reverse |> hd |> Process.exit(:kill)trueiex(8)> Stack.push "foo":okiex(9)> Stack.push "bar":okiex(10)> Stack.pop"bar"iex(11)> Stack.pop"foo"

iex(8)> :observer.start:ok

DistribuindoProcessamento

def flow_test do1..@large_number|> Flow.from_enumerable()|> Flow.map(&(&1 * 3))|> Flow.partition()|> Flow.filter(&Integer.is_odd/1)

|> Flow.partition()|> Enum.sort|> Enum.sum

endend

defmodule Teste dorequire Integer@large_number 10_000_000@slice 5_000@concurrency 10

def enum_test do1..@large_number|> Enum.map(&(&1 * 3))|> Enum.filter(

&Integer.is_odd/1)|> Enum.sum

end

def stream_test do1..@large_number|> Stream.map(&(&1 * 3))|> Stream.filter(

&Integer.is_odd/1)|> Enum.sum

end

defmodule Teste dorequire Integer@large_number 10_000_000@slice 5_000@concurrency 10

def enum_test do1..@large_number|> Enum.map(&(&1 * 3))|> Enum.filter(

&Integer.is_odd/1)|> Enum.sum

end

def stream_test do1..@large_number|> Stream.map(&(&1 * 3))|> Stream.filter(

&Integer.is_odd/1)|> Enum.sum

end

def flow_test do1..@large_number|> Flow.from_enumerable()|> Flow.map(&(&1 * 3))|> Flow.partition()|> Flow.filter(&Integer.is_odd/1)

|> Flow.partition()|> Enum.sort|> Enum.sum

endend

Sistema Operacionalpara AplicaçõesDistribuídas

Versão Lançamento

1.0 18/09/2014

1.1 28/09/2015

1.2 03/01/2016

1.3 21/06/2016

1.4 05/01/2017

1.5 25/07/2017

OBRIGADOslideshare.net/akitaonrails

@akitaonrails