Upgrade to Pro — share decks privately, control downloads, hide ads and more …

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.

Tobias Pfeiffer

May 26, 2018
Tweet

More Decks by Tobias Pfeiffer

Other Decks in Programming

Transcript

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

    times faster and only 50% of the code!” Someone
  2. “Language x, is 10 times faster and requires 50% of

    the code of language Y!” Someone Often implies...
  3. Terraform allows you to incrementally transform an older API into

    one powered by Phoenix - one endpoint at a time. poteto/terraform
  4. 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
  5. 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
  6. “Is the technology I’m choosing the right fit for the

    problem I’m trying to solve?” Everyone, hopefully
  7. def connect(%{"token" => token}, socket) do token |> JWT.verify_token |>

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

    respond_based_on_token_contents(socket) end Pattern Match
  9. def connect(%{"token" => token}, socket) do token |> JWT.verify_token |>

    respond_based_on_token_contents(socket) end Pipe
  10. def join("courier:" <> courier_id, _, %{assigns: %{user: user}}) do if

    authorized?(courier_id, user) do # login else # unauthorizd end end Channel
  11. 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
  12. 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
  13. 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
  14. 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
  15. 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
  16. 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
  17. 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
  18. 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
  19. 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
  20. 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
  21. 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
  22. 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
  23. “We are still using this like Rails – we should

    use GenServers!” Someone on your team