Search code examples
asynchronousrepository-patterncqrsclean-architecture

How to design a repository writing to pub/sub and reading from database in clean architecture


I want to design my application which requires writing asynchronously through pub/sub and reading synchronously from the database. How do you implement this in clean architecture? There's a separate process reading from the pub/sub and writing to the database.

I'm thinking of a design like this; however, I wasn't sure if it's a good design for one repository to be implemented using separate persistent infrastructure for reading and writing.

  Repository   |     Controller   |    Infrastructure
my repository ---> my controller ---> (write) pub/sub
                                  \-> (read)  database

An alternative could be CQRS, but in my case, I use the same model for reading and writing, so I think it's better to use a single model.

Background: Writes to my application are very elastic, while reads are consistent. So I avoid getting my service overloaded by writing asynchronously.

Thanks!


Solution

  • It the same as with any other clean architecture application.

    +------------+  ||  +----------+      +------------+
    | Controller | ---> | Use Case | ---> | Repository |
    +------------+  ||  +-----------      +------------+
                    ||                    | save()     |
                    ||                    | find()     |
                    ||                    +------------+
                    ||                          ^
    ============================================|==========                               
                                                |
                                          +------------+
                                          |  RepoImpl  |
                                          +------------+
                                          | save()     | ---> write to pub/sub
                                          | find()     | ---> read from db
                                          +------------+
    

    Maybe you split up the repository writes and reads into different interfaces, because you might have a use case that only reads and another that only writes. I usually apply the interface segregation principle and define use case specific interfaces.