Fork me on GitHub
#pathom
<
2024-01-04
>
tony.kay06:01:25

I’m having trouble getting mutations to work with an async EQL processor in pathom3. I’ve got it set up and working with resolvers, but as soon as I call a mutation (even if it just returns a (p/resolved {})) the EQL processor never returns.

tony.kay06:01:17

I’ve added tracing statements, and I see the mutation get called…it’s just that the (a.eql/process …) never returns if I invoke a mutation. Is anyone else using async processor?

tony.kay06:01:39

(let [base-env (pci/register (vals @pathom-registry))]
  (p/let [res (a.eql/process base-env eql))]
    ... never reach this line ...
for mutation:
(defmutation f [env {:member/keys [email] :as params}]
     {:check       none
      ::pco/output [:member/guid :login/nonce-sent?]}
     (p/resolved  {:member/guid (new-uuid)
       :login/nonce-sent?    true})

tony.kay06:01:55

Where f is in the pathom-registry atom

tony.kay06:01:35

I’ve got the bridge installed, and this resolver works fine:

(defresolver test-resolver [env input]
  {::pco/output [:test-value]
   :check       (constantly true)}
  (async/go
    (async/<! (async/timeout 200))
    {:test-value (rand-int 100)}))

tony.kay06:01:24

This is in Clojure, not cljs, BTW. I’m writing a server that needs to handle high traffic, so I’m using ring async handling…thus the need for the parser to be able to park when I/O is going on.

wilkerlucio14:01:36

hi @tony.kay, I'm trying to repro, but in a simple example it seems to be working, I wonder if there is something on plugins or anything else that might be causing the lockup in the middle of the process

wilkerlucio14:01:44

sample I made here:

wilkerlucio14:01:47

(ns demos.async-mutations
  (:require [com.wsscode.pathom3.connect.indexes :as pci]
            [com.wsscode.pathom3.connect.operation :as pco]
            [com.wsscode.pathom3.interface.async.eql :as p.a.eql]
            [com.wsscode.promesa.bridges.core-async]
            [promesa.core :as p]))

(pco/defmutation sample []
  (p/resolved {:foo "bar"}))

(def env
  (-> {}
      (pci/register [sample])))

(comment
  @(p/let [foo (p.a.eql/process env [`(sample {})])]
     foo))

tony.kay15:01:11

Ah sorry, it is a mutation join. Maybe I have a bad resolver

tony.kay15:01:33

I'm returning what it needs, so it didn't occur to me that a resolver would even be invoked

wilkerlucio16:01:48

could be a bug too, so will be nice if we can make a standalone repro

wilkerlucio16:01:46

also, Pathom 3 currently doesn't provide "hard limits" for processing (which Pathom 2 does), it could be a time to consider it, I'm still not sure if thats better as a Pathom feature or something for the user to handle (adding a timeout around your process call to ensure it finishes at some point)

wilkerlucio16:01:48

a basic mutation join seems to work (with data ready, and fetching after):

(ns demos.async-mutations
  (:require [com.wsscode.pathom3.connect.built-in.resolvers :as pbir]
            [com.wsscode.pathom3.connect.indexes :as pci]
            [com.wsscode.pathom3.connect.operation :as pco]
            [com.wsscode.pathom3.interface.async.eql :as p.a.eql]
            [com.wsscode.promesa.bridges.core-async]
            [promesa.core :as p]))

(pco/defmutation sample []
  {::pco/output [:foo]}
  (p/resolved {:foo "bar"}))

(def env
  (-> {}
      (pci/register [sample
                     (pbir/alias-resolver :foo :bar)])))

(comment
  [@(p.a.eql/process env [{`(sample {}) [:foo]}])
   @(p.a.eql/process env [{`(sample {}) [:bar]}])]
  ;=> [{demos.async-mutations/sample {:foo "bar"}} {demos.async-mutations/sample {:bar "bar"}}]
  )

tony.kay16:01:09

I’ll see if I can tease it apart into a min repro. This is a new project, and I only have the one test resolver, and two mutations that are called via mutation joins. There is NO resolver that could possibly resolve the data the mutation joins query for, BUT the query MIGHT contain things that the mutations do not always return

tony.kay16:01:17

I may just stick with pathom 2 for now, but I did want to try 3 out and see how it was going. For this particular app, though, it probably doesn’t have anything new that I want/need (the queries won’t be particularly complicated/deep/involved)

wilkerlucio17:01:53

I'm interested in learning whats going on, if you can get a repro I'll be happy to help figure whats going on

tony.kay17:01:38

OK, I think this exposes my problem:

(ns demos.async-mutations
  (:require [com.wsscode.pathom3.connect.built-in.resolvers :as pbir]
            [com.wsscode.pathom3.connect.indexes :as pci]
            [com.wsscode.pathom3.connect.operation :as pco]
            [com.wsscode.pathom3.interface.async.eql :as p.a.eql]
            [simplymeet.lib.core]
            [promesa.core :as p]))

(pco/defmutation sample []
  {::pco/output [:foo :bar]}
  (p/resolved {:foo "bar"}))

(def env
  (-> {}
    (pci/register [sample])))

(comment
  [@(p.a.eql/process env [{`(sample {}) [:foo :bar]}])
   ]
  ;=> Execution error (ExceptionInfo) at com.wsscode.pathom3.connect.planner/verify-plan!* (planner.cljc:1694).
Pathom can't find a path for the following elements in the query: [:bar] at path [demos.async-mutations/sample]
  )
When I run that one, I get an exception..and I’m adapting to core.async, and I think I forgot to handle the case where it throws or something. I forgot in p3 that you default to this mode where if you can’t find something you throw

tony.kay17:01:52

I expected a not found result

tony.kay17:01:29

In my case I’m doing a login mutation, and the data that gets resolved is ONLY available from the mutation, but some of it doesn’t come back on login failure

tony.kay17:01:49

so there is no resolver to “make up the difference”.

wilkerlucio17:01:11

yeah, the default mode is strict and wont allow for missing things, but the client can say something is optional, I guess in your case you will prefer to use lenient mode, but otherwise this works:

@(p.a.eql/process env [{`(sample {}) [:foo (pco/? :bar)]}])

wilkerlucio17:01:40

the difference is that the client is expressing that :bar is optional, so Pathom 3 wont throw in case its missing

tony.kay19:01:30

well, at least it isn’t a bug. Thanks for looking