This page is not created by, affiliated with, or supported by Slack Technologies, Inc.
2023-07-22
Channels
As I am writing a Datahike pod I tried out how the error handling works and I now got a problem that I don't know how to solve. Based on bad input to a function it throws an exception but this exception seems not to be handled well in babashka or is it something I need to fix?
https://app.circleci.com/pipelines/github/TimoKramer/datahike/458/workflows/0bb82d13-49ce-4f24-90bb-053dc6721dca/jobs/2251
https://github.com/TimoKramer/datahike/blob/feat/babashka-pod/bb/resources/native-image-tests/run-bb-pod-tests.clj#L63
running locally with bb ni-cli && ./bb/resources/native-image-tests/run-bb-pod-tests.clj
You're supposed to handle exceptions yourself in the pod loop and send an exception response
I think it's documented in the README of the pods project. Let me know it isn't. There's also tests for it
I think I got it as advertised, basically copied it over from other pods: https://github.com/TimoKramer/datahike/blob/feat/babashka-pod/src/datahike/pod.clj#L239-267
Just thought this is a problem in bb but if you're sure it's not I guess you're right:
#error {
:cause "clojure.lang.PersistentVector cannot be cast to byte[]"
:via
[{:type java.lang.ClassCastException
:message "clojure.lang.PersistentVector cannot be cast to byte[]"
:at [babashka.pods.impl$bytes__GT_string invokeStatic "impl.clj" 28]}]
:trace
[[babashka.pods.impl$bytes__GT_string invokeStatic "impl.clj" 28]
[babashka.pods.impl$processor invokeStatic "impl.clj" 190]
[babashka.pods.sci$load_pod$fn__27430 invoke "sci.clj" 122]
[sci.impl.vars$binding_conveyor_fn$fn__424 invoke "vars.cljc" 133]
[clojure.core$binding_conveyor_fn$fn__5823 invoke "core.clj" 2047]
[clojure.lang.AFn call "AFn.java" 18]
[java.util.concurrent.FutureTask run "FutureTask.java" 264]
[java.util.concurrent.ThreadPoolExecutor runWorker "ThreadPoolExecutor.java" 1128]
[java.util.concurrent.ThreadPoolExecutor$Worker run "ThreadPoolExecutor.java" 628]
[java.lang.Thread run "Thread.java" 829]
[com.oracle.svm.core.thread.PlatformThreads threadStartRoutine "PlatformThreads.java" 705]
[com.oracle.svm.core.posix.thread.PosixPlatformThreads pthreadStartRoutine "PosixPlatformThreads.java" 202]]}
doesn't ring a bell. what I would do is debug with the JVM pods library. perhaps you can do the same
if you aren't aware, I'd also recommend running your pod in a JVM, so you don't have to graal compile it every time you make a change, this iterates much faster
hm, I tried a few things, but couldn't find the problem. It think it's the input to the bytes->string
-fn... 🤷
just try printing what goes into that function and report back. check out the pods library using :local/root and make a println change
so the function receives an empty persistenvector presumably from the ex-message part of the processor
why do you think it hits that path? don't the locations you pasted above show that it's this codepath? https://github.com/babashka/pods/blob/8b717eb001811bc5da5d15d1163565de00b4ffa4/src/babashka/pods/impl.clj#L190-L193
that's what I thought but I couldn't find the problem there since it has the some->>
macro in there
BABASHKA_POD=true "clojure" "-M" "-m" "datahike.cli"
Execution error (ClassNotFoundException) at java.net.URLClassLoader/findClass (URLClassLoader.java:445).
datahike.java.IEntity
new error:
$ BABASHKA_POD=true "clojure" "-M" "-m" "datahike.cli"
Execution error (FileNotFoundException) at datahike.pod/eval37638$loading (pod.clj:1).
Could not locate bencode/core__init.class, bencode/core.clj or bencode/core.cljc on classpath.
Full report at:
/var/folders/j9/xmjlcym958b1fr0npsp9msvh0000gn/T/clojure-14533572372815876965.edn
I'm willing to take another look if you can set up stuff in a way that I can debug with the pods library and have clear instructions how to start
One thing I changed in run-bb-pod-tests was:
(pods/load-pod ["clojure" "-M" "-m" "datahike.cli"])
$ ./bb/resources/native-image-tests/run-bb-pod-tests.clj
Testing user
Ran 1 tests containing 20 assertions.
0 failures, 0 errors.
so it works when running the pod in a JVM. Could be a reflection issue perhaps? It might be worth fixing these:
$ BABASHKA_POD=true "clojure" "-M:pod" "-m" "datahike.cli"
:yolo
Reflection warning, superv/async.cljc:834:40 - reference to field getTime on java.lang.Object can't be resolved.
Reflection warning, datahike/array.cljc:45:13 - call to static method compare on java.util.Arrays can't be resolved (argument types: unknown, unknown).
Reflection warning, datahike/db/transaction.cljc:231:32 - reference to field e can't be resolved.
Reflection warning, datahike/query_stats.cljc:6:11 - call to java.math.MathContext ctor can't be resolved.
sorry, played around with it too long yesterday and changed the failing test. here it is again: https://github.com/TimoKramer/datahike/blob/feat/babashka-pod/bb/resources/native-image-tests/run-bb-pod-tests.clj#L63 https://app.circleci.com/pipelines/github/TimoKramer/datahike/462/workflows/ff92a007-bd28-46a0-b44b-405325423017/jobs/2282?invite=true#step-102-288
borkdude@m1 /tmp/datahike (feat/babashka-pod?) $ ./bb/resources/native-image-tests/run-bb-pod-tests.clj
----- Error --------------------------------------------------------------------
Type: java.lang.NullPointerException
Location: /private/tmp/datahike/./bb/resources/native-image-tests/run-bb-pod-tests.clj:7:1
----- Context ------------------------------------------------------------------
3: (require '[babashka.pods :as pods]
4: '[clojure.test :refer [run-tests deftest testing is]])
5: (import '[java.util Date])
6:
7: (pods/load-pod ["clojure" "-M:pod" "-m" "datahike.cli"])
^---
8:
9: (require '[datahike.pod :as d])
10:
11: (def config {:keep-history? true,
12: :search-cache-size 10000,
----- Stack trace --------------------------------------------------------------
babashka.pods.impl/bytes->string - <built-in>
babashka.pods.impl/describe->metadata - <built-in>
babashka.pods.impl/load-pod - <built-in>
babashka.pods.sci/load-pod/fn--28088 - <built-in>
babashka.pods.sci/load-pod - <built-in>
clojure.core/apply - <built-in>
babashka.impl.pods/load-pod - <built-in>
user - /private/tmp/datahike/./bb/resources/native-image-tests/run-bb-pod-tests.clj:7:1
borkdude@m1 /tmp/datahike (feat/babashka-pod?) $ Reflection warning, superv/async.cljc:834:40 - reference to field getTime on java.lang.Object can't be resolved.
Reflection warning, datahike/array.cljc:45:13 - call to static method compare on java.util.Arrays can't be resolved (argument types: unknown, unknown).
Reflection warning, datahike/db/transaction.cljc:231:32 - reference to field e can't be resolved.
Reflection warning, datahike/query_stats.cljc:6:11 - call to java.math.MathContext ctor can't be resolved.
:writing {"format" "transit+json", "namespaces" [{"name" "datahike.pod", "vars" [{"name" "delete-database"} {"name" "pull"} {"name" "entity"} {"name" "metrics"} {"name" "datoms"} {"name" "q"} {"name" "schema"} {"name" "pull-many"} {"name" "since"} {"name" "create-database"} {"name" "db"} {"name" "connect"} {"name" "history"} {"name" "database-exists?"} {"name" "transact"} {"name" "as-of"} {"name" "release-db"} {"name" "db-with"} {"name" "with-db", "code" "(defmacro with-db [bindings & body]\n (cond\n (= (count bindings) 0) `(do ~@body)\n (symbol? (bindings 0)) `(let ~(subvec bindings 0 2)\n (try\n (with-db ~(subvec bindings 2) ~@body)\n (finally\n (release-db ~(bindings 0)))))\n :else (throw (IllegalArgumentException.\n \"with-db only allows Symbols in bindings\"))))"}]}], "id" "42aaf0eb-4ba1-43b4-b459-0929172b81e5", "ops" {"shutdown" {}}}
This is what I'm seeing right now: https://gist.github.com/borkdude/c44eba75eed1e766810324fb420b3251
yeah sorry, disable the debug in datahike.pod-ns. The NPE is what I expect in the test. What I am getting back with java-17-graalvm is
timo@Zockolette> ./bb/resources/native-image-tests/run-bb-pod-tests.clj ~/projects/datahike
Testing user
ERROR in (pod-workflow) (/home/timo/projects/datahike/./bb/resources/native-image-tests/run-bb-pod-tests.clj:22)
transact with bad arg
expected: (= [:tempids :db-before :db-after :tx-meta :tx-data] (keys (d/transact "foo" [{:name "Alice", :age 20} {:name "Bob", :age 30} {:name "Charlie", :age 40} {:age 15}])))
actual: clojure.lang.ExceptionInfo: Cannot invoke "java.util.concurrent.Future.get()" because "fut" is null
{:argument-type "", :type "class java.lang.NullPointerException"}
at babashka.pods.impl$processor.invokeStatic (impl.clj:219)
babashka.pods.sci$load_pod$fn__28022.invoke (sci.clj:122)
sci.impl.vars$binding_conveyor_fn$fn__440.invoke (vars.cljc:133)
clojure.core$binding_conveyor_fn$fn__5823.invoke (core.clj:2047)
clojure.lang.AFn.call (AFn.java:18)
java.util.concurrent.FutureTask.run (FutureTask.java:317)
java.util.concurrent.ThreadPoolExecutor.runWorker (ThreadPoolExecutor.java:1144)
java.util.concurrent.ThreadPoolExecutor$Worker.run (ThreadPoolExecutor.java:642)
java.lang.Thread.run (Thread.java:1589)
com.oracle.svm.core.thread.PlatformThreads.threadStartRoutine (PlatformThreads.java:775)
com.oracle.svm.core.posix.thread.PosixPlatformThreads.pthreadStartRoutine (PosixPlatformThreads.java:203)
Ran 1 tests containing 21 assertions.
0 failures, 1 errors.
can you maybe make a separate branch if this is easier? and then I'll check that one out and run
ok, this is what I'm seeing:
ERROR in (pod-workflow) (/private/tmp/datahike/./bb/resources/native-image-tests/run-bb-pod-tests.clj:22)
transact with bad arg
expected: (= [:tempids :db-before :db-after :tx-meta :tx-data] (keys (d/transact "foo" [{:name "Alice", :age 20} {:name "Bob", :age 30} {:name "Charlie", :age 40} {:age 15}])))
actual: clojure.lang.ExceptionInfo: Cannot invoke "java.util.concurrent.Future.get()" because "fut" is null
{:argument-type "", :type "class java.lang.NullPointerException"}
at babashka.pods.impl$processor.invokeStatic (impl.clj:219)
babashka.pods.sci$load_pod$fn__28124.invoke (sci.clj:122)
sci.impl.vars$binding_conveyor_fn$fn__440.invoke (vars.cljc:133)
clojure.core$binding_conveyor_fn$fn__5823.invoke (core.clj:2047)
clojure.lang.AFn.call (AFn.java:18)
java.util.concurrent.FutureTask.run (FutureTask.java:317)
java.util.concurrent.ThreadPoolExecutor.runWorker (ThreadPoolExecutor.java:1144)
java.util.concurrent.ThreadPoolExecutor$Worker.run (ThreadPoolExecutor.java:642)
java.lang.Thread.runWith (Thread.java:1636)
java.lang.Thread.run (Thread.java:1623)
com.oracle.svm.core.thread.PlatformThreads.threadStartRoutine (PlatformThreads.java:807)
com.oracle.svm.core.posix.thread.PosixPlatformThreads.pthreadStartRoutine (PosixPlatformThreads.java:210)
Ran 1 tests containing 21 assertions.
0 failures, 1 errors.
and in the catch-block from my pod-impl I am not sending a value back as you are not doing either in your samples. so I don't get the exception message since there is a some->>
and it should not get into the bytes->string
-fn
I wouldn't expect laziness in transact but I can check with @UB95JRKM3
When you feed "foo" into this function:
(defn transact [conn arg-map]
(let [c (get @conns conn)
{:keys [db-before db-after tx-meta tx-data tempids]} (d/transact c arg-map)]
(-> {:tempids tempids}
(assoc :db-before (select-keys db-before [:max-tx :max-eid]))
(assoc :db-after (select-keys db-after [:max-tx :max-eid]))
(assoc :tx-meta tx-meta)
(assoc :tx-data (map seq tx-data)))))
then c
is null. Could it be that the Cannot invoke "java.util.concurrent.Future.get()" because "fut" is null
is coming from that?
if you transact with a bad argument, why don't you expect an exception?
(testing "transact with bad arg"
(is (= [:tempids :db-before :db-after :tx-meta :tx-data]
(keys (d/transact
"foo"
[{:name "Alice", :age 20}
{:name "Bob", :age 30}
{:name "Charlie", :age 40}
{:age 15}])))))
I do expect an exception but I don't understand why I am getting the stacktrace from bb/sci
the test seems to suggest you just get some transaction data back, rather than an exception?
I don't get a stacktrace from bb/sci, I just get a failing test, like expected, I would say
hmm, so this is what you want to see when a test is failing?
at babashka.pods.impl$processor.invokeStatic (impl.clj:219)
babashka.pods.sci$load_pod$fn__28022.invoke (sci.clj:122)
sci.impl.vars$binding_conveyor_fn$fn__440.invoke (vars.cljc:133)
clojure.core$binding_conveyor_fn$fn__5823.invoke (core.clj:2047)
clojure.lang.AFn.call (AFn.java:18)
java.util.concurrent.FutureTask.run (FutureTask.java:317)
java.util.concurrent.ThreadPoolExecutor.runWorker (ThreadPoolExecutor.java:1144)
java.util.concurrent.ThreadPoolExecutor$Worker.run (ThreadPoolExecutor.java:642)
java.lang.Thread.run (Thread.java:1589)
com.oracle.svm.core.thread.PlatformThreads.threadStartRoutine (PlatformThreads.java:775)
com.oracle.svm.core.posix.thread.PosixPlatformThreads.pthreadStartRoutine
yes, this is the exception thrown from the pod processor as this is is the exception you wanted to raise by sending exception data