Fork me on GitHub
#hyperfiddle
<
2023-08-30
>
grounded_sage19:08:23

I'm looking at making Datahike work easily with Electric like the Datalevin/Datascript starters. Though e/watch does not appear to trigger the updates. When I do add-watch on the database connection it triggers the callback. I am unsure what is different with e/watch and how to debug this.

Dustin Getz19:08:30

e/watch is implemented in terms of the atom subscription interfaces provided by clojure.core, likely Datahike does not implement them

Dustin Getz19:08:49

you can implement the reactive subscription with m/observe, search in #CL85MBPEF for discussions related to this

grounded_sage19:08:52

Yea I have taken a good look at missionary today. But I still wanted to figure out why the simple solution doesn't work.

Dustin Getz19:08:17

Ok I now see you tried add-watch against datahike and it works

grounded_sage19:08:41

There is (:wrapped-atom conn) which returns an atom which works with the normal watcher. There is also a branch about to be merged that makes it possible to do without this.

Dustin Getz19:08:14

if add-watch is working, i expect e/watch is working as well, try to confirm it with just a println

Dustin Getz19:08:00

next likely issue is that equality is implemented wrong and/or hacked on whatever object is returned by the subscription callback

grounded_sage19:08:02

(binding [db (e/watch conn)]
     (println "This is the db: " db)
     (println "the db query: " (dh/q '[:find [?e ...] :in $ ?status
                                       :where [?e :task/status ?status]] db :active))...)
This works when I refresh the page. I can add a task with the UI.

grounded_sage19:08:39

But it doesn't trigger when I transact. I have to do the page refresh to get it printing. So I'm missing something.

Dustin Getz19:08:14

I don't understand

Dustin Getz19:08:35

"works" and "doesn't work" is also underspecified, please state expectations and actual

grounded_sage19:08:36

All good. I will look at what you mentioned just above.

grounded_sage20:08:35

Does seem to be an equality issue.

Vincent16:08:12

fascinating

grounded_sage17:08:44

Current status: Can transact at the repl and get the result rendered in electric. This was not working before as there was an issue with equality. However transact wrapped in electric causes a failure. We are unsure why this is happening. It fails silently.

👀 2
grounded_sage17:08:20

It spat out this at one point long after it stopped working.

ERROR:
java.lang.UnsupportedOperationException
	at java.base/java.lang.Thread.stop(Thread.java:1705)
	at nrepl.middleware.session$interrupt_stop$fn__22452.invoke(session.clj:198)
	at clojure.core$binding_conveyor_fn$fn__5823.invoke(core.clj:2047)
	at clojure.lang.AFn.call(AFn.java:18)
	at java.base/java.util.concurrent.FutureTask.run(FutureTask.java:317)
	at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1144)
	at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:642)
	at java.base/java.lang.Thread.run(Thread.java:1623)

👀 2
Vincent17:08:23

Hmm binding conveyor is new to me, although it makes sense there would be some sort of binding sequence /conveyor belt... UnsupportedOperation shows up when ... i'm thinking there might be some gap in datahike - a vague hunch.

Dustin Getz17:08:01

i don’t recognize that, but try wrapping in e/offload

👍 2
grounded_sage18:08:01

e/offload doesn't appear to do it. Extra information: • when I transact inside electric the transaction works. Querying at the repl I can verify this. • the repl eventually dies though @U055PQH9R4M the error shows up on browser refresh

👀 2
grounded_sage18:08:41

I've invited you to repo @U09K620SG also happy to invite anyone else that can help surface the error.

xificurC19:08:15

if the API is the same as datascript you can try to swap out the requires and see if it works. We know datascript works so it would be a user error

grounded_sage19:08:44

There is a lot happening with Datahike and it has heavily diverged from Datascript. We are working to get it functional with Electric. The silent failure makes it a little difficult to tell where the error is.

grounded_sage19:08:04

I also just tested transacting from within electric with e/watch commented out. Then queried in repl. This works repeatedly. So it is somewhere between transact inside of electric and the watch that an error is occurring.

grounded_sage19:08:32

Having a Datahike starter is interesting IMO because you can use the JDBC interface and point to a service like Supabase for a PostgreSQL backend or use the S3 backend. Easy persistence.

grounded_sage19:08:03

I can actually just make this repo public since it is going to be anyways. https://github.com/groundedsage/electric-starter-datahike

xificurC20:08:21

my suggestion to put datascript in was a temporary test to rule out user errors. Having a working datahike starter app is a great and much appreciated effort!

