Fork me on GitHub
#pathom
<
2022-09-06
>
Ernesto Garcia08:09:02

For instance, I have obtained an error with error-data being nil, which I didn't expect:

{:com.wsscode.pathom3.error/error-message "Don't know how to create ISeq from: clojure.lang.Symbol", :com.wsscode.pathom3.error/error-data nil, :com.wsscode.pathom3.error/error-stack "java.lang.IllegalArgumentException: Don't know how to create ISeq from: clojure.lang.Symbol\n\tat clojure.lang.RT.seqFrom(RT.java:557)\n\tat clojure.lang.RT.seq(RT.java:537)\n\tat clojure.lang.APersistentMap.cons(APersistentMap.java:40)\n\tat clojure.lang.RT.conj(RT.java:677)\n..."}

Ernesto Garcia09:09:12

Pathom-relevant part of the stack trace, btw:

at clojure.core$update_in.invokeStatic(core.clj:6175)
	at clojure.core$update_in.doInvoke(core.clj:6161)
	at clojure.lang.RestFn.invoke(RestFn.java:467)
	at edn_query_language.core$call__GT_ast.invokeStatic(core.cljc:154)
	at edn_query_language.core$call__GT_ast.invoke(core.cljc:151)
	at edn_query_language.core$expr__GT_ast.invokeStatic(core.cljc:207)
	at edn_query_language.core$expr__GT_ast.invoke(core.cljc:199)
	at clojure.core$map$fn__5880$fn__5881.invoke(core.clj:2746)
	at clojure.lang.PersistentVector.reduce(PersistentVector.java:343)
	at clojure.core$transduce.invokeStatic(core.clj:6885)
	at clojure.core$into.invokeStatic(core.clj:6901)
	at clojure.core$into.invoke(core.clj:6889)
	at edn_query_language.core$query__GT_ast.invokeStatic(core.cljc:165)
	at edn_query_language.core$query__GT_ast.invoke(core.cljc:158)
	at com.wsscode.pathom3.interface.eql$process.invokeStatic(eql.cljc:67)
	at com.wsscode.pathom3.interface.eql$process.invoke(eql.cljc:35)
	at com.wsscode.pathom3.interface.eql$boundary_interface$boundary_interface_internal__54301.invoke(eql.cljc:192)
	at com.wsscode.pathom3.interface.eql$boundary_interface$boundary_interface_internal__54301.invoke(eql.cljc:196)

wilkerlucio22:09:50

do you believe this is a bug in pathom? im not sure from that stack, if so, please send a repro and I'll be happy to look into it :)

Ernesto Garcia15:09:28

I think the error-data obtained from boundary-interface should never be nil, and boundary-interface should specify how to distinguish when there has been an error in the EQL query, or an exception thrown by resolvers, or an exception in the Pathom engine. I will look into how to reproduce the error above. I think it was just an incorrect EQL txn.

Ernesto Garcia15:09:37

Thanks for your response.

Thomas Moerman10:09:56

Hi gang, a bit of a long-shot question. I've lately been thinking and reading about hexagonal/[diplomat](https://youtu.be/ct5aWqhHARs) architectural patterns and was ruminating on how to marry this with Pathom mutations. The #interceptors approach (cfr Sieppari and Pedestal) offers a nice way of composing functionality using interceptor operators on a context map. Now my question is: when using Fulcro/Pathom, how could I break up a classic pathom mutation into an interceptor chain or part of an interceptor chain? Roughly the interceptor chain would consist of: :enter phase => [param coercion] -> [param resolution (using pathom)] -> [do permission checks] -> [pure functional business logic operation on ctx map (aka mutation body)] -> ["sync" side-effects (e.g. db transactions)] -> ["async" side effect (e.g. posting messages to queues)] :leave phase => [resolving eql mutation join] -> [redaction of eql results in function of authorization policy rules] -> [error response handling] The two steps in bold are what typical processing of a pathom mutation entails, but in the above schematic they are broken up into two discrete interceptor phases. I'm thinking in the direction of having an interceptor at the start of the chain the inspects the eql AST and dynamicall injects the interceptor building blocks in the chain, based on a data representation that describe pathom mutations (name, params and body) as well as the interceptor chains involved. The main objective of this approach would be to increase the compositional nature of mutations in a Fulcro/Pathom app. Thoughts, comments, ideas?

Thomas Moerman14:09:29

The pathom plugin systems might be a good starting point for this. It's not explicitly mentioned in the Pathom docs, but the https://pathom3.wsscode.com/docs/plugins#adding-plugins looks exactly like an interceptor-based system.

dvingo23:09:22

@U052A8RUT I landed on this exact pattern after learning pedestal https://github.com/dvingo/my-clj-utils/blob/99d3820b1b2bc77ba33c792b493017645786b947/src/main/dv/pathom.clj#L187 I made this helper some time ago, I have a more recent version in a project that uses sieppari instead because it has cljc support

๐Ÿ™ 1
dvingo23:09:48

the pathom context substitutes exactly for the pedestal context in a http request lifecycle

wilkerlucio23:09:39

hello @U052A8RUT, as you found out, the plugins is the right way to handle that generically for a pathom system, also as @U49U72C4V pointed out, the ::pco/transform is another way to extract this kind of behavior, but instead of applying it globally, its uses are per mutation case.

๐Ÿ‘ 1
dvingo23:09:46

note that sieppari is apparently being sunset, but this https://github.com/exoscale/interceptor is a good alternative

Thomas Moerman10:09:29

@U051V5LLP oh is it? Good to know, thanks. Thanks all for sharing your perspective. metal

Thomas Moerman19:09:43

๐Ÿงช๐Ÿ”ฌ:male-scientist: ๐Ÿงซ I cooked up something to illustrate my idea: https://gist.github.com/tmoerman/c4c863c00e5364932ad209f921d9e7d2 Instead of running interceptors in a mutation body, the eql-processor becomes a (2-phase) interceptor itself! I used 2 Pathom plugins, each of which is added to the env to modify the behavior of p.eql/process: one for the :enter phase of an interceptor, one for the :leave phase. This means the p.eql/process fn is run twice. In :enter the result of the mutation step is captured in acc atom, the mutation join is stripped off the ast. In :leave the captured result is used instead of executing the mutation. With some more plumbing, I would then only allow pure functions in the mutation body, capturing transactions and other side-effects in the interceptor context map, for other downstream interceptors to pick up and apply. When the :leave phase of the eql-processing interceptor is reached, the side effects have already been done and the mutation join is sure to resolve data in function of an updated DB. Not sure this approach will turn out to be more useful than running an interceptor stack in mutation bodies, but I had a good time learning about pathom plugins ๐Ÿ˜‰ The plugin system is very cool @U066U8JQJ! What do you guys think? Cheers!