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

Protocols and Structs

Protocols and Structs

Processing a data flow in Elixir

8f29619526ac4fb3d9b78c82eaa5e40e?s=128

Claudio Ortolina

December 02, 2015
Tweet

Transcript

  1. PROTOCOLS AND STRUCTS FOR EFFECTIVE DATA FLOW

  2. THE DOMAIN CHECK-IN PROCESS NOTIFY

  3. RECAP ABOUT PROTOCOLS AND STRUCTS

  4. STRUCTS defmodule Checkin do defstruct id: nil, lat: 0.0, lng:

    0.0 end
  5. STRUCTS %Checkin{id: "123", lat: 51.50, lng: 0.12} struct(Checkin, id: "123",

    lat: 51.50, lng: 0.12) struct(Checkin, %{id: "123", lat: 51.50, lng: 0.12}) struct(Checkin, id: "123", lat: 51.50, lng: 0.12, ignored: true)
  6. PROTOCOLS defprotocol Persistence do def create(thing) end

  7. IMPLEMENTATION defimpl Persistence, for: Checkin do def create(checkin) do %Doc{class:

    "Checkin", fields: Map.from_struct(checkin)} |> Repo.create end end
  8. FALLBACK defprotocol Persistence do @fallback_to_any true def create(thing) end

  9. FALLBACK defimpl Persistence, for: Any do def create(thing) do class

    = Map.get(thing, :__struct__) |> to_string %Doc{class: class, fields: Map.from_struct(thing)} |> Repo.create end end
  10. USAGE %Checkin{id: "123", lat: 51.50, lng: 0.12} |> Persistence.create

  11. FLOW MESSAGE IDENTIFY LOG PROCESS LOG NOTIFY

  12. FLOW MESSAGE IDENTIFY LOG PROCESS LOG NOTIFY

  13. IDENTIFY { "meta" : { "version" : 1, "topic" :

    "checkins", "type" : "create", "request_id" : "15456d4e-782b-11e5-8bcf-feff819cdc9f" }, "data" : { "ref" : "123ASDS", "lat" : 51.50, "lng" : 0.12 } }
  14. IDENTIFY defmodule V1.Checkin.Create do defstruct request_id: nil, ref: nil, lat:

    0.0, lng: 0.0 end
  15. IDENTIFY def identify(payload) do case payload["meta"] do %{"version" => 1,

    "topic" => "checkins", "type" => "create"} -> V1.Checkins.Create _other -> {:error, :unsupported_payload} end end
  16. POPULATE def populate(struct_name, payload) do request_id = get_in(payload, "meta", "request_id")

    struct_attrs = Map.put(payload["data"], "request_id", request_id) Kernel.struct(struct_name, Utils.atomise_map(struct_attrs)) end
  17. ALL TOGETHER NOW message |> identify |> populate(message)

  18. WINS STABLE INTERFACE DEFINES A BOUNDARY EXTENSIBLE INTENTION REVEALING

  19. FLOW MESSAGE IDENTIFY LOG PROCESS LOG NOTIFY

  20. LOG defimpl String.Chars, for: V1.Checkins.Create do def to_string(create_struct) do "type=create

    status=accepted request_id=#{create_struct.request_id} ref={create_struct.ref}" end end
  21. LOG def log(item) do :ok = Logger.info item item end

  22. ALL TOGETHER NOW message |> identify |> populate(message) |> log

  23. FLOW MESSAGE IDENTIFY LOG PROCESS LOG NOTIFY

  24. PROCESS defimpl Job, for: V1.Checkin.Create do def process(create_struct) do {:ok,

    new_record} = Persistence.create(create_struct) %V1.Checkin.Created{request_id: create_struct.request_id, record: new_record} end end
  25. ALL TOGETHER NOW message |> identify |> populate(message) |> log

    |> Job.process
  26. WINS STABLE INTERFACE DEFINES A BOUNDARY EXTENSIBLE INTENTION REVEALING

  27. FLOW MESSAGE IDENTIFY LOG PROCESS LOG NOTIFY

  28. LOG defimpl String.Chars, for: V1.Checkins.Created do def to_string(created_struct) do "type=create

    status=processed request_id=#{create_struct.request_id} id={created_struct.record.id}" end end
  29. ALL TOGETHER NOW message |> identify |> populate(message) |> log

    |> Job.process |> log
  30. NOTIFY MESSAGE IDENTIFY LOG PROCESS LOG NOTIFY

  31. NOTIFY defimpl Notify, for: V1.Checkin.Created do def topics(created_struct), do: ["checkins",

    "users"] def to_message(created_struct) do %Message{request_id: created_struct.request_id, type: :create, data: %{id: created_struct.record.id}} end end
  32. NOTIFY def notify(item) do payload = Notify.to_message(item) topics = Notify.topics(item)

    PubSub.broadcast(payload, topics) end
  33. ALL TOGETHER NOW message |> identify |> populate(message) |> log

    |> Job.process |> log |> notify
  34. EXECUTION MESSAGE IDENTIFY LOG PROCESS LOG NOTIFY LISTENER PROCESS POOL

    PUBSUB POOL
  35. EXTENDING FURTHER ADD NEW STRUCTS IMPLEMENT PROTOCOLS

  36. CORE IDEAS ASSIGN INTENT TO DATA DEFINE FUNCTIONALITY AS PROTOCOLS

    DEFINE STRICT BOUNDARIES BETWEEN STEPS
  37. THANK YOU! http://bit.ly/ff-protocols-structs

  38. PLUG ELIXIR, JAVASCRIPT, ELM DEVELOPMENT ELIXIR, JAVASCRIPT, ELM TRAINING ASK

    ME ABOUT IT!