This page is not created by, affiliated with, or supported by Slack Technologies, Inc.
2021-07-26
Channels
- # aws-lambda (15)
- # babashka (7)
- # beginners (124)
- # calva (7)
- # cider (19)
- # clj-kondo (26)
- # clojure (261)
- # clojure-australia (3)
- # clojure-dev (10)
- # clojure-europe (45)
- # clojure-nl (4)
- # clojure-uk (6)
- # clojurescript (10)
- # datomic (7)
- # depstar (7)
- # emacs (11)
- # fulcro (41)
- # graalvm (48)
- # helix (1)
- # honeysql (17)
- # inf-clojure (7)
- # introduce-yourself (3)
- # jackdaw (2)
- # lsp (36)
- # malli (2)
- # meander (2)
- # membrane (1)
- # missionary (11)
- # off-topic (17)
- # pathom (83)
- # polylith (15)
- # re-frame (31)
- # reagent (42)
- # sci (35)
- # shadow-cljs (13)
- # spacemacs (13)
- # sql (19)
- # timbre (3)
- # tools-deps (77)
It would be nice to be able to rename fields in the EQL queries (like aliases in GraphQL)
@cyppan in pathom (2) there is an almost undocumented feature: [(:a {:pathom/as :b})]
In pathom3 we still not have, as far I know
@cyppan I think that is nice to have an "standalone" eql-select
library, where you can simply call (select {:a 42} [(:a {:as :b})]) => {:b 42}
Then develop a plugin to use eql-select
as a pathom3 plugin
if anyone is interested in publishing an eql-select library
here a "base implementation" from my codebase 🙂
Maybe handle :default
too on the library
https://gist.github.com/souenzzo/cb37af999d2ab76e68e465427f1f3cd9
I'm trying to discourage this at this moment, but you can make an plugin using this extension point: https://pathom3.wsscode.com/docs/plugins#pcrwrap-merge-attribute
you can read the params with (-> env ::pcp/node ::pcp/params)
, you can use that to re-implement something like :pathom/as
As a first very naive attempt, I used the wrap-map-select-entry extension point, following the protect-attributes-wrapper example
; define the extension wrapper fn
(defn rename-output-wrapper [mse]
(fn [env source {:keys [key] :as ast}]
(if-let [as (get-in ast [:params ::p.eql/as])]
(coll/make-map-entry as (get source key))
(mse env source ast))))
(p.plugin/defplugin rename-output-plugin
{::pf.eql/wrap-map-select-entry rename-output-wrapper})
(comment
(p.eql/process env {:todo/id 1} ['(:todo/name {::p.eql/as :todo/overriden-name})])
)
looks good, sorry I gave a bad instruction about how to get the params before, but you got it right 👍
but there may be a problem there, I'm checking now, because going this way will prevent the children from use the same algorithm (it will not filter things that has :as
)
yeah, confirmed the issue:
(p.eql/process
(-> (pci/register [entity all-entities])
(p.plugin/register rename-output-plugin))
[{'(:all {::p.eql/as :foo})
[:name
]}])
=> {:foo [{:id 1, :name "a", :address {:n 100}} {:id 2, :name "b"}]}
(not asked for address, but ended up out there)
fixed version:
(defn rename-output-wrapper [mse]
(fn [env source ast]
(let [entry (mse env source ast)]
(if-let [as (get-in ast [:params ::p.eql/as])]
(coll/make-map-entry as (val entry))
entry))))
And for the why I need that, our front is in ReScript (so not very EQL-friendly), so I’m building a GraphQL server wrapper (using Lacinia) on top of Pathom resolvers on our backend API, and GraphQL supports that (to alias fields)
@cyppan if you are using lacinia, I think that it will do the alias for you, you don't need to worrry about that in pathom side.
this is indeed something that I would love to see too, there is also a discussion for that: https://github.com/wilkerlucio/pathom3/discussions/18
On the last alpha version (2021.07.23-alpha) I can see the pathom3 strict mode does not work for batch resolvers
but I also wonder, why are you disabling cache on this resolver? cache is kinda important for Batch, because without reliying on the previous input to cache, its hard to know if that part was tried already.
I guess I don’t really understand what is cached, if it is the resolver output, I don’t want caching because I often want the most recent data from the DB
by default the cache lives only during a single request
its to avoid re-doing the same operation from different parts of the same query
Ah! I missed that in the doc thank you > without reliying on the previous input to cache, its hard to know if that part was tried already. I don’t really understand that, I’m gonna have a look into the code
I gonna fix it anyway, because its a bug, it shouldn't rely only on that
but what happens, specially in the case of placeholders, is that you ahve to process the same stuff in different parts of the tree
since Pathom concept of entity is quite flexible, the only way to be sure we are trying to same thing is if the resolver gets called with the same exact input, from a different place
this when cache kicks in, also in the base of batch, the items are cached as if they were individual calls, so when we see that same data need in another part of the query, it can avoid re-calling the resolver by using batch
And I’m not sure how I should handle resources that do not exist in the database in my resolvers to avoid this :thinking_face:, throw an “not-found” exception? It feels strange to me that the processor goes into an infinite loop (in “lenient” mode) when it can’t get the expected output, what I would expect actually is a way to make the ::pco/output nilable, a bit like optional inputs (pco/? ...)
Pathom 3 is still alpha, some things are still getting figured out, and batch is one of then, there's been some issues with the current way to process it, so its good to collect these kinds of issues so we can figure how to make a better implementation
specially with the very recent addition of strict mode, things are getting worked out, can you bring the specific case you have so we can see what we can do about it?
No problem with the alpha state, I’m happy to share and contribute in any way possible, Pathom is a really nice abstraction 🙏
Here I think my concern is not really the batch resolver:
My backend is MongoDB so I have documents sometimes with keys sometimes without, I use those fetched documents directly in my Pathom resolvers, so it happens that a pco/output key is not present in the response.
For instance, an account-resolver
, for a :account/id
input, declares the following outputs: :account/name
and :account/avatar
but avatars are optional, without even the avatar key sometimes in my Mongo documents, and this makes Pathom go into an infinite loop when I request :account/avatar in my EQL.
I can merge a default map with all pco outputs keys with nil associated, but I wonder if there is something more elegant maybe to do
It’s more like a “default” for a ::pco/output maybe, but again, hard to integrate into the graph path resolution I guess
its ok to have optional things on the output, you can look at the output more as like: "I may provide these attributes"
the strictiness is always at the consumer side, so its not about the provider to say "I will for sure provide this", instead, its up to consumer to say "I *require* this part, while these other part may be optional"
makes sense?
Since there is no concept of “schema”, I guess the information of what keys are optional or not has to be expressed another way, so yes it makes sense
yeah, and I think this a good place to be, in the same way we want the consumer to decide what he wants in the query, he is also responsible for deciding what is optional about it
and to point out, when I say consumers I'm refering to resolver inputs and queries sent to p.eql/process
(I was thinking of several resolvers* providing the same outputs, and how to choose / fallback to another path when you have required and optional outputs, wondering how to handle that)
when you say “its ok to have optional things on the output” you mean, as a resolver, I’m not forced to provide you the keys I have declared?
on multiple options Pathom will generate OR
nodes in the plan, so it will try one at a time, there is a built-in thing you can use to prioritize, but this is still an area of exploration, not many people have used it so not enough experience, but there is a discussion about it here: https://github.com/wilkerlucio/pathom3/discussions/57
> when you say “its ok to have optional things on the output” you mean, as a resolver, I’m not forced to provide you the keys I have declared? correct
Pathom never complains about missing data on the output, it complains if the the data is missing by the time it tries to call something that requires it
here is an example that illustrates that:
(pco/defresolver ab []
{::pco/output
[:a :b]}
{:a 1})
(pco/defresolver c [{:keys [a]}]
{:c (inc a)})
(p.eql/process-one
(pci/register [ab c])
:c)
Yes I understand, this is problematic in my case because I have “foreign keys” in my mongo documents, but sometimes without the key as I was explaining, so when I try to “join” and there isn’t the key, it errors, I’m merging nil keys to solve that
ab
says it outputs :b
, but it doesn't, but since :c
doesn't care about :b
. not an issue
its valid to make join keys optional, is this something that works for your case?
like: [:foo {(pco/? :join-bar) [:baz]}]
no, on the input (or query)
resolver outputs never need optional mark
can you show the place where you demand the join? I know its a bit weird at first this thing about requirements on the consumer
in my case I do something like that, [:meta-campaign/brand {(pco/? :brand_expanded) [,,,]]
the join key is :meta-campaign/brand, which sometimes is not present from my meta-campaign resolver output
If I understand correctly it should work with
[:meta-campaign/brand {(pco/? :brand_expanded) [,,,]]
but not with
[:meta-campaign/brand {:brand_expanded [,,,]]
(def entity-db
{1 {:name "a"
; has address
:address {:n 100}}
2 {:name "b"
; no address
}})
(pco/defresolver entity [{:keys [id]}]
{::pco/output
[:name {:address [:n]}]}
(get entity-db id))
(pco/defresolver all-entities []
;just output the ids
{:all
(mapv #(array-map :id %) (keys entity-db))})
(p.eql/process
(pci/register [entity all-entities])
[{:all [:name {(pco/? :address) [:n]}]}])
note the optionality on the query side, and this works the same when making ::pco/input
no worries, glad we got thought it
maybe on the optional input section