juji-io / datalevin

A simple, fast and versatile Datalog database
https://github.com/juji-io/datalevin
Eclipse Public License 1.0
1.07k stars 60 forks source link

Transaction Error: Entity cannot be retracted #211

Open den1k opened 1 year ago

den1k commented 1 year ago

I have a strange case where an entity cannot be retracted. Working on a repro. Logging the error here for now in case it helps

(db/transact! [[:db/retractEntity 291]])
Execution error (NullPointerException) at datalevin.db/transact-retract-datom (db.cljc:868).
Cannot read field "e" because "d" is null
java.lang.NullPointerException: Cannot read field "e" because "d" is null
    at datalevin.db$transact_retract_datom.invokeStatic(db.cljc:868)
    at datalevin.db$transact_retract_datom.invoke(db.cljc:866)
    at clojure.lang.ArrayChunk.reduce(ArrayChunk.java:63)
    at clojure.core.protocols$fn__8244.invokeStatic(protocols.clj:136)
    at clojure.core.protocols$fn__8244.invoke(protocols.clj:124)
    at clojure.core.protocols$fn__8204$G__8199__8213.invoke(protocols.clj:19)
    at clojure.core.protocols$seq_reduce.invokeStatic(protocols.clj:31)
    at clojure.core.protocols$fn__8236.invokeStatic(protocols.clj:75)
    at clojure.core.protocols$fn__8236.invoke(protocols.clj:75)
    at clojure.core.protocols$fn__8178$G__8173__8191.invoke(protocols.clj:13)
    at clojure.core$reduce.invokeStatic(core.clj:6886)
    at clojure.core$reduce.invoke(core.clj:6868)
    at datalevin.db$local_transact_tx_data$fn__12742.invoke(db.cljc:1228)
    at datalevin.db$local_transact_tx_data.invokeStatic(db.cljc:996)
    at datalevin.db$local_transact_tx_data.invoke(db.cljc:980)
    at datalevin.db$transact_tx_data.invokeStatic(db.cljc:1286)
    at datalevin.db$transact_tx_data.invoke(db.cljc:1262)
    at datalevin.core$with.invokeStatic(core.cljc:366)
    at datalevin.core$with.invoke(core.cljc:360)
    at datalevin.core$with.invokeStatic(core.cljc:363)
    at datalevin.core$with.invoke(core.cljc:360)
    at datalevin.core$_transact_BANG_$fn__15726$fn__15735$helper15739__15740$helper15741__15742.invokePrim(core.cljc:621)
    at datalevin.core$_transact_BANG_$fn__15726$fn__15735$helper15739__15740$helper15741__15742.invoke(core.cljc)
    at datalevin.core$_transact_BANG_$fn__15726$fn__15735$helper15739__15740.invokePrim(core.cljc:619)
    at datalevin.core$_transact_BANG_$fn__15726$fn__15735$helper15739__15740.invoke(core.cljc)
    at datalevin.core$_transact_BANG_$fn__15726$fn__15735.invoke(core.cljc:619)
    at datalevin.core$_transact_BANG_$fn__15726.invoke(core.cljc:619)
    at datalevin.core$_transact_BANG_.invokeStatic(core.cljc:619)
    at datalevin.core$_transact_BANG_.invoke(core.cljc:618)
    at datalevin.core$transact_BANG_.invokeStatic(core.cljc:711)
    at datalevin.core$transact_BANG_.invoke(core.cljc:624)
    at datalevin.core$transact_BANG_.invokeStatic(core.cljc:709)
    at datalevin.core$transact_BANG_.invoke(core.cljc:624)
    at tesserae.db$eval51974$fn__51975$transact_BANG___51976.invoke(form-init17514198031870106473.clj:67)
    at tesserae.ui.sheet$eval138868.invokeStatic(sheet.cljc:496)
    at tesserae.ui.sheet$eval138868.invoke(sheet.cljc:496)
    at clojure.lang.Compiler.eval(Compiler.java:7194)
    at clojure.lang.Compiler.eval(Compiler.java:7149)
    at clojure.core$eval.invokeStatic(core.clj:3215)
    at clojure.core$eval.invoke(core.clj:3211)
    at nrepl.middleware.interruptible_eval$evaluate$fn__968$fn__969.invoke(interruptible_eval.clj:87)
    at clojure.lang.AFn.applyToHelper(AFn.java:152)
    at clojure.lang.AFn.applyTo(AFn.java:144)
    at clojure.core$apply.invokeStatic(core.clj:667)
    at clojure.core$with_bindings_STAR_.invokeStatic(core.clj:1990)
    at clojure.core$with_bindings_STAR_.doInvoke(core.clj:1990)
    at clojure.lang.RestFn.invoke(RestFn.java:425)
    at nrepl.middleware.interruptible_eval$evaluate$fn__968.invoke(interruptible_eval.clj:87)
    at clojure.main$repl$read_eval_print__9206$fn__9209.invoke(main.clj:437)
    at clojure.main$repl$read_eval_print__9206.invoke(main.clj:437)
    at clojure.main$repl$fn__9215.invoke(main.clj:458)
    at clojure.main$repl.invokeStatic(main.clj:458)
    at clojure.main$repl.doInvoke(main.clj:368)
    at clojure.lang.RestFn.invoke(RestFn.java:1523)
    at nrepl.middleware.interruptible_eval$evaluate.invokeStatic(interruptible_eval.clj:84)
    at nrepl.middleware.interruptible_eval$evaluate.invoke(interruptible_eval.clj:56)
    at nrepl.middleware.interruptible_eval$interruptible_eval$fn__999$fn__1003.invoke(interruptible_eval.clj:152)
    at clojure.lang.AFn.run(AFn.java:22)
    at nrepl.middleware.session$session_exec$main_loop__1067$fn__1071.invoke(session.clj:202)
    at nrepl.middleware.session$session_exec$main_loop__1067.invoke(session.clj:201)
    at clojure.lang.AFn.run(AFn.java:22)
    at java.base/java.lang.Thread.run(Thread.java:833)

The entity also has a nil key and value when touched:

=>
{nil nil, <--
 :sheet/_cells 272,
 :cell/y 8,
 :db/id 291,
 :cell/pos [2 8],
 :db/updated-at 1683480182912,
 :cell/x 2,
 :cell/exception? false,
 :db/created-at 1683479011501}
huahaiy commented 1 year ago

Were you able to reproduce?

den1k commented 1 year ago

I was not able to. Tried to rebuild the db using the new re-index function but that errored and wiped the DB. It was just a dev DB so that was okay but I lost the faulty data that somehow caused the error.

huahaiy commented 1 year ago

OK, looks like we need to create a backup db before re-indexing.

huahaiy commented 3 months ago

0.9.0 will use a safer default write option :nometasync, so only the last transaction may be lost, but the DB will not be corrupted.

den1k commented 3 months ago

Have a similar error where it seems that data that failed to deserialize blocks a retract.

(db/transact! [[:db/retractEntity 214]])

Error handling response - class java.lang.RuntimeException: No reader function for tag datalevin/Indexable
den1k commented 3 months ago

possibly a regression: https://github.com/juji-io/datalevin/issues/208

den1k commented 3 months ago

I have not been able to come up with a repro yet.