pathom

tony.kay 2024-01-04T06:03:25.989759Z

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.kay 2024-01-04T06:03:31.121549Z

Any ideas?

tony.kay 2024-01-04T06:06:17.367789Z

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.kay 2024-01-04T06:09:39.645409Z

(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.kay 2024-01-04T06:09:55.325609Z

Where f is in the pathom-registry atom

tony.kay 2024-01-04T06:10:35.357409Z

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.kay 2024-01-04T06:13:24.843929Z

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.

wilkerlucio 2024-01-04T14:53:36.453469Z

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

wilkerlucio 2024-01-04T14:53:44.378459Z

sample I made here:

wilkerlucio 2024-01-04T14:53:47.466809Z

(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.kay 2024-01-04T15:37:11.741189Z

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

tony.kay 2024-01-04T15:38:33.529489Z

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

wilkerlucio 2024-01-04T16:09:48.824769Z

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

wilkerlucio 2024-01-04T16:10:46.312469Z

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)

wilkerlucio 2024-01-04T16:12:48.542079Z

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.kay 2024-01-04T16:29:09.574559Z

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.kay 2024-01-04T16:31:17.187829Z

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)

wilkerlucio 2024-01-04T17:06:53.014899Z

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.kay 2024-01-04T17:32:38.242559Z

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.kay 2024-01-04T17:32:52.967849Z

I expected a not found result

tony.kay 2024-01-04T17:33:29.842159Z

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.kay 2024-01-04T17:33:49.239339Z

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

wilkerlucio 2024-01-04T17:59:11.220659Z

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)]}])

wilkerlucio 2024-01-04T17:59:40.998579Z

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

tony.kay 2024-01-04T19:12:30.175079Z

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