I'm wondering what other people do for "business error" values as result of pathom queries. I'm up-to-date with error handling in the context of failures (exceptions) or attribute errors, and this is not directly what I'm referring to. I'm talking more about how normally a response might have some attributes but when there is a business logic failure a different set of attributes need to be returned. Something like an "error object" or error attributes. My current solution has a per-resolver error attribute that must always get filled in; in case of an error, it might contain some string text or something, but if there was no error, this value has to be set to something that's not-nil, indicating no error. example:
(defresolver maybe-fail
[{input-a :input/a}]
{::pco/output [:output/x
:output/y
:output/error]}
(if (= input-a "failure")
{:output/x :error
:output/y :error
:output/error "You triggered the businesss error."}
{:output/x (str input-a input-a)
:output/y (str input-a input-a input-a)
:output/error :no-error}))
How do other people handle this situation?Maybe this is a use case for union queries / resolvers?
@hendrik.levering -- I just read through the docs for union queries and I'm not making the mental connection. Would you kindly elaborate what you are thinking here?
My thought is, that it expresses the following very well: Either I have an output-thing or I have an error-thing
Feel free to correct my understanding, but I read union queries as being a selection on which resolver to use. My case is that I have one resolver, that sometimes return an error-thing and sometimes an output-thing.
I think, that it is about the output of one resolver.
If you want to avoid union/queries: Why just make the error key optional and only check if it is there?
Iβll think about union queries a bit; i donβt mind using them, just not sure yet how to arrange the pieces of the puzzle
You could pull out the :output/error attribute to it's own resolver (and maybe even the conditional value) then use those as inputs to this resolver. If you don't need to specify :error on the x and y keys then you can collapse to a single map of
{:output/x (str ...)
:output/y (str ...)
:output/error input-attr/error}
From what I've seen I wouldn't really have an issue with your original solution, just maybe would have suggested exactly what I typed here. If you have to have the :error value on x and y than my suggestion is just because maybe the error should be it's own attribute, but that is your call at that point.
Another solution would be to, as Hendrik said, have a well defined output and error thing. So define both maps in resolvers as a nested map with some name, pull out the conditional logic that tells you if you are in normal or error mode, then have a resolver which takes both maps (resolvers) and the normal/error attribute as inputs and then (get inputs normal-error-map-key)> If you don't need to specify :error on the x and y keys
This is to avoid pathom attribute errors for failing to resolve an attribute.
Thank you for the engagement.
you could write a plugin that always ensures some expected keys like :errors are present, but I also don't see what's wrong about explicitly returning the error attribute