Advertisement
Advertisement

More Related Content

Advertisement
Advertisement

Elixir/OTP for PHP developers

  1. Elixir/OTP for PHP developers Nacho Martín
  2. My name is Nacho Martín. I write code at Limenius. We build tailor-made projects, and provide consultancy and formation. We have been using PHP for many years. But for certain tasks we use Elixir/Erlang & we are very happy with it.
  3. Investing in a new language?
  4. Learning alternatives
  5. Learning alternatives Learning complements
  6. Syntax?
  7. Platform Overall philosophy Why was it built Orientation of the community
  8. (Simplified) Request Nginx WrapperFastCGI PHPFastCGI Response WrapperFastCGI PHPFastCGI Response WrapperFastCGI PHPFastCGI Response WrapperFastCGI PHPFastCGI Response WrapperFastCGI PHPFastCGI Response Socket
  9. (Simplified) Request Nginx WrapperFastCGI PHPFastCGI Response WrapperFastCGI PHPFastCGI Response WrapperFastCGI PHPFastCGI Response WrapperFastCGI PHPFastCGI Response WrapperFastCGI PHPFastCGI Response Socket ?
  10. Most of what we are going to say applies to both
  11. Erlang:The Movie Hello Mike.
  12. Speaking about Elixir means speaking about Erlang • Similar syntax. • Battle tested. • Very stable. • More low-level feeling in code & community.
  13. Elixir core features
  14. Everything flows from Cheap processes • Low footprint • Fast start • Isolated • Share nothing • Use as many as you need
  15. pid = spawn(fn -> IO.puts "In #{inspect self()} process" end) #PID<0.42.0>
  16. pid = spawn(fn -> IO.puts "In #{inspect self()} process" end) #PID<0.43.0>#PID<0.42.0>
  17. Message passing #PID<0.43.0>#PID<0.42.0> send pid, {:hello, "world"} receive do {:hello, msg} -> msg {:something, msg} -> "won't match" end
  18. Monitors
  19. Monitors pid = spawn(fn -> :timer.sleep 500 raise(“I’m dying.”) end)
  20. Monitors pid = spawn(fn -> :timer.sleep 500 raise(“I’m dying.”) end)
  21. Monitors pid = spawn(fn -> :timer.sleep 500 raise(“I’m dying.”) end) ref = Process.monitor(pid)
  22. Monitors pid = spawn(fn -> :timer.sleep 500 raise(“I’m dying.”) end) ref = Process.monitor(pid)
  23. Monitors pid = spawn(fn -> :timer.sleep 500 raise(“I’m dying.”) end) ref = Process.monitor(pid) receive do {:DOWN, ^ref, :process, ^pid, msg} -> IO.puts "Received :DOWN from #{inspect pid}" end
  24. Monitors pid = spawn(fn -> :timer.sleep 500 raise(“I’m dying.”) end) ref = Process.monitor(pid) receive do {:DOWN, ^ref, :process, ^pid, msg} -> IO.puts "Received :DOWN from #{inspect pid}" end
  25. Monitors pid = spawn(fn -> :timer.sleep 500 raise(“I’m dying.”) end) ref = Process.monitor(pid) receive do {:DOWN, ^ref, :process, ^pid, msg} -> IO.puts "Received :DOWN from #{inspect pid}" end
  26. Links Process.flag(:trap_exit, true) spawn_link(fn -> raise(“I am dying.”) end)
  27. Links Process.flag(:trap_exit, true) spawn_link(fn -> raise(“I am dying.”) end)
  28. Links Process.flag(:trap_exit, true) spawn_link(fn -> raise(“I am dying.”) end) receive do {:EXIT, pid, msg} -> IO.inspect ":EXIT received from #{inspect pid}" IO.inspect msg end
  29. Links Process.flag(:trap_exit, true) spawn_link(fn -> raise(“I am dying.”) end) receive do {:EXIT, pid, msg} -> IO.inspect ":EXIT received from #{inspect pid}" IO.inspect msg end
  30. Links Process.flag(:trap_exit, true) spawn_link(fn -> raise(“I am dying.”) end) receive do {:EXIT, pid, msg} -> IO.inspect ":EXIT received from #{inspect pid}" IO.inspect msg end
  31. 😍OPEN TELECOM PLATFORM😍
  32. OTP Supervision Trees Supervisor GenServerGenServerSupervisor GenServerGenServer GenServer
  33. {:ok, pid} = GenServer.start_link(Stack, [:hello]) GenServer defmodule Stack do use GenServer @impl true def init(stack) do {:ok, stack} end end Client GenServer
  34. {:ok, pid} = GenServer.start_link(Stack, [:hello]) GenServer defmodule Stack do use GenServer @impl true def init(stack) do {:ok, stack} end end GenServer.call(pid, :pop) #=> :hello Client GenServer @impl true def handle_call(:pop, _from, [head | tail]) do {:reply, head, tail} end
  35. {:ok, pid} = GenServer.start_link(Stack, [:hello]) GenServer defmodule Stack do use GenServer @impl true def init(stack) do {:ok, stack} end end GenServer.cast(pid, {:push, :world}) #=> :ok GenServer.call(pid, :pop) #=> :hello Client GenServer @impl true def handle_call(:pop, _from, [head | tail]) do {:reply, head, tail} end @impl true def handle_cast({:push, item}, state) do {:noreply, [item | state]} end
  36. {:ok, pid} = GenServer.start_link(Stack, [:hello]) GenServer.call(pid, :pop) #=> :world GenServer defmodule Stack do use GenServer @impl true def init(stack) do {:ok, stack} end end GenServer.cast(pid, {:push, :world}) #=> :ok GenServer.call(pid, :pop) #=> :hello Client GenServer @impl true def handle_call(:pop, _from, [head | tail]) do {:reply, head, tail} end @impl true def handle_cast({:push, item}, state) do {:noreply, [item | state]} end
  37. Supervisor defmodule KV.Supervisor do use Supervisor def start_link(opts) do Supervisor.start_link(__MODULE__, :ok, opts) end def init(:ok) do children = [ Stack, AnotherChild, AndAnother ] Supervisor.init(children, strategy: :one_for_one) end end
  38. Supervision strategies one_for_one
  39. Supervision strategies one_for_one
  40. Supervision strategies one_for_one
  41. Supervision strategies one_for_one
  42. Supervision strategies one_for_all
  43. Supervision strategies one_for_all
  44. Supervision strategies one_for_all
  45. Supervision strategies one_for_all
  46. Supervision strategies one_for_all
  47. Supervision strategies one_for_all
  48. Supervision strategies rest_for_all
  49. Supervision strategies rest_for_all
  50. Supervision strategies rest_for_all
  51. Supervision strategies rest_for_all
  52. Supervision strategies rest_for_all
  53. Supervision strategies rest_for_all
  54. Let it crash vs defensive programming :ok = do_something_that_can_crash Not :ok? process crashes Supervisors take care of regenerating the system try { somethingThatCanCrash(); } catch (Exception $e) { recoverMaybe(); }
  55. Distribution Node.spawn_link :”bar@computer-name", fn -> Hello.world end Node foo@computer-name Node bar@computer-name
  56. Useful scenarios
  57. Broadcast messages PHP User User’ User’’
  58. Broadcast messages PHP User User’ User’’ Have a look at
  59. Notify selected users PHP User User’’ Some auth
  60. Presence Sarah Daniel Ellen 3 min ago Lukas 2 hours ago
  61. PHP User DB General case
  62. PHP User DB General case
  63. PHP User DB User’ General case
  64. Thinking of problems as particular DBs
  65. Focus in the dataFocus in the logic Think as DB/cacheThink as app/game Logic vs data
  66. Focus in the dataFocus in the logic Think as DB/cacheThink as app/game It is a continuous: We tend to be somewhere in the middle Logic vs data
  67. Demo
  68. Things to consider • Not as easy as other platforms • Not a massive language • Releases & deployment difficult (compared with PHP)
  69. To summarize • Very different platform • Very good for some problems • Great source of ideas • Useful to know even if we don’t end up using it • And even if we don’t want to adopt these ideas!
  70. To know more • https://elixir-lang.org/ Especially the guide MIX AND OTP • Phoenix Framework https://phoenixframework.org/ • Learn You Some Erlang for Great Good https://learnyousomeerlang.com/
  71. Thanks! @nacmartin nacho@limenius.com
Advertisement