movio / bramble

A federated GraphQL API gateway
https://movio.github.io/bramble/
MIT License
497 stars 55 forks source link

Feature Request: @fanout directive #233

Closed Quantumplation closed 7 months ago

Quantumplation commented 7 months ago

One thing that's currently hard to express in bramble is when multiple services want to "contribute" to a list of objects.

For example, I have something built on top of a big event stream, each of which represents some "Transaction", but different subsystems might "claim" that transaction and enrich it with additional data / interpretation.

For example, one transaction might represent a purchase that someone has made; while another might represent a salary payment; while another might represent recurring bill payment.

Each of these systems wants to index, store, and report on only their set of objects, but then in the merged API, we want to present a stream of all relevant transactions.

One component of this would be the ability to have something like a Union or Interface where different services have different implementations, and I know that's on your radar as something to support in the long run.

That can be worked-around for now though, by defining a boundary type, and each service adds it's own property to:

type Transaction @boundary {
  purchaseOrder: X
}
...
type Transaction @boundary {
  salaryPayment: X
}
...

However, there's no way to merge these queries across multiple services; the consumer of the API needs to make separate queries to each service and then merge them.

Something like a @fanout directive might solve this:

// service A
type Query {
  transactions: [Transaction!]! @fanout
}

// service B
type Query {
  transactions: [Transaction!]! @fanout
}

Bramble could then recognize, for fields tagged @fanout with the same boundary type and arguments, it can forward the query to all of these services, and then just concatenate the results.

I'm not sure how much this enroaches on Brambles philosophy of staying simple, so I totally get if this isn't something you want to support, but I just thought I would raise it as someone whose using (and loving) Bramble, but has a couple of pain points with it.

pkqk commented 7 months ago

Hi @Quantumplation

Yes combining two resolvers into one result isn't easily doable. We have a few usages of your first suggested work around in our graph.

Unfortunately I think that's the best way to approach it. Combining multiple resolvers into one result would make things like pagination very difficult but it also conflicts with one of Brambles core design ideas, which is that a Field always maps to exactly one Service.

You're welcome to try other ideas on a fork and if they suit we can bring them back in but for now I think it will conflict with our attempt at saying simple.

Quantumplation commented 7 months ago

@pkqk No worries, I totally understand wanting to keep things simple :)

We're about a full week into using bramble for a fairly complex API (all mocked out with dummy data for now, to trial it), and it's been working fantastically. We're planning on using bramble heavily, and may end up with a number of upstream contributions / plugins / etc.

Is there somewhere we can stay in touch so I can occasionally throw questions your way about how to structure these things before going through the effort of a full PR / Issue writeup, to get alignment before investing a significant amount of work into any particular idea? each issue just feels like I'm being really heavy-weight / annoying :sweat_smile:

pkqk commented 7 months ago

@Quantumplation I'm on the gopher slack with this same username so you can ask me there (I'll try and check it) we don't have a channel though as some other project took the #bramble name there.