Publishing events without a command or aggregate with commanded

Just wanted to note an update because it seems our posts are immutable (as expected for an Elixir community): the :version can probably be better off having :any_version instead of 0.

defmodule Core.Cmd.Evt do
  alias Commanded.EventStore
  alias Commanded.Event.Mapper

  def dispatch(e) do
    dispatch(e, [])
  end

  def dispatch(event, opts) when is_struct(event) do
    dispatch([event], opts)
  end

  def dispatch(events, opts) when is_list(events) do
    EventStore.append_to_stream(
      Core.Cmd,
      Keyword.get(opts, :stream_id, "manual_event_stream"),
      Keyword.get(opts, :version, :any_version),
      Mapper.map_to_event_data(events,
        correlation_id: Keyword.get(opts, :correlation_id, UUID.uuid4()),
        causation_id: Keyword.get(opts, :causation_id, UUID.uuid4()),
        metadata: Keyword.get(opts, :metadata, %{})
      )
    )
  end
end

The unfortunate downside with this technique is that the InMemoryEventStore can’t really be used for testing, but the positive side is that Mox can be a better substitute with the appropriate behaviour defined.

defmodule Core.Cmd.Evt.Behaviour do
  @callback dispatch(event :: map() | struct() | list(struct())) ::
              :ok | {:ok, term()} | {:error, reason :: term()}
  @callback dispatch(event :: list(struct()), opts :: keyword()) ::
              :ok | {:ok, term()} | {:error, reason :: term()}
end

with

# test/support/test_helper.exs
Mox.defmock(MockEvt, for: Core.Cmd.Evt.Behaviour)

and with functions that take in an event dispatcher parameter.