This page is not created by, affiliated with, or supported by Slack Technologies, Inc.
2020-03-20
Channels
- # admin-announcements (1)
- # announcements (9)
- # aws (11)
- # babashka (33)
- # beginners (125)
- # calva (20)
- # cider (18)
- # clj-kondo (7)
- # cljs-dev (73)
- # clojure (72)
- # clojure-europe (18)
- # clojure-italy (13)
- # clojure-nl (13)
- # clojure-uk (9)
- # clojurescript (22)
- # core-async (7)
- # cursive (1)
- # data-science (25)
- # datomic (22)
- # duct (32)
- # emacs (13)
- # graalvm (5)
- # hoplon (16)
- # juxt (6)
- # kaocha (8)
- # leiningen (3)
- # malli (11)
- # meander (12)
- # off-topic (18)
- # pathom (109)
- # pedestal (5)
- # rdf (10)
- # reagent (1)
- # reitit (12)
- # shadow-cljs (27)
- # spacemacs (5)
- # sql (9)
- # tools-deps (7)
@kwladyka you can set ::p/process-error
in the env, this allows you to process the error in any way you want to return to the user, example: (p/parser {::p/env {::p/process-error (fn [env error] error)}}) ; returns the literal error
by default Pathom uses a string representation due to the initial usages always crossed the wire, so that ended up becaming the default
but as experience shows, its rare that this default is the best option
(def parser
(p/parallel-parser
{::p/env {::p/reader [p/map-reader
pc/parallel-reader
pc/open-ident-reader
p/env-placeholder-reader]
::p/process-error (fn [env error] (println "foo" error))
::p/placeholder-prefixes #{">"}}
::p/mutate pc/mutate-async
::p/plugins [(pc/connect-plugin {::pc/register resolvers})
p/elide-special-outputs-plugin
p/error-handler-plugin
p/trace-plugin]}))
it doesn’t work for me. ::p/process-error
never triggered@souenzzo still doesn’t work when I return map
. ::p/process-error
work when I return string
check if it isn't some encoding issue, but if you run on the REPL it should give the correct answer
strange, what is getting out on the error when you try to use a map?
{:logs :com.wsscode.pathom.core/not-found, :shops :com.wsscode.pathom.core/not-found}
@wilkerlucio any idea how can I return this :logs
without adding to ::pc/output
in each resolver?
I don’t want to throw exception for things which I predicted. This is well precited error in code, so no reason to throw exception.
I want to return :logs
even if not in ::pc/output
and even if not listed in EQL query
@kwladyka seems like you are talking about something different than error processing
if you don't likst things on ::pc/output
, the resolver is not going to get called
and I dont see any way around that, this is a very basic premise of pathom, because this is how things are indexed and how pathom decides what to trigger
but maybe I'm not understading you yet
(pc/defresolver get-shops [env {:shop/keys [uuids]}]
{::pc/input #{:shop/uuids}
::pc/output [{:shops [:shop/uuid :shop/name :shop/engine :shop/config]}]}
(let [shops (shop-db/get-shops-by-uuid (case uuids
:all :all
(set (map (partial safe-coercion uuid/as-uuid) uuids))))]
(if (vector? shops)
{:shops (mapv #(update % :shop/uuid str) shops)}
shops)))
BUT if during processing all of this there is for example error in validation then this resolver return:
{:logs [{:type :error,
:code :validation,
:cause ({:via [:shop/uuids :shop/uuid],
:val "999",
:message "UUID has to be in valid format (for example 00000000-0000-0000-0000-000000000000)."}
{:via [:shop/uuids],
:val #{"999"},
:message "Has to be set of uuid (for example #{00000000-0000-0000-0000-000000000000})."})}]}
that's quite a different approach, nothing wrong with that, but requires you to re-invent the error system
pathom errors are just data in the end
if you want something like that, you have to make your own plugin
add an atom to the env to accumulate things
and in the ::p/wrap-parser
plugin you can inject the collected things to the final response
how are you using this? what your query looks like?
for example this is wrong query because of the validation
(utils/request-eql [{[:shop/uuids #{"999"}] [:shops]}])
this is good one
(utils/request-eql [{[:shop/uuids #{"00000000-0000-0000-0000-000000000000"}] [:shops]}])
{:logs [{:type :error, :code :validation, :cause ({:via [:shop/uuids :shop/uuid], :val “999”, :message “UUID has to be in valid format (for example 00000000-0000-0000-0000-000000000000).“} {:via [:shop/uuids], :val #{“999”}, :message “Has to be set of uuid (for example #{00000000-0000-0000-0000-000000000000}).“})}]}
I personally don't use collections as inputs, I found that given then a name is usually a better option (if possible)
just to understand your case better, how do you build this set to make this query? (whats the source for this list?)
> I found that given then a name is usually a better option (if possible) What do you mean?
I mean, before, when you build the query. I imagine there is some place from which you get this set of ids
so, what I would do there is [{:shop/all [:shop/name]}]
because, lists tend be something else
you are using it in a peculiar way
idents should refer to a single entity, that's more a Fulcro premise, but a lot of Pathom is built upon this idea
what if I will have :shop/all
as real value in :shop
map data? It will make a little confusion.
so, instead of trying to send them by hand on an ident, you can have a resolver that returns all the ids (like: [{:shop/id 1} {:shop/id 2} {:shop/id 3} ...])
This is why I was thinking about not use /all
to avoid confusion it is a value of :shop
@kwladyka this is a very open graph, you should be consistent about what properties mean, so having it as both would be wrong modeling
but you can give other names, as long as they are consistent
https://clojurians.slack.com/archives/C87NB2CFN/p1584732290329700?thread_ts=1584711881.316000&cid=C87NB2CFN I can do this too
sorry, I don't have a lot of time to chat around this now, gotta get back to work, but I suggest you try to follow the things as documented, at least until you get a better feeling of pathom, the direction you are taking is just unknown and likely not well supported
but so far I stuck on :logs
so the feedback why query failed (for example data validation)
you are kind of manually dealing with list processing in this approach, pathom has a bunch of helpers to deal with sequences (think it like jQuery), also, errors in pathom are made in a way to be tolerant as much as possible
I feel like you are thinking like entities (which is very common, that's what happens almost everywhere else) but in Pathom it really helps if you try to get your head around properties (not entities) as the primary building block
so, when you think about something failing, its not the entity, but each attribute
each attribute may fail for a different reason, so you can get partial results
so, in my view, its not about the :shop/id
failing, its about the detail of it failing because the dependency :shop/id
was invalid, so the error would be on the final attribute (`:shop/name` or something)`, not on the list processing
I really gotta go now, but would be happy to chat more around this some other time
I see. But it makes it hard for API client processing. The client has to understand when the value is an error and when expected value.
Only I don’t see how to make this easy to parse by client and understand when the client can use reposne and when not
so after all… are you saying throwing exceptions is the right way of returning validations errors in pathom?
@wilkerlucio is it possible to apply the batch transformer to a dynamic resolver?
I think it should be, but I didn't get to play with that on dynamic resolvers yet
you mean it's already supported? how?
I just did a check, its not supported yet
but its on my list, if you have a close case you need it, I can prioritize it
its not a hard thing to add
I'm converting walkable to a dynamic resolver, it'll be much easier if it's supported
ok, tomorrow I'll have some time, I'll try to add it, I think the basic support (like the previous ones does) should be strait forward to implement
I also would like to support multi-depth batching in this new one, that may take more work
even when you can't implement it soon, please give me several lines of example code so I know what to expect when it's done
hard to tell with certain without sitting and giving some thinking, but I think it will be pretty much like the current one, instead of getting a map as input, you will get a sequence of maps (the inputs to batch)
what is "multi-depth batching"? Say [{:a [{:b [:c]}]}]
, does it mean all the :c
children from multiple :b
branches?
yeah, like: [{:people [{:person/family [:person/name]}]}]
I had people asking about this before, not in the near future, but something to think about how to implement over time
started looking into it, I found that batch already works for regular resolvers on reader3, the issue is that batch relies on caching, and dynamic resolvers don't support caching due to their complex input/output relations
I'm starting to think about how we can go around that for dynamic resolvers
What kind of caching? I use p/cached in my dynamic resolver and it seems to work
p/cached
works, but batch relies on the standard resolver caching, which doesn't work for dynamic, the reason is, when we do a batch for regular resolvers, we get the batched result, and then cache each entry as if they were called separated, so when the processing continues and the user reach that same resolver, the batch will have the call cached, this way it goes fast
but for dynamic resolvers that's much harder, given there is not well defined input to cache from a dynamic response (what is the input? what if the request was already composed from multiple things on the dynamic, how to isolate that part?)
makes sense?
Btw I've made progress on converting walkable to a dynamic resolver. The batching was done by leveraging p/cached that makes batched query from parent node :)
nice!
How do you return errors (not exception ,but for example spec validations info) from resolvers?
I usually do as a param
yeah it was my first intuition but the issue is that the search is not part of the response
if you need in on the response as well, yes, you can do that