···21 Supervisor.start_link(__MODULE__, arg, name: __MODULE__)
22 end
2324- @immpl true
25- def init(_arg) do
26 children = [
27- Drinkup,
28- ExampleRecordConsumer
29 ]
3031 Supervisor.init(children, strategy: :one_for_one)
···21 Supervisor.start_link(__MODULE__, arg, name: __MODULE__)
22 end
2324+ @impl true
25+ def init(_) do
26 children = [
27+ {Drinkup, %{module: ExampleRecordConsumer}}
028 ]
2930 Supervisor.init(children, strategy: :one_for_one)
+1-50
lib/consumer.ex
···3 An unopinionated consumer of the Firehose. Will receive all events, not just commits.
4 """
56- alias Drinkup.{ConsumerGroup, Event}
78 @callback handle_event(Event.t()) :: any()
9-10- defmacro __using__(_opts) do
11- quote location: :keep do
12- use GenServer
13- require Logger
14-15- @behaviour Drinkup.Consumer
16-17- def child_spec(opts) do
18- %{
19- id: __MODULE__,
20- start: {__MODULE__, :start_link, [opts]},
21- type: :worker,
22- restart: :permanent,
23- max_restarts: 0,
24- shutdown: 500
25- }
26- end
27-28- def start_link(opts) do
29- GenServer.start_link(__MODULE__, [], opts)
30- end
31-32- @impl GenServer
33- def init(_) do
34- ConsumerGroup.join()
35- {:ok, nil}
36- end
37-38- @impl GenServer
39- def handle_info({:event, event}, state) do
40- {:ok, _pid} =
41- Task.start(fn ->
42- try do
43- __MODULE__.handle_event(event)
44- rescue
45- e ->
46- Logger.error(
47- "Error in event handler: #{Exception.format(:error, e, __STACKTRACE__)}"
48- )
49- end
50- end)
51-52- {:noreply, state}
53- end
54-55- defoverridable GenServer
56- end
57- end
58end
···3 An unopinionated consumer of the Firehose. Will receive all events, not just commits.
4 """
56+ alias Drinkup.Event
78 @callback handle_event(Event.t()) :: any()
00000000000000000000000000000000000000000000000009end
-39
lib/consumer_group.ex
···1-defmodule Drinkup.ConsumerGroup do
2- @moduledoc """
3- Register consumers and dispatch events to them.
4- """
5-6- alias Drinkup.Event
7-8- @scope __MODULE__
9- @group :consumers
10-11- def start_link(_) do
12- :pg.start_link(@scope)
13- end
14-15- def child_spec(opts) do
16- %{
17- id: __MODULE__,
18- start: {__MODULE__, :start_link, [opts]},
19- type: :worker,
20- restart: :permanent,
21- shutdown: 500
22- }
23- end
24-25- @spec join() :: :ok
26- def join(), do: join(self())
27-28- @spec join(pid()) :: :ok
29- def join(pid), do: :pg.join(@scope, @group, pid)
30-31- @spec dispatch(Event.t()) :: :ok
32- def dispatch(event) do
33- @scope
34- |> :pg.get_members(@group)
35- |> Enum.each(&send(&1, {:event, event}))
36- end
37-38- # TODO: read `:pg` docs on what `monitor` is used fo
39-end
···000000000000000000000000000000000000000
+12-5
lib/drinkup.ex
···1defmodule Drinkup do
2 use Supervisor
34- def start_link(arg \\ []) do
5- Supervisor.start_link(__MODULE__, arg, name: __MODULE__)
00000006 end
78- def init(_) do
9 children = [
10- Drinkup.ConsumerGroup,
11- Drinkup.Socket
12 ]
1314 Supervisor.init(children, strategy: :one_for_one)