Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Deferred/Streaming Resolution #4

Open
xsc opened this issue Oct 11, 2016 · 0 comments
Open

Deferred/Streaming Resolution #4

xsc opened this issue Oct 11, 2016 · 0 comments

Comments

@xsc
Copy link
Owner

xsc commented Oct 11, 2016

Claro should allow functionality akin to GraphQL's (proposed?) defer, stream and live directives [1], i.e. return incomplete results that get completed asynchronously. Ideally, this is offered by engine middlewares but there are some things to consider.

Access to the full Engine

To let a middleware run resolution, it needs access to the full engine, i.e. one also including all middlewares on top of the current one. This could be achieved by exposing a dynamic binding or lookup function (e.g. claro.engine/current) to the resolver or by (conditionally) injecting the engine into the environment using a well-known key (e.g. :claro/engine).

Dedicated Value Types + Projection

Resolvable parts have to be "marked" as deferred or to-stream, e.g. by wrapping them in dedicated defer/stream records. This can also be elegantly done using projections:

{:id      projection/leaf
 :name    projection/leaf
 :friends (projection/defer [{:name projection/leaf}])}

For stream resolvables it's probably necessary for them to implement explicit streaming functionality.

Push Mechanism

A callback mechanism has to be used to deliver the results of asynchronous resolution. Possible parameters for such a function could be:

  • a unique ID describing the location of the value to deliver,
  • the result value,
  • the environment (which might contain handles on some kind of push transport).

Race Conditions

Deferred values can be nested, so one has to be careful to only push nested results once the upper level has been finalised.

Batching

Deferred values of the same class should be resolved in batches if possible (i.e. if they implement BatchedResolvable), or individually if not.


Keeping these points in mind, deferred resolution is most likely a multi-stage process:

  1. Run normal resolution, wrap values in defer/stream records. Return the result immediately.
  2. Collect all deferred values, probably tuples of (deferredID, resolvable).
  3. If there are any, resolve the deferred tuples asynchronously, processing results using a callback mechanism. Here, similar resolvables can be batched.
  4. Continue with step 2 for each result.

This requires wrapping the full engine, though, not only the resolver part. The result has to be inspected and further actions have to be initiated.

[1] https://medium.com/apollo-stack/new-features-in-graphql-batch-defer-stream-live-and-subscribe-7585d0c28b07

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

1 participant