O slideshow foi denunciado.
Utilizamos seu perfil e dados de atividades no LinkedIn para personalizar e exibir anúncios mais relevantes. Altere suas preferências de anúncios quando desejar.

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

75 visualizações

Publicada em

Atualização da minha apresentação sobre Elixir

Publicada em: Tecnologia
  • Seja o primeiro a comentar

  • Seja a primeira pessoa a gostar disto

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

  1. 1. ELIXIR Tolerância a Falhas para Adultos Fabio Akita
  2. 2. Sintaxe
  3. 3. defmodule Teste do def say(name) do IO.puts("Hello #{name}") end end Teste.say("Fabio") # => "Hello Fabio" defmodule Teste do @spec say(String.t) def say(name) when is_string(name) do IO.puts "Hello " <> name end end TiposeParêntesesOpcionais
  4. 4. defmodule Teste do def factorial(n) do if n == 0 do 1 else n * factorial(n - 1) end end end Teste.factorial(10) # => 3628800 defmodule Teste do def factorial(1), do: 1 def factorial(n) do n * factorial(n - 1) end end Teste.factorial(10) # => 3628800 CallbyPattern
  5. 5. %{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}} = registro IO.puts Enum.join([name|result], ", ") # => Fabio, 1, 2, 3, 4 registro = {:ok, %{name: "Fabio", last_name: "Akita"}} {:ok, %{name: name}} = registro IO.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}} = registro IO.puts name # => Fabio registro = %{name: "Fabio", year: 2017, foo: {:ok, [1,2,3,4]}} %{name: name, foo: {:ok, result}} = registro IO.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} PatternMatching
  6. 6. range = (1..100) # => 1..100 interval = 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..100 interval = 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]
  7. 7. 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 )
  8. 8. 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) PipeOperator|>
  9. 9. Fundações
  10. 10. 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 :ok iex(24)> pid = spawn(function) Hello from function #PID<0.112.0> iex(25)> Process.alive?(pid) false iex(26)> Process.alive?(self) true iex(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 :ok iex(24)> pid = spawn(function) Hello from function #PID<0.112.0> iex(25)> Process.alive?(pid) false iex(26)> Process.alive?(self) true iex(27)> self #PID<0.85.0>
  11. 11. 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) true iex(3)> send(pid, {:say, self}) {:say, #PID<0.85.0>} iex(4)> flush "say what?" :ok iex(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) true iex(3)> send(pid, {:say, self}) {:say, #PID<0.85.0>} iex(4)> flush "say what?" :ok iex(5)> send(pid, "blabla") "blabla" iex(6)> Process.alive?(pid) false
  12. 12. 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!
  13. 13. iex(1)> pid = spawn(fn -> ...(1)> receive do ...(1)> {:say, from} -> send(from, "say what?") ...(1)> _ -> Process.exit(self, :normal) ...(1)> end ...(1)> end)
  14. 14. iex(2)> Process.flag(:trap_exit, true) false iex(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) false iex(3)> send(pid, "blabla") "blabla" iex(4)> flush {:EXIT, #PID<0.92.0>, :normal} :ok ASYNCHRONOUSEXCEPTIONS
  15. 15. defmodule Stack do def start_link do Agent.start_link(fn -> [] end, name: __MODULE__) end def push(new_value) do Agent.update(__MODULE__, fn(state) -> [new_value|state] end) end def pop do Agent.get_and_update(__MODULE__, fn(state) -> [head|tail] = state {head, tail} end) end end
  16. 16. iex(8)> Stack.start_link {:ok, #PID<0.123.0>} iex(9)> Stack.push "hello" :ok iex(10)> Stack.push "world" :ok iex(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" :ok iex(10)> Stack.push "world" :ok iex(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
  17. 17. defmodule Stack.Supervisor do use Supervisor def start_link do Supervisor.start_link(__MODULE__, :ok) end def init(:ok) do children = [ worker(Stack, []) ] supervise(children, strategy: :one_for_one) end end
  18. 18. iex(3)> Stack.Supervisor.start_link {:ok, #PID<0.127.0>} iex(4)> Stack.push "hello" :ok iex(5)> Stack.push "world" :ok iex(6)> Stack.pop "world" iex(7)> Process.list |> Enum.reverse |> hd |> Process.exit(:kill) true iex(8)> Stack.push "foo" :ok iex(9)> Stack.push "bar" :ok iex(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" :ok iex(5)> Stack.push "world" :ok iex(6)> Stack.pop "world" iex(7)> Process.list |> Enum.reverse |> hd |> Process.exit(:kill) true iex(8)> Stack.push "foo" :ok iex(9)> Stack.push "bar" :ok iex(10)> Stack.pop "bar" iex(11)> Stack.pop "foo"
  19. 19. iex(8)> :observer.start :ok
  20. 20. Distribuindo Processamento
  21. 21. def flow_test do 1..@large_number |> Flow.from_enumerable() |> Flow.map(&(&1 * 3)) |> Flow.partition() |> Flow.filter( &Integer.is_odd/1) |> Flow.partition() |> Enum.sort |> Enum.sum end end defmodule Teste do require Integer @large_number 10_000_000 @slice 5_000 @concurrency 10 def enum_test do 1..@large_number |> Enum.map(&(&1 * 3)) |> Enum.filter( &Integer.is_odd/1) |> Enum.sum end def stream_test do 1..@large_number |> Stream.map(&(&1 * 3)) |> Stream.filter( &Integer.is_odd/1) |> Enum.sum end defmodule Teste do require Integer @large_number 10_000_000 @slice 5_000 @concurrency 10 def enum_test do 1..@large_number |> Enum.map(&(&1 * 3)) |> Enum.filter( &Integer.is_odd/1) |> Enum.sum end def stream_test do 1..@large_number |> Stream.map(&(&1 * 3)) |> Stream.filter( &Integer.is_odd/1) |> Enum.sum end def flow_test do 1..@large_number |> Flow.from_enumerable() |> Flow.map(&(&1 * 3)) |> Flow.partition() |> Flow.filter( &Integer.is_odd/1) |> Flow.partition() |> Enum.sort |> Enum.sum end end
  22. 22. Sistema Operacional para Aplicações Distribuídas
  23. 23. 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
  24. 24. OBRIGADO slideshare.net/akitaonrails @akitaonrails

×