blunt-elixir / blunt

CQRS Tools for Elixir
13 stars 2 forks source link

Migration from cqrs_tools #10

Open yleflour opened 1 year ago

yleflour commented 1 year ago

I first of all thank you for cqrs_tools and blunt.

We are trying to migrate to blunt but have no idea on how to apply the migration. Do you have a sample project we could use ?

(Edit) Steps to migrate

I will live update this comment with the steps followed to migrate from cqrs_tools to blunt. Please note that as we didn't use every available cqrs_tools feature, not everything will be documented

Install blunt

# mix.exs
defp deps do
     [ {:blunt, github: "blunt-elixir/blunt", ref: "reorg", sparse: "apps/blunt", override: true},
      {:blunt_data,
       github: "blunt-elixir/blunt", ref: "reorg", sparse: "apps/blunt_data", override: true},
      {:blunt_ddd,
       github: "blunt-elixir/blunt", ref: "reorg", sparse: "apps/blunt_ddd", override: true},
      {:blunt_absinthe,
       github: "blunt-elixir/blunt", ref: "reorg", sparse: "apps/blunt_absinthe", override: true},
      {:blunt_absinthe_relay,
       github: "blunt-elixir/blunt",
       ref: "reorg",
       sparse: "apps/blunt_absinthe_relay",
       override: true}]
end

Replace imports

A find and replace from Cqrs to Blunt will handle ~80% of the migration

Message

Common struct patterns have been factored into Blunt.Message

It is used by (at least):

Options

The option require_all_fields is now require_all_fields?

Behaviors

If using specific @impl (such as @impl Cqrs.ValueObject) for please note that it now implements Blunt.Message. This is important for migrating:

DomainEvent

Query

Absinthe

trbngr commented 1 year ago

I'm sorry I didn't see this earlier.

Here is a demo. It's a little bit outdated, but the core public Blunt API has not changed.

https://github.com/trbngr/thetamind

yleflour commented 1 year ago

Thanks

I've encountered issues while migrating ValueObject:

trbngr commented 1 year ago

hi @yleflour

can you create a small example that demonstrates the issues you're facing? I will have an easier time understanding that way.

I'll check on float fields now.

trbngr commented 1 year ago

Thanks for reporting the float field issue. It's fixed now on the reorg branch.

trbngr commented 1 year ago

BTW: handle_validate/2 is defined on all message types. https://github.com/blunt-elixir/blunt/blob/reorg/apps/blunt/lib/blunt/message.ex#L40

yleflour commented 1 year ago

Thanks, during the migration I used @impl Blunt.ValueObject for handle_validate but the behavior is defined in Blunt.Message

Should allow us to move forward with the migration

yleflour commented 1 year ago

Just renamed the issue so others can find it. I'll try to write a PR with a migrating_from_cqrs_tools.md file once cleared. In the meantime, I'll update the top comment with steps followed

yleflour commented 1 year ago

Hi @trbngr got quite far but I'm getting stuck on pipeline setup

trbngr commented 1 year ago

Hi @yleflour

I'm sorry for not getting back to you sooner.

What you're getting hung up on is where Blunt is super flexible. It's where you can define your dispatch pipeline so all Commands and Queries are consistent in their dispatching.

I believe it should be left up to the developers using the library.

I apologize for not having any docs ready to go. It's on my roadmap. I just haven't found the time yet.


Have a look at the config file to see what you can configure. https://github.com/trbngr/thetamind/blob/8bd30e1d57/config/config.exs#L10

The most important pieces are:

pipeline_resolver

This is how we lookup message handlers.

In this example, we simply append Handler to the message module to find the handler.

This is just one example. You could simply call MyCommandedApplication.dispatch for commands if you need. You can be as creative as you need to be here.

dispatch_strategy

This defines how a message is dispatched and any lifecycle that you can think up.

In this example, we're looking up the handler and calling before_dispatch on it before calling handle_dispatch.

The same approach is used for queries. Just a different lifecycle.

I hope that helps.