Your Monolith, Elixir and You

Your Monolith, Elixir and You

Elixir is great, so clearly we'll all rewrite our applications in Elixir. Mostly, you can't and shouldn't do that. This presentation will show you another path. You’ll see how at Liefery, we started with small steps instead of rewriting everything. This allowed us to reap the benefits earlier and get comfortable before getting deeper into it. We’ll examine in detail the tactics we used to create two Elixir apps for new requirements, and how we integrated them with our existing Rails code base.

8480daec7137f28565bc2d2e666b915a?s=128

Tobias Pfeiffer

May 26, 2018
Tweet

Transcript

  1. 1.
  2. 6.
  3. 7.
  4. 8.
  5. 9.
  6. 13.
  7. 17.
  8. 18.
  9. 19.

    “We rewrote it all in Language x, now it’s 10

    times faster and only 50% of the code!” Someone
  10. 20.

    “Language x, is 10 times faster and requires 50% of

    the code of language Y!” Someone Often implies...
  11. 23.
  12. 26.

    Terraform allows you to incrementally transform an older API into

    one powered by Phoenix - one endpoint at a time. poteto/terraform
  13. 27.

    Terraform allows you to incrementally transform an older API into

    one powered by Phoenix - one endpoint at a time. poteto/terraform Not the Infrastructure As Code
  14. 28.

    defmodule MyApp.Terraformers.Foo do alias MyApp.Clients.Foo use Plug.Router plug :match plug

    :dispatch get "/v1/hello-world", do: send_resp(conn, 200, "Hi") get _ do res = Foo.get!(conn) send_response({:ok, conn, res}) end end poteto/terraform
  15. 33.
  16. 35.

    “Is the technology I’m choosing the right fit for the

    problem I’m trying to solve?” Everyone, hopefully
  17. 55.

    def connect(%{"token" => token}, socket) do token |> JWT.verify_token |>

    respond_based_on_token_contents(socket) end Socket
  18. 56.

    def connect(%{"token" => token}, socket) do token |> JWT.verify_token |>

    respond_based_on_token_contents(socket) end Pattern Match
  19. 57.

    def connect(%{"token" => token}, socket) do token |> JWT.verify_token |>

    respond_based_on_token_contents(socket) end Pipe
  20. 59.

    def join("courier:" <> courier_id, _, %{assigns: %{user: user}}) do if

    authorized?(courier_id, user) do # login else # unauthorizd end end Channel
  21. 60.

    defp authorized?("", _), do: false defp authorized?(courier_id, %{courier_ids: ids}) do

    Enum.member?(ids, String.to_integer(courier_id)) end defp authorized?(_, _), do: false Channel
  22. 61.

    defp authorized?("", _), do: false defp authorized?(courier_id, %{courier_ids: ids}) do

    Enum.member?(ids, String.to_integer(courier_id)) end defp authorized?(_, _), do: false Channel
  23. 62.

    defp authorized?("", _), do: false defp authorized?(courier_id, %{courier_ids: ids}) do

    Enum.member?(ids, String.to_integer(courier_id)) end defp authorized?(_, _), do: false Channel
  24. 63.

    defp authorized?("", _), do: false defp authorized?(courier_id, %{courier_ids: ids}) do

    Enum.member?(ids, String.to_integer(courier_id)) end defp authorized?(_, _), do: false Channel
  25. 64.

    defp authorized?("", _), do: false defp authorized?(courier_id, %{courier_ids: ids}) do

    Enum.member?(ids, String.to_integer(courier_id)) end defp authorized?(_, _), do: false Channel
  26. 80.

    defmodule Fulfillment.OrderCreation do def create(params, customer, auth) do with {:ok,

    order} <- validate_order(params, customer), {:ok, order} <- validate_in_backend(order, auth), {:ok, order} <- Repo.insert(order) do {:ok, order} else {:error, changeset} -> {:error, changeset} end end end
  27. 81.

    defmodule Fulfillment.OrderCreation do def create(params, customer, auth) do with {:ok,

    order} <- validate_order(params, customer), {:ok, order} <- validate_in_backend(order, auth), {:ok, order} <- Repo.insert(order) do {:ok, order} else {:error, changeset} -> {:error, changeset} end end end “Success” Rail
  28. 82.

    defmodule Fulfillment.OrderCreation do def create(params, customer, auth) do with {:ok,

    order} <- validate_order(params, customer), {:ok, order} <- validate_in_backend(order, auth), {:ok, order} <- Repo.insert(order) do {:ok, order} else {:error, changeset} -> {:error, changeset} end end end “Error” Rail
  29. 83.

    defmodule Fulfillment.OrderCreation do def create(params, customer, auth) do with {:ok,

    order} <- validate_order(params, customer), {:ok, order} <- validate_in_backend(order, auth), {:ok, order} <- Repo.insert(order) do {:ok, order} else {:error, changeset} -> {:error, changeset} end end end Validate internally
  30. 84.

    defmodule Fulfillment.OrderCreation do def create(params, customer, auth) do with {:ok,

    order} <- validate_order(params, customer), {:ok, order} <- validate_in_backend(order, auth), {:ok, order} <- Repo.insert(order) do {:ok, order} else {:error, changeset} -> {:error, changeset} end end end Validate externally
  31. 85.

    defmodule Fulfillment.OrderCreation do def create(params, customer, auth) do with {:ok,

    order} <- validate_order(params, customer), {:ok, order} <- validate_in_backend(order, auth), {:ok, order} <- Repo.insert(order) do {:ok, order} else {:error, changeset} -> {:error, changeset} end end end Save
  32. 86.

    defmodule Fulfillment.OrderCreation do def create(params, customer, auth) do with {:ok,

    order} <- validate_order(params, customer), {:ok, order} <- validate_in_backend(order, auth), {:ok, order} <- Repo.insert(order) do {:ok, order} else {:error, changeset} -> {:error, changeset} end end end Done
  33. 94.
  34. 97.
  35. 99.
  36. 102.
  37. 103.
  38. 104.

    “We are still using this like Rails – we should

    use GenServers!” Someone on your team
  39. 106.