EctoApi
This is one idea that I’ve been experiment with and I’m making it public so there can be some discussion to improve these ideas. Although the name initially might drive someone to think that it’s only for http api, the way i’m envisioning this is that it can be used with any sort of communication protocol. Even asynchronous protocols might fit here.
Proposed API
I’m thinking t mimic Ecto.Repo for EctoApi with some restrictions and additions:
insert_allandupdate_allaren’t planned to be available.allmight happen, but not soon. I’m still uncertain if it’s better to support a limitted version ofEcto.Queryor build a proper DSL for this.get_byfromEcto.Repousually just return a single entry so for the current lack ofallI’m addingget_all.-
I’m currently working on how
preloadshould work. -
so the available functions are
insert,update,delete,get,get_by,get_all.
Behaviours and internal nomenclature
EctoApi.Client: this is where the side effects happen. All the communication are wrapped around this.EctoApi.Resolver: receives the metadata from the resource and received params and build all the information thatEctoApi.Clientneeds to do the external communication.EctoApi.Builder: takes the response from theEctoApi.Clientand cast the resource from it. It also dumps the resource to a proper structure thatEctoApi.Resolvercan use to build requests with it.
Although EctoApi.Client and EctoApi.Resolver hints to http and crud operations, this is not supposed to restrict implementations of those behaviors.
A GrapQL that only requires a get and post methods, might use the put and delete functions just to build context for the way to build the request.
Current explorations and doubts
Configuration and sensible defaults
I’m not a fan of library wide configurations.
I’ve been thinking to do something like Ecto.Repo, in a way that you implement EctoApi for your application and you set it for a single implementation.
Other possibility here is that the resource itself describes what should be used to resolve it, so a User would have client/0, resolver/0 and builder/0 functions returning the proper ones to be used with that specific resource.
The former might lead to difficuties when using resources that requires different resolvers, clients and builders.
The later might require a lot of boiler plate in place for a resource to be used.
Preload and relations
There are some issues with relations and preloading them.
The first one that comes to mind is that some relations might just not work back and forth.
What I mean with it is that a belongs_to might not translate properly to a has_one or has_many relation.
Other issue that I see is about pagination. For http apis this would make impossible to preload all the related resources with a single request. Should it go through all pages with a single preload or it’s better to set pagination options when preloading and allow to preload more data with other later requests. This not only relates to the lazyness of the operation but on the proper way to configure the relation and set the default pagination.
Additions and possible nice features to have in the future
I’m thinking to add some caching and pooling strategies but this only can come up once the configuration and preload explorations are done. Besides that I’m thinking to have a default Clients/Resolvers for basic restful apis, jsonapi specification and graphql. I didn’t explore grpc yet, but it might make sense to have one for it too.