xificurC20:08:40

the link is a 404

grounded_sage20:08:19

Ah it wasn't properly public. It is now.

grounded_sage20:08:55

I copied the Datalevin starter someone had created. Datalevin is still in it commented out so I can switch between it for ruling out errors in userland.

👍 2
👀 2
😟 2
xificurC20:08:26

I'm not familiar with datahike's internals but from a quick glance the :wrapped-atom is some sort of internal thing? From the public API I'd use listen to receive alerts about new transactions and deref the connection at that point

xificurC20:08:21

(dh/listen conn #(reset! !db (:db-after %)))

grounded_sage20:08:44

Was trying to get (binding [db (e/watch conn)] ...) working out of the box. Because conn can be watched.

whilo20:08:13

i will take a look into this later tonight, having electric support would be super nice

whilo20:08:56

i currently work on the connection management in datahike and added the watcher lately. maybe equality has some problem, but it was always tested since we forked from datascript.

Dustin Getz10:09:06

you copied a third party starter app repo? don’t do that, you must start from ours

👍 2
Dustin Getz10:09:19

third party repos are not maintained and likely junk

Dustin Getz10:09:15

@U1C36HC6N datascript db equality was broken we had to fix it

whilo17:09:30

i see, is your fix upstream?

whilo17:09:51

we have rolling hashes already, which make equality tests faster, but need to check how far i can piggy back on them

Dustin Getz17:09:14

our datascript PR is linked in the ask datomic url above

whilo02:09:14

i implemented a fix that does not require the identical? hack of datascript, but checks hash equality instead

grounded_sage22:09:52

Tested this today and it worked.

🎉 4
grounded_sage08:09:33

I get this error when building to a jar. Has anyone seen this before?

WARN  org.eclipse.jetty.websocket.common.WebSocketSession: Exception while notifying onError
java.lang.NoClassDefFoundError: clojure/tools/logging/impl/LoggerFactory
	at hyperfiddle.electric_jetty_adapter$electric_ws_adapter$on_error__44172.invoke(electric_jetty_adapter.clj:71)
	at ring.adapter.jetty9.websocket$proxy_ws_adapter$fn__44027.invoke(websocket.clj:153)
	at ring.adapter.jetty9.websocket.proxy$org.eclipse.jetty.websocket.api.WebSocketAdapter$WebSocketPingPongListener$12d400b6.onWebSocketError(Unknown Source)
	at org.eclipse.jetty.websocket.common.events.JettyListenerEventDriver.onError(JettyListenerEventDriver.java:169)
	at org.eclipse.jetty.websocket.common.WebSocketSession.callApplicationOnError(WebSocketSession.java:416)
	at org.eclipse.jetty.websocket.common.io.AbstractWebSocketConnection.close(AbstractWebSocketConnection.java:209)
	at org.eclipse.jetty.websocket.common.WebSocketSession.close(WebSocketSession.java:130)
	at org.eclipse.jetty.websocket.common.events.AbstractEventDriver.openSession(AbstractEventDriver.java:221)
	at org.eclipse.jetty.websocket.common.WebSocketSession.open(WebSocketSession.java:493)
	at org.eclipse.jetty.websocket.common.WebSocketSession.onOpened(WebSocketSession.java:459)
	at org.eclipse.jetty.io.AbstractConnection.onOpened(AbstractConnection.java:213)
	at org.eclipse.jetty.io.AbstractConnection.onOpen(AbstractConnection.java:205)
	at org.eclipse.jetty.io.AbstractEndPoint.upgrade(AbstractEndPoint.java:444)
	at org.eclipse.jetty.server.HttpConnection.onCompleted(HttpConnection.java:401)
	at org.eclipse.jetty.server.HttpChannel.onCompleted(HttpChannel.java:820)
	at org.eclipse.jetty.server.HttpChannel.handle(HttpChannel.java:368)
	at org.eclipse.jetty.server.HttpConnection.onFillable(HttpConnection.java:279)
	at org.eclipse.jetty.io.AbstractConnection$ReadCallback.succeeded(AbstractConnection.java:311)
	at org.eclipse.jetty.io.FillInterest.fillable(FillInterest.java:105)
	at org.eclipse.jetty.io.ChannelEndPoint$1.run(ChannelEndPoint.java:104)
	at org.eclipse.jetty.util.thread.strategy.EatWhatYouKill.runTask(EatWhatYouKill.java:336)
	at org.eclipse.jetty.util.thread.strategy.EatWhatYouKill.doProduce(EatWhatYouKill.java:313)
	at org.eclipse.jetty.util.thread.strategy.EatWhatYouKill.tryProduce(EatWhatYouKill.java:171)
	at org.eclipse.jetty.util.thread.strategy.EatWhatYouKill.produce(EatWhatYouKill.java:135)
	at org.eclipse.jetty.util.thread.QueuedThreadPool.runJob(QueuedThreadPool.java:882)
	at org.eclipse.jetty.util.thread.QueuedThreadPool$Runner.run(QueuedThreadPool.java:1036)
	at java.base/java.lang.Thread.run(Thread.java:1623)
Caused by: java.lang.ClassNotFoundException: clojure.tools.logging.impl.LoggerFactory
	at java.base/jdk.internal.loader.BuiltinClassLoader.loadClass(BuiltinClassLoader.java:641)
	at java.base/jdk.internal.loader.ClassLoaders$AppClassLoader.loadClass(ClassLoaders.java:188)
	at java.base/java.lang.ClassLoader.loadClass(ClassLoader.java:521)
	... 27 common frames omitted
WARN  org.eclipse.jetty.websocket.common.WebSocketSession: Exception while notifying onClose
java.lang.NoClassDefFoundError: clojure/tools/logging/impl/LoggerFactory
	at hyperfiddle.electric_jetty_adapter$electric_ws_adapter$on_close__44165.invoke(electric_jetty_adapter.clj:68)
	at ring.adapter.jetty9.websocket$proxy_ws_adapter$fn__44031.invoke(websocket.clj:159)
	at 

xificurC08:09:39

do you have tools.logging on the classpath?

grounded_sage08:09:00

How do I check that?

xificurC08:09:27

what command are you running to build?

grounded_sage08:09:58

HYPERFIDDLE_ELECTRIC_APP_VERSION=`git describe --tags --long --always --dirty`
clojure -X:build uberjar :jar-name "app.jar" :version '"'$HYPERFIDDLE_ELECTRIC_APP_VERSION'"'
java -DHYPERFIDDLE_ELECTRIC_SERVER_VERSION=$HYPERFIDDLE_ELECTRIC_APP_VERSION -jar app.jar

grounded_sage08:09:27

I am using the official electric-starter-app and swapped out Datascript for Datahike.

grounded_sage08:09:23

yea. I am a little confused as to how to resolve this. I've been looking at clj -Stree etc and looked at dependencies. It does build normally so somehow Datahike being added is booting it off the path?

xificurC08:09:29

btw clj -X:build:deps list to list deps with the :build alias

xificurC08:09:45

do you have a repo where I can repro your issue?

grounded_sage09:09:41

Will have one to share later today

👍 2
grounded_sage11:09:43

So I've gone back to a minimum repo to figure out how I actually build a persistent database connected Electric. Here is the repo: https://github.com/groundedsage/electric-starter-datahike Changes I made. • Moved user.clj to src-dev • added (alter-var-root #'app/!datahike (constantly (app/start-datahike!))) to prod.clj • the hyperfiddle version check is commented out to test clj -M -m prod works clj -A:dev -X user/main works When I build the jar and then run it. This is the error I get.

$ electric-starter-datahike % java -DHYPERFIDDLE_ELECTRIC_SERVER_VERSION=$HYPERFIDDLE_ELECTRIC_APP_VERSION -jar app.jar
Exception in thread "main" java.lang.NoSuchFieldError: __thunk__0__
	at clojure.tools.analyzer.jvm.utils__init.load(Unknown Source)
	at clojure.tools.analyzer.jvm.utils__init.<clinit>(Unknown Source)
	at java.base/java.lang.Class.forName0(Native Method)
	at java.base/java.lang.Class.forName(Class.java:496)
	at java.base/java.lang.Class.forName(Class.java:475)
	at clojure.lang.RT.classForName(RT.java:2209)
	at clojure.lang.RT.classForName(RT.java:2218)
	at clojure.lang.RT.loadClassForName(RT.java:2237)
	at clojure.lang.RT.load(RT.java:449)
	at clojure.lang.RT.load(RT.java:424)

grounded_sage11:09:02

There is a little ceremony to run Datahike at present due to the branch I am using not being on main and the way Datahike is at present doesn't allow the usage of git sha. I haven't quite figured out how to resolve that because being able to use a git sha would be way more convenient for this kind of work.