vortico / flama

Fire up your models with the flame 🔥

Home Page:https://flama.dev

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Domain-driven design for HTTP resources

migduroli opened this issue · comments

Summary

HTTP resources as counterpart of SQLAlchemy resources

Motivation

At the moment, when we want to interact with a database, we know we can use the SQLAlchemyWorker and the SQLAlchemyTableRepository to represent the connection to the DB, and one of the tables, respectively. In particular, we reach an interface of the like:

async with worker:
    worker.repository_name.action(*args, **kwargs)

So that the worker provides the context, under which the connection with the DB is established, and the transaction is initialised, to then interact with one of the tables via repository_name (its type being SQLAlchemyTableRepository) and one of the actions available for such a repository, and to finally, commit the changes and eventually close the connection when the context is closed.

With all this, we have a perfectly isolated way of working with the database tables in a DDD-compliant way. However DBs are not the only type of unit of work we can find. Indeed, one of the most common units of work found (implicitly) during the development of APIs is the interaction with another API (microservice). Thus, it's worth considering the implementation of a similar approach for HTTP/REST resources.

Proposed changes

With the previous context given, we propose a similar approach to that followed with the SQLAlchemyWorker and SQLAlchemyTableRepository. In this case we would have:

  • HTTPWorker which will be in charge of initializing the flama.Client with the corresponding base_url of the microservice to interact with.
  • HTTPResourceRepository which will be in charge of implementing the CRUDL methods to interact with a specific _resource (enpoint) of the microservice we're interacting with.

The idea is that if we have an API at the URL, say, http://my_api_url.dev and we want to make requests to the enpoint /user/ (representing the REST resource User), then we would like to have the following communication interface:

class MyAPIWorker(HTTPWorker):
    _url = "http://my_api_url.dev"

class User(HTTPResourceRepository):
    _resource = "user"
    
...

async with worker:
    await worker.user.create(...)