Successfully reported this slideshow.
We use your LinkedIn profile and activity data to personalize ads and to show you more relevant ads. You can change your ad preferences anytime.

Elixir, your Monolith and You

1,025 views

Published on


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.

Join us on our tale of adopting Elixir and Phoenix and see what we learned, what we loved, and what bumps we hit along the road

Published in: Technology
  • Be the first to comment

  • Be the first to like this

Elixir, your Monolith and You

  1. 1. Who wants to go and build a system in Elixir?
  2. 2. Can't go out and rewrite it all
  3. 3. You shouldn’t
  4. 4. Elixir, your Monolith and You (alpha-1) Tobias Pfeiffer @PragTob pragtob.info
  5. 5. Your Monolith and You
  6. 6. Your Monolith now?
  7. 7. Your Monolith?
  8. 8. Tear it all down and rewrite it
  9. 9. Sooooon!
  10. 10. “We rewrote it all in Language x, now it’s 10 times faster and only 50% of the code!” Someone
  11. 11. “Language x, is 10 times faster and requires 50% of the code of language Y!” Someone Often implies...
  12. 12. What nobody tells you...
  13. 13. Business Value?
  14. 14. Sooooon!
  15. 15. Replace it step by step
  16. 16. We have a bedroom, for the bathroom please check out legacy!
  17. 17. Terraform allows you to incrementally transform an older API into one powered by Phoenix - one endpoint at a time. poteto/terraform
  18. 18. 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
  19. 19. Replace a critical component
  20. 20. Check out our sweet new heating system!
  21. 21. Write a new component
  22. 22. Check it out we built a brand new high tech entertainment facility!
  23. 23. Write a new component Obvious in microservices
  24. 24. “Is the technology I’m choosing the right fit for the problem I’m trying to solve?” Everyone, hopefully
  25. 25. Reasonably separate and limited problem
  26. 26. Requirement that poses a problem for the current stack
  27. 27. Spark of Enthusiasm
  28. 28. Courier Tracking
  29. 29. Courier Tracking
  30. 30. Courier Tracking
  31. 31. Courier Tracking Websockets
  32. 32. Courier Tracking Websockets Basic Knowledge
  33. 33. How to make them talk?
  34. 34. Monolith FrontendCourier DB
  35. 35. MonolithTracking FrontendCourier DB DB
  36. 36. Connect them?
  37. 37. MonolithTracking FrontendCourier DB DB
  38. 38. JSON Web Token
  39. 39. Header Payload Signature
  40. 40. { "role": "admin", "courier_ids": [1337, 55], "id": 42, "exp": 1520469475 }
  41. 41. MonolithTracking FrontendCourier DB DB Shared Secret
  42. 42. MonolithTracking FrontendCourier DB DB JWT JWT Shared Secret
  43. 43. MonolithTracking FrontendCourier DB DB JWTJWT JWT Shared Secret JWT
  44. 44. def connect(%{"token" => token}, socket) do token |> JWT.verify_token |> respond_based_on_token_contents(socket) end Socket
  45. 45. defp login_user(%{"role" => role, ...}, socket) do {:ok, assign(socket, :user, %{role: role, ...})} end Socket
  46. 46. def join("courier:" <> courier_id, _, % {assigns: %{user: user}}) do if authorized?(courier_id, user) do # login else # unauthorizd end end Channel
  47. 47. 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
  48. 48. MonolithTracking FrontendCourier DB DB LocationsLocations Most of the time
  49. 49. Fulfillment
  50. 50. Fulfillment CRUD
  51. 51. Fulfillment CRUD Experience
  52. 52. MonolithFulfillment DB DB
  53. 53. MonolithFulfillment DB DB Own UI
  54. 54. MonolithFulfillment DB DB OAuth OAuth
  55. 55. MonolithFulfillment DB DB /current_user Who?
  56. 56. MonolithFulfillment DB DB Products
  57. 57. MonolithFulfillment DB DB Order Valid?Order
  58. 58. MonolithFulfillment DB DB Packaging Create
  59. 59. Rail-way oriented programming!
  60. 60. Railway Oriented Programming
  61. 61. 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
  62. 62. 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
  63. 63. 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
  64. 64. 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
  65. 65. 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
  66. 66. 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
  67. 67. No Kafka/Message Queue?
  68. 68. Be careful with new technologies!
  69. 69. Microservices!
  70. 70. Microservices! ”Macroapplications”
  71. 71. All challenges are clearly technical
  72. 72. All challenges are clearly technical
  73. 73. Stakeholders
  74. 74. Your team
  75. 75. First Major Version
  76. 76. Get the others on board
  77. 77. Workshops
  78. 78. To know it, you got to build it
  79. 79. Pair Adopter with Alchemist
  80. 80. Pair Adopter with Alchemist Alchemist doesn’t touch keyboard
  81. 81. Knowledge
  82. 82. Knowledge
  83. 83. “We are still using this like Rails – we should use GenServers!” Someone on your team
  84. 84. You don’t need to kill your Monolith, Complement it
  85. 85. Your Apps
  86. 86. Enjoy using Elixir effectively to help your company Tobias Pfeiffer @PragTob pragtob.info

×