fabriziosestito / commanded-spear-adapter

Spear event store adapter for Commanded
MIT License
19 stars 5 forks source link

Handling of system events not working correctly in master #90

Open philipgiuliani opened 7 months ago

philipgiuliani commented 7 months ago

In the latest version in master there is a problem with the system events again. When deleting an event, the following error comes up:

** (Protocol.UndefinedError) protocol Jason.Encoder not implemented for %Spear.Event{id: "ac30fd24-56af-4084-a506-e83c60ebfd9d", type: "$>", body: "3@test1708017305-beneficiary-9WYJCVLSUFE7", link: nil, metadata: %{created: ~U[2024-02-15 17:15:08.446608Z], content_type: "application/octet-stream", stream_name: "$ce-test1708017305", prepare_position: 69086811, commit_position: 69086811, custom_metadata: "{\"$v\":\"3:-1:1:4\",\"$c\":69086169,\"$p\":69086169,\"$o\":\"test1708017305-beneficiary-9WYJCVLSUFE7\",\"$causedBy\":\"cb89d3c2-8de9-4aa8-8cc4-ef541921cdc4\",\"$correlationId\":\"d60b52f4-1417-46a3-8e0c-166a95d3c731\"}", stream_revision: 9}} of type Spear.Event (a struct), Jason.Encoder protocol must always be explicitly implemented.

If you own the struct, you can derive the implementation specifying which fields should be encoded to JSON:

    @derive {Jason.Encoder, only: [....]}
    defstruct ...

It is also possible to encode all fields, although this should be used carefully to avoid accidentally leaking private information when new fields are added:

    @derive Jason.Encoder
    defstruct ...

Finally, if you don't own the struct you want to encode to JSON, you may use Protocol.derive/3 placed outside of any module:

    Protocol.derive(Jason.Encoder, NameOfTheStruct, only: [...])
    Protocol.derive(Jason.Encoder, NameOfTheStruct)
....
    (jason 1.4.1) lib/jason.ex:164: Jason.encode!/2
    (commanded_spear_adapter 1.0.0-dev) lib/commanded/event_store/adapters/spear/mapper.ex:131: Commanded.EventStore.Adapters.Spear.Mapper.to_proposed_message/3
    (elixir 1.15.7) lib/stream.ex:613: anonymous fn/4 in Stream.map/2
    (elixir 1.15.7) lib/enum.ex:4830: Enumerable.List.reduce/3
    (elixir 1.15.7) lib/stream.ex:1828: Enumerable.Stream.do_each/4
    (elixir 1.15.7) lib/stream.ex:1052: Stream.do_transform_inner_enum/7
    (elixir 1.15.7) lib/stream.ex:1828: Enumerable.Stream.do_each/4
    (spear 1.4.0) lib/spear/connection/request.ex:113: Spear.Connection.Request.emit_messages/2
    (spear 1.4.0) lib/spear/connection.ex:416: Spear.Connection.request_and_stream_body/4
    (spear 1.4.0) lib/spear/connection.ex:276: Spear.Connection.handle_call/3
    (connection 1.1.0) lib/connection.ex:488: Connection.handle_call/3
    (stdlib 5.1.1) gen_server.erl:1113: :gen_server.try_handle_call/4
    (stdlib 5.1.1) gen_server.erl:1142: :gen_server.handle_msg/6
    (stdlib 5.1.1) proc_lib.erl:241: :proc_lib.init_p_do_apply/3

These errors were fixed with https://github.com/fabriziosestito/commanded-spear-adapter/issues/10 before. /cc @dvic

philipgiuliani commented 7 months ago

The whole event looks like this:

%Commanded.EventStore.EventData{
   causation_id: "281ca4b2-4ed4-4e9a-a4af-e31c4db5fc74",
   correlation_id: "042f2ba4-6d12-4042-8103-41a32cee5976",
   event_type: "Elixir.Dia.Projects.Events.AssistantRemoved",
   data: %Dia.Projects.Events.AssistantRemoved{
     assistant_id: "MA4676WJFGQZ",
     applicant_id: "EPC244RCPCHZ",
     id: "ef377a8b-0b86-4301-a864-6223352c710f"
   },
   metadata: %{
     link: %Spear.Event{
       id: "23aef121-84d2-4a3e-9689-bcec358d09ee",
       type: "$>",
       body: "3@test1708018151-beneficiary-MA4676WJFGQZ",
       link: nil,
       metadata: %{
         created: ~U[2024-02-15 17:29:14.825739Z],
         content_type: "application/octet-stream",
         stream_name: "$ce-test1708018151",
         prepare_position: 76359753,
         commit_position: 76359753,
         custom_metadata: "{\"$v\":\"3:-1:1:4\",\"$c\":76359446,\"$p\":76359446,\"$o\":\"test1708018151-beneficiary-MA4676WJFGQZ\",\"$causedBy\":\"b71573d9-e0f4-466e-adc3-d0a88a316154\",\"$correlationId\":\"042f2ba4-6d12-4042-8103-41a32cee5976\"}",
         stream_revision: 9
       }
     }
   }
 }
philipgiuliani commented 7 months ago

I wasn't able to understand this code well enough. In the meanwhile I added an ugly try/rescue and the system seems to behave correctly.

custom_metadata =
      if event_type == "$>" do
        ""
      else
        try do
          serialize_metadata(event, serializer)
        rescue
          _ ->
            ""
        end
dvic commented 7 months ago

It looks like, somehow the metadata ended up containing a link (Spear.Event).

Can you check if replacing metadata in https://github.com/fabriziosestito/commanded-spear-adapter/blob/fcf18250f28ce495688ba2257108d9c15e29d8a7/lib/commanded/event_store/adapters/spear/mapper.ex#L173 with (metadata != nil && Map.reject(metadata, fn {_, value} -> is_struct(value, Spear.Event) end)) fixes the issue?