Skip to content

Commit

Permalink
Expose missing attributes during planner error
Browse files Browse the repository at this point in the history
  • Loading branch information
wilkerlucio committed Dec 19, 2024
1 parent e707f01 commit a9857a2
Show file tree
Hide file tree
Showing 3 changed files with 141 additions and 76 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
- Track `::pcp/expects` on AND nodes, it includes all expects from the node chain
- BREAKING: removed `p->` and `p->>` helpers from `com.wsscode.promesa.macros`. These were old macros and currently Promesa has them in the library.
- Bump `com.wsscode/cljc-misc` to `2024.12.18`
- Expose missing attributes during planner error

## [2024.11.23-alpha]
- Fix placeholders using different parameters
Expand Down
29 changes: 20 additions & 9 deletions src/main/com/wsscode/pathom3/connect/planner.cljc
Original file line number Diff line number Diff line change
Expand Up @@ -1359,13 +1359,12 @@
(let [[graph' extended?] (extend-available-attribute-nested graph env attr shape)]
(if extended?
[graph' node-map]
(reduced [graph' nil])))
[graph' nil]))

(let [graph' (compute-attribute-dependency-graph graph env attr shape)]
(if-let [root (::root graph')]
[graph'
(assoc node-map attr root)]
(reduced [(merge-unreachable graph graph') nil])))))
[graph' (if node-map (assoc node-map attr root))]
[(merge-unreachable graph graph') nil]))))
[graph {}]
missing))

Expand Down Expand Up @@ -1704,19 +1703,31 @@
(update source-ast :children
#(into (with-meta [] (meta %)) keep-required-transducer %)))

(defn unreachable-attr-cause [{::pci/keys [index-oir]} _graph attr]
(if (contains? index-oir attr)
{::unreachable-cause ::unreachable-cause-missing-inputs
::unreachable-missing-inputs {}}
(defn unreachable-attr-cause [{::pci/keys [index-oir]} graph attr]
(if-let [paths (get index-oir attr)]
(let [unreachable-paths (::unreachable-paths graph)]
{::unreachable-cause ::unreachable-cause-missing-inputs
::unreachable-missing-inputs (into {}
(map (fn [[k v]]
[(pfsd/intersection unreachable-paths k) v]))
paths)})
{::unreachable-cause ::unreachable-cause-unknown-attribute}))

(defn unreachable-details [env graph missing]
(into {} (map (fn [[k]] [k (unreachable-attr-cause env graph k)])) missing))

(defn unreachable-attr-str [attr]
(str " - Can't reach attribute " attr))

(defn unreachable-attr-inputs [inputs]
(str/join "\n" (map unreachable-attr-str (keys (key inputs)))))

(defn unreachable-detail-string [_env attr cause]
(case (::unreachable-cause cause)
::unreachable-cause-missing-inputs
(str "- Attribute " attr " inputs can't be met, details: WIP")
(str "- Attribute " attr " inputs can't be met, details:\n"
(str/join "\n OR\n"
(map unreachable-attr-inputs (::unreachable-missing-inputs cause))))

::unreachable-cause-unknown-attribute
(str "- Attribute " attr " is unknown, there is not any resolver that outputs it.")))
Expand Down
187 changes: 120 additions & 67 deletions test/com/wsscode/pathom3/connect/planner_test.cljc
Original file line number Diff line number Diff line change
Expand Up @@ -284,18 +284,17 @@
{::resolvers []
::eql/query [:a :b]})))

;; WIP - figuring out the format, will comment for now so CI passes
#_
(testing "broken chain"
(check (=> {:ex/message
(str
"Pathom can't find a path for the following elements in the query:\n"
"- Attribute :b inputs can't be met, details:\n"
" - Missing attribute :a")
" - Can't reach attribute :a")

:ex/data
{::pcp/unreachable-paths {:b {}}
::pcp/unreachable-details {:b {::pcp/unreachable-cause ::pcp/unreachable-cause-missing-inputs}}
::pcp/unreachable-details {:b {::pcp/unreachable-cause ::pcp/unreachable-cause-missing-inputs
::pcp/unreachable-missing-inputs {{:a {}} #{'b}}}}
::p.error/phase ::pcp/plan
::p.error/cause ::p.error/attribute-unreachable}}
(compute-run-graph-ex
Expand All @@ -309,7 +308,16 @@
(str
"Pathom can't find a path for the following elements in the query:\n"
"- Attribute :b inputs can't be met, details:\n"
" - Missing attribute :a")}
" - Can't reach attribute :a")

:ex/data
'{::pcp/unreachable-paths {:b {}}
::pcp/unreachable-details
{:b
{::pcp/unreachable-cause
::pcp/unreachable-cause-missing-inputs
::pcp/unreachable-missing-inputs
{{:a {}} #{b}}}}}}
(compute-run-graph-ex
{::resolvers [{::pco/op-name 'b
::pco/input [:a :c]
Expand All @@ -322,7 +330,16 @@
(str
"Pathom can't find a path for the following elements in the query:\n"
"- Attribute :b inputs can't be met, details:\n"
" - Missing attribute :a")}
" - Can't reach attribute :a")

:ex/data
'{::pcp/unreachable-paths {:b {}}
::pcp/unreachable-details
{:b
{::pcp/unreachable-cause
::pcp/unreachable-cause-missing-inputs
::pcp/unreachable-missing-inputs
{{:a {}} #{b}}}}}}
(compute-run-graph-ex
{::resolvers [{::pco/op-name 'b
::pco/input [:a :c]
Expand All @@ -335,7 +352,16 @@
(str
"Pathom can't find a path for the following elements in the query:\n"
"- Attribute :b inputs can't be met, details:\n"
" - Missing attribute :a")}
" - Can't reach attribute :a")

:ex/data
'{::pcp/unreachable-paths {:b {}}
::pcp/unreachable-details
{:b
{::pcp/unreachable-cause
::pcp/unreachable-cause-missing-inputs
::pcp/unreachable-missing-inputs
{{:a {}} #{b b1}}}}}}
(compute-run-graph-ex
{::resolvers [{::pco/op-name 'b
::pco/input [:a]
Expand All @@ -350,8 +376,16 @@
(str
"Pathom can't find a path for the following elements in the query:\n"
"- Attribute :c inputs can't be met, details:\n"
" - Missing attribute :b\n"
" - Provide :a to use path: :a -> :b")}
" - Can't reach attribute :b")

:ex/data
'{::pcp/unreachable-paths {:c {}},
::pcp/unreachable-details
{:c
{::pcp/unreachable-cause
::pcp/unreachable-cause-missing-inputs
::pcp/unreachable-missing-inputs
{{:b {}} #{c}}}}}}
(compute-run-graph-ex
{::resolvers [{::pco/op-name 'b
::pco/input [:a]
Expand All @@ -365,9 +399,7 @@
(str
"Pathom can't find a path for the following elements in the query:\n"
"- Attribute :d inputs can't be met, details:\n"
" - Missing attribute :c\n"
" - Provide :b to use path: :b -> :c\n"
" - Provide :a to use path: :a -> :b -> :c")}
" - Can't reach attribute :c")}
(compute-run-graph-ex
{::resolvers [{::pco/op-name 'b
::pco/input [:a]
Expand All @@ -385,15 +417,12 @@
(str
"Pathom can't find a path for the following elements in the query:\n"
"- Attribute :c inputs can't be met, details:\n"
" - Missing attribute :b\n"
" - Provide :a to use path: :a -> :b\n"
" - Missing attribute :d")}
" - Can't reach attribute :b\n"
" - Can't reach attribute :d")}
(compute-run-graph-ex
{::resolvers [{::pco/op-name 'b
::pco/input [:a]
::pco/output [:b]}
{::pco/op-name 'd
::pco/output [:d]}
{::pco/op-name 'c
::pco/input [:b :d]
::pco/output [:c]}]
Expand All @@ -403,19 +432,34 @@
(check (=> {:ex/message
(str
"Pathom can't find a path for the following elements in the query:\n"
"- Attribute :d dependencies can't be met, details:\n"
" - Missing attribute :b\n"
" - Provide :a to use path: :a -> :b\n"
" - Missing attribute :c\n"
" - Provide :a to use path: :a -> :c")}
"- Attribute :d inputs can't be met, details:\n"
" - Can't reach attribute :b\n"
" - Can't reach attribute :c")}
(compute-run-graph-ex
{::resolvers [{::pco/op-name 'a->bc
::pco/input [:a]
::pco/output [:b :c]}
{::pco/op-name 'd
::pco/input [:b :c]
::pco/output [:d]}]
::eql/query [:d]})))))
::eql/query [:d]}))))

(testing "multiple input paths to reach missing attribute"
(check (=> {:ex/message
(str
"Pathom can't find a path for the following elements in the query:\n"
"- Attribute :c inputs can't be met, details:\n"
" - Can't reach attribute :a\n"
" OR\n"
" - Can't reach attribute :b")}
(compute-run-graph-ex
{::resolvers [{::pco/op-name 'a->c
::pco/input [:a]
::pco/output [:c]}
{::pco/op-name 'b->c
::pco/input [:b]
::pco/output [:c]}]
::eql/query [:c]})))))

(testing "currently available data"
(is (= (compute-run-graph
Expand Down Expand Up @@ -791,30 +835,33 @@
:root 4})))

(testing "nested cycles"
(is (thrown-with-msg?
#?(:clj Throwable :cljs js/Error)
#"Pathom can't find a path for the following elements in the query at path \[:a]:\n- Attribute :b inputs can't be met, details: WIP"
(compute-run-graph
{::resolvers [{::pco/op-name 'cycle-a
::pco/output [:a]}
{::pco/op-name 'cycle-b
::pco/input [{:a [:b]}]
::pco/output [:b]}]
::eql/query [:b]})))
(check (=> {:ex/message
(str
"Pathom can't find a path for the following elements in the query at path [:a]:\n"
"- Attribute :b inputs can't be met, details:\n")}
(compute-run-graph-ex
{::resolvers [{::pco/op-name 'cycle-a
::pco/output [:a]}
{::pco/op-name 'cycle-b
::pco/input [{:a [:b]}]
::pco/output [:b]}]
::eql/query [:b]})))

(is (thrown-with-msg?
#?(:clj Throwable :cljs js/Error)
#"Pathom can't find a path for the following elements in the query at path \[:a]:\n- Attribute :c inputs can't be met, details: WIP"
(compute-run-graph
{::resolvers [{::pco/op-name 'cycle-a
::pco/output [:a]}
{::pco/op-name 'cycle-b
::pco/input [{:a [:c]}]
::pco/output [:b]}
{::pco/op-name 'cycle-c
::pco/input [:b]
::pco/output [:c]}]
::eql/query [:b]}))))))
(check (=> {:ex/message
(str
"Pathom can't find a path for the following elements in the query at path [:a]:\n"
"- Attribute :c inputs can't be met, details:\n"
" - Can't reach attribute :b")}
(compute-run-graph-ex
{::resolvers [{::pco/op-name 'cycle-a
::pco/output [:a]}
{::pco/op-name 'cycle-b
::pco/input [{:a [:c]}]
::pco/output [:b]}
{::pco/op-name 'cycle-c
::pco/input [:b]
::pco/output [:c]}]
::eql/query [:b]}))))))

(deftest compute-run-graph-nested-inputs-test
(testing "discard non available paths on nesting"
Expand Down Expand Up @@ -1350,24 +1397,28 @@

(deftest compute-run-graph-nested-inputs-cycles-test
(testing "basic impossible nested input path"
(is
(thrown-with-msg?
#?(:clj Throwable :cljs :default)
#"Pathom can't find a path for the following elements in the query at path \[:parent]:\n- Attribute :child inputs can't be met, details: WIP"
(compute-run-graph
{::resolvers [{::pco/op-name 'parent
::pco/output [{:parent [:foo]}]}
{::pco/op-name 'child
::pco/input [{:parent [:child]}]
::pco/output [:child]}]
::eql/query [:child]}))))
(check (=>
{:ex/message
(str
"Pathom can't find a path for the following elements in the query at path [:parent]:\n"
"- Attribute :child inputs can't be met, details:\n")}
(compute-run-graph-ex
{::resolvers [{::pco/op-name 'parent
::pco/output [{:parent [:foo]}]}
{::pco/op-name 'child
::pco/input [{:parent [:child]}]
::pco/output [:child]}]
::eql/query [:child]}))))

(testing "indirect cycle"
(is
(thrown-with-msg?
#?(:clj Throwable :cljs :default)
#"Pathom can't find a path for the following elements in the query at path \[:parent]:\n- Attribute :child-dep inputs can't be met, details: WIP"
(compute-run-graph
(check
(=>
{:ex/message
(str
"Pathom can't find a path for the following elements in the query at path [:parent]:\n"
"- Attribute :child-dep inputs can't be met, details:\n"
" - Can't reach attribute :child")}
(compute-run-graph-ex
{::resolvers [{::pco/op-name 'parent
::pco/output [{:parent [:foo]}]}
{::pco/op-name 'child
Expand All @@ -1379,11 +1430,13 @@
::eql/query [:child]}))))

(testing "deep cycle"
(is
(thrown-with-msg?
#?(:clj Throwable :cljs :default)
#"Pathom can't find a path for the following elements in the query at path \[:parent]:\n- Attribute :child inputs can't be met, details: WIP"
(compute-run-graph
(check
(=>
{:ex/message
(str
"Pathom can't find a path for the following elements in the query at path [:parent]:\n"
"- Attribute :child inputs can't be met, details:\n")}
(compute-run-graph-ex
{::resolvers [{::pco/op-name 'parent
::pco/output [{:parent [:foo]}]}
{::pco/op-name 'child
Expand Down

0 comments on commit a9857a2

Please sign in to comment.