commanded / commanded

Use Commanded to build Elixir CQRS/ES applications

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Commanded calling apply/2 on wrong aggregate

manoadamro opened this issue · comments

I stumbled accross this problem while trying to create a new aggregate (rather than having everything all in one)
but no matter what I do, it doesn't seem call execute on any aggregate, but tries to call apply on the wrong one (and fails to find it).

Have I misunderstood how the router works? (snippet below)

Plan:

PatientAggregate: CreatePatient -> PatientCreated
DiffAggregate : AddChunk -> ChunkAdded

Reality:

PatientAggregate : ??? -> ???
DiffAggregate : ??? -> PatientCreated

Router:

  identify(DiffAggregate, by: :system_id)
  dispatch(AddChunk, to: DiffAggregate)

  identify(PatientAggregate, by: :system_id)
  dispatch(CreatePatient, to: PatientAggregate)

PatientAggregate:

  def execute(%__MODULE__{system_id: nil}, %CreatePatient{system_id: system_id, patient: patient})
        returns PatientCreated        

  def apply(%__MODULE__{}, %PatientCreated{system_id: system_id, patient: patient})

DiffAggregate:

  def execute(%__MODULE__{system_id: system_id}, %AddChunk{system_id: system_id, chunk: new_chunk})
        returns ChunkAdded

  def apply(%__MODULE__{system_id: nil}, %ChunkAdded{system_id: system_id, chunk: chunk, chunks: chunks} )

Dispatch

  Application.dispatch(%CreatePatient{
    system_id: patient_id,
    patient: patient
  })

The Error:

(codepilot 0.1.0) lib/codepilot_events/batch_file_uploads/aggregates/diff_aggregate.ex:33: CodepilotEvents.BatchFileUploadEvents.Aggregates.DiffAggregate.apply(
  %CodepilotEvents.BatchFileUploadEvents.Aggregates.DiffAggregate{
    chunks: ..., last_chunk: ..., system_id: ...
  }, 
  %CodepilotEvents.Patients.Events.PatientCreated{
    patient: %{
      age: ..., id: ..., practice_id: ..., system_id: ...
    }, 
    system_id: ...
  }
)

As you can see, despite what the router is configured to do, it calls PatientCreated on the DiffAggregate instead of the PatientAggregate

The line (33) it mentions in the error is in fact:

  def apply(%__MODULE__{system_id: _system_id}, %ChunkAdded{chunk: chunk, chunks: chunks})

which is the only apply function in this new aggregate, so it fails to match

It looks like you are sharing the same aggregate identity (:system_id) between two different types of aggregates. This means that events persisted for one type of aggregate will be retrieved when loading the other aggregate type for the same system_id.

You can use an identity prefix in the router to differentiate between the two aggregate types so that they can share a system_id as follows:

identify(DiffAggregate, by: :system_id, prefix: "diff-")
dispatch(AddChunk, to: DiffAggregate)

identify(PatientAggregate, by: :system_id, prefix: "patient-")
dispatch(CreatePatient, to: PatientAggregate)