Skip to content

Commit

Permalink
Remove after_start/0 and update tests and docs
Browse files Browse the repository at this point in the history
  • Loading branch information
dvic committed Sep 20, 2024
1 parent f24f5fc commit ed12cae
Show file tree
Hide file tree
Showing 10 changed files with 65 additions and 17 deletions.
2 changes: 1 addition & 1 deletion guides/Events.md
Original file line number Diff line number Diff line change
Expand Up @@ -87,8 +87,8 @@ This will ensure the handler only receives events appended to that stream.

### Event handler callbacks

- `c:Commanded.Event.Handler.init/0` - (optional) initialisation callback function called when the handler starts.
- `c:Commanded.Event.Handler.init/1` - (optional) used to configure the handler before it starts.
- `c:Commanded.Event.Handler.after_start/1` - (optional) initialisation callback function called in the process of the started handler.
- `c:Commanded.Event.Handler.error/3` - (optional) called when an event handle/2 callback returns an error.

### Metadata
Expand Down
2 changes: 1 addition & 1 deletion guides/Usage.md
Original file line number Diff line number Diff line change
Expand Up @@ -104,7 +104,7 @@ Here's an example bank account opening feature built using Commanded to demonstr
application: BankApp,
name: __MODULE__

def init do
def after_start(_state) do
with {:ok, _pid} <- Agent.start_link(fn -> 0 end, name: __MODULE__) do
:ok
end
Expand Down
22 changes: 12 additions & 10 deletions lib/commanded/event/handler.ex
Original file line number Diff line number Diff line change
Expand Up @@ -344,7 +344,7 @@ defmodule Commanded.Event.Handler do
@type subscribe_from :: :origin | :current | non_neg_integer()
@type consistency :: :eventual | :strong

@doc deprecated: "Use the initialize/1 callback instead."
@doc deprecated: "Use the after_start/1 callback instead."
@callback init() :: :ok | {:stop, reason :: any()}

@doc """
Expand All @@ -364,7 +364,7 @@ defmodule Commanded.Event.Handler do
name: "ExampleHandler"
# Optional initialisation
def initialize(_handler_state) do
def after_start(_handler_state) do
:ok
end
Expand All @@ -375,7 +375,7 @@ defmodule Commanded.Event.Handler do
end
"""
@callback initialize(handler_state :: term()) :: :ok | {:stop, reason :: any()}
@callback after_start(handler_state :: term()) :: :ok | {:stop, reason :: any()}

@doc """
Optional callback function called to configure the handler before it starts.
Expand Down Expand Up @@ -603,18 +603,15 @@ defmodule Commanded.Event.Handler do
end

@doc false
def init, do: :ok

@doc false
def initialize(_state), do: init()
def after_start(_state), do: :ok

@doc false
def init(config), do: {:ok, config}

@doc false
def before_reset, do: :ok

defoverridable init: 0, init: 1, initialize: 1, before_reset: 0
defoverridable init: 1, after_start: 1, before_reset: 0
end
end

Expand Down Expand Up @@ -782,12 +779,17 @@ defmodule Commanded.Event.Handler do

%Handler{handler_module: handler_module} = state

case handler_module.initialize(state.handler_state) do
if function_exported?(handler_module, :init, 0) do
IO.warn("#{inspect(handler_module)}.init/0 is deprecated, use after_start/1 instead")
:ok = handler_module.init()
end

case handler_module.after_start(state.handler_state) do
:ok ->
{:noreply, state}

{:stop, reason} ->
Logger.debug(describe(state) <> " `init/0` callback has requested to stop")
Logger.debug(describe(state) <> " `after_start/1` callback has requested to stop")

{:stop, reason, state}
end
Expand Down
2 changes: 1 addition & 1 deletion test/event/support/appending_event_handler.ex
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ defmodule Commanded.Event.AppendingEventHandler do
application: Commanded.DefaultApp,
name: __MODULE__

def init do
def after_start(_state) do
with {:ok, _pid} <- Agent.start_link(fn -> %{events: [], metadata: []} end, name: __MODULE__) do
:ok
end
Expand Down
2 changes: 1 addition & 1 deletion test/event/support/concurrency/concurrent_event_handler.ex
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ defmodule Commanded.Event.ConcurrentEventHandler do
concurrency: 5

@impl Commanded.Event.Handler
def init do
def after_start(_state) do
Process.send(:test, {:init, self()}, [])
end

Expand Down
2 changes: 1 addition & 1 deletion test/event/support/concurrency/partition_event_handler.ex
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ defmodule Commanded.Event.PartitionEventHandler do
concurrency: 5

@impl Commanded.Event.Handler
def init do
def after_start(_state) do
Process.send(:test, {:init, self()}, [])
end

Expand Down
9 changes: 9 additions & 0 deletions test/event/support/init/after_start_handler.ex
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
defmodule Commanded.Event.AfterStartHandler do
use Commanded.Event.Handler,
application: Commanded.MockedApp,
name: __MODULE__

def after_start(_state) do
Process.send(:test, {:after_start, self()}, [])
end
end
37 changes: 37 additions & 0 deletions test/event_handler_after_start_test.exs
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
defmodule Commanded.Event.HandlerAfterStartTest do
use Commanded.MockEventStoreCase

import Mox

alias Commanded.Event.AfterStartHandler
alias Commanded.EventStore.Adapters.Mock, as: MockEventStore

describe "event handler `after_start/1` callback" do
setup do
true = Process.register(self(), :test)

expect(MockEventStore, :subscribe_to, fn
_event_store, :all, handler_name, handler, _subscribe_from, _opts ->
assert is_binary(handler_name)

{:ok, handler}
end)

handler = start_supervised!(AfterStartHandler)

[handler: handler]
end

test "should be called after subscription subscribed", %{handler: handler} do
refute_receive {:after_start, ^handler}

send_subscribed(handler)

assert_receive {:after_start, ^handler}
end
end

defp send_subscribed(handler) do
send(handler, {:subscribed, handler})
end
end
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ defmodule Commanded.ExampleDomain.BankAccount.AccountBalanceHandler do
alias Commanded.ExampleDomain.BankAccount.Events.MoneyDeposited
alias Commanded.ExampleDomain.BankAccount.Events.MoneyWithdrawn

def init do
def after_start(_state) do
with {:ok, _pid} <- Agent.start_link(fn -> 0 end, name: __MODULE__) do
:ok
end
Expand Down
2 changes: 1 addition & 1 deletion test/example_domain/bank_account/bank_account_handler.ex
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ defmodule Commanded.ExampleDomain.BankAccount.BankAccountHandler do

alias Commanded.ExampleDomain.BankAccount.Events.BankAccountOpened

def init do
def after_start(_state) do
case Agent.start_link(fn -> %{prefix: "", accounts: []} end, name: __MODULE__) do
{:ok, _} -> :ok
{:error, {:already_started, _}} -> :ok
Expand Down

0 comments on commit ed12cae

Please sign in to comment.