Skip to content

Superlifter wont deliver (lacinia) promise if a fetch request is rejected #27

@lennartbuit

Description

@lennartbuit

Heya 👋

Say you have some datasource, that can fail for some reason:

(defrecord Fail [nonce]
  u/Datasource
  (-identity [_] nonce)
  (-fetch! [_ _] (prom/rejected (ex-info "Not good" {}))))

With a resolver that uses with-superlifter/enqueue!:

(defn failing-resolver
  [ctx args val]
  (with-superlifer ctx
    (enqueue! (Fail. (rand-int 100)))

Then with-superlifter will produce a lacinia "resolver result" promise that is never delivered. This request will now hang.


I think the problem here is how enqueue works. Enqueue takes your (urania) AST, and appends a then step:

delivering-muse (u/map (fn [result]
(prom/resolve! p result)
result)
muse)]

Now, this is not the place that the urania tree is executed, that happens in update-buckets!, via (urania) u/execute!:

(-> (u/execute! (u/collect muses)
(merge (:urania-opts new)
(when cache
{:cache (->urania cache)})))

Urania, however, will short circuit asts that contain failing datasources. The all step here is rejected:

https://github.com/funcool/urania/blob/3d3c61206d8a7de675af5d97ad08706ad3307a15/src/urania/core.cljc#L236

Therefore, this then step is skipped (the promise is rejected):

https://github.com/funcool/urania/blob/3d3c61206d8a7de675af5d97ad08706ad3307a15/src/urania/core.cljc#L237-L241

And therefore the superlifter amended then is never interpreted. Urania essentially short circuits and superlifter can never deliver the promise created in enqueue! because of that.


So; we tried something, but I'm not necessarily sure whether that is something that we should do in superlifter like this. The rejection of the datasource does bubble up to u/execute!. So in update-buckets! we can know what calls to enqueue! resulted in a rejection.

So in this tree, I've changed the queue shape to have both a muse, and the (enqueue!) promise. So that if u/execute! fails, I can know what enqueue promises it needs to reject.

Thoughts?

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions