Welcome! Please see the About page for a little more info on how this works.

+1 vote
in Cloud by
edited by

com.datomic/dev-local {:mvn/version "1.0.243"}
datomic.client.api

One of our dataflow experiments is thrashing d/with rapidly (for each keystroke in a form connected by websocket) and it crashes. Obviously this is not a reasonable circumstance but wanted to report as a possible concurrency bug.

I'm not able to repro minimally yet. Confounding variables include concurrency model, whether the d/with calls are parallel or composed, whether the d/with calls are interrupting each other or concurrent, how Datomic responds to ThreadInterruptedException, and likely more.

d/with, tx: ([:db/add 536561674378709 :label/name "6"]) ...success

d/with, tx: ([:db/add 536561674378709 :label/name "65"]) ...failure, e:  
#error {
 :cause nil
 :via
 [{:type java.nio.channels.ClosedChannelException
   :message nil
   :at [sun.nio.ch.FileChannelImpl ensureOpen FileChannelImpl.java 159]}]
 :trace
 [[sun.nio.ch.FileChannelImpl ensureOpen FileChannelImpl.java 159]
  [sun.nio.ch.FileChannelImpl read FileChannelImpl.java 814]
  [datomic.dev_local.io$read_n_bbuf invokeStatic io.clj 66]
  [datomic.dev_local.io$read_n_bbuf invoke io.clj 63]
  [datomic.dev_local.io$read_n_buf invokeStatic io.clj 72]
  [datomic.dev_local.io$read_n_buf invoke io.clj 69]
  [datomic.dev_local.tx$keyoff_datom_bbuf invokeStatic tx.clj 374]
  [datomic.dev_local.tx$keyoff_datom_bbuf invokePrim tx.clj -1]
  [datomic.dev_local.tx$datom_lookup_valfn invokeStatic tx.clj 401]
  [datomic.dev_local.tx$datom_lookup_valfn invoke tx.clj 397]
  [datomic.dev_local.local_log.LocalLog valAt local_log.clj 56]
  [datomic.dev_local.btindex_db$double_lookup$reify__19853 valAt btindex_db.clj 404]
  [datomic.dev_local.btindex$lookup_cmp$reify__19649 valAt btindex.clj 268]
  [datomic.dev_local.btindex.BTIndexLeaf leftk btindex.clj 238]
  [datomic.dev_local.btindex$leftk invokeStatic btindex.clj 59]
  [datomic.dev_local.btindex$leftk invoke btindex.clj 58]
  [datomic.dev_local.btindex.BTIndexBranch bspos btindex.clj 165]
  [datomic.dev_local.btindex.BTIndexBranch seek btindex.clj 184]
  [datomic.dev_local.btindex.BTIndexBranch seek btindex.clj 185]
  [datomic.dev_local.btindex.BTIndex seek btindex.clj 310]
  [datomic.core.btset$seek invokeStatic btset.clj 405]
  [datomic.core.btset$seek invoke btset.clj 400]
  [datomic.core.db.Db seekEAVT db.clj 2195]
  [datomic.core.db$find_eavt invokeStatic db.clj 1135]
  [datomic.core.db$find_eavt invoke db.clj 1129]
  [datomic.core.db$find_eavt invokeStatic db.clj 1132]
  [datomic.core.db$find_eavt invoke db.clj 1129]
  [datomic.core.db$next_valid_inst invokeStatic db.clj 3041]
  [datomic.core.db$next_valid_inst invoke db.clj 3037]
  [datomic.core.db.ProcessExpander getData db.clj 3291]
  [datomic.dev_local.btindex_db$expand_tx invokeStatic btindex_db.clj 445]
  [datomic.dev_local.btindex_db$expand_tx invoke btindex_db.clj 429]
  [datomic.dev_local.with_db.WithDb with with_db.clj 73]
  [datomic.client.api$with invokeStatic api.clj 363]
  [datomic.client.api$with invoke api.clj 353]
  [clojure.core$eval39795$fn__39796$fn__39797 invoke NO_SOURCE_FILE 0]
  [clojure.core$eval39787$fn__39788$fn__39789$fn__39790 invoke NO_SOURCE_FILE 0]
  [clojure.lang.Atom swap Atom.java 37]
  [clojure.core$swap_BANG_ invokeStatic core.clj 2369]
  [clojure.core$swap_BANG_ invoke core.clj 2362]
  [clojure.core$eval39787$fn__39788$fn__39789 invoke NO_SOURCE_FILE 0]
  [hyperfiddle.photon$wrap_STAR_$cr31022_block_0__31024$cr31022_place_2__31025 invoke photon.cljc 154]
  [missionary.impl.Thunk run Thunk.java 58]
  [java.util.concurrent.ThreadPoolExecutor runWorker ThreadPoolExecutor.java 1136]
  [java.util.concurrent.ThreadPoolExecutor$Worker run ThreadPoolExecutor.java 635]
  [java.lang.Thread run Thread.java 833]]}

some test code that does NOT repro the bug:

  (def tx1 [[:db/add 536561674378709 :label/name "6"]])
  (def tx2 [[:db/add 536561674378709 :label/name "65"]])
  
  (def db0 (d/with-db test/datomic-conn)) ; mbrainz-samples
  
  (do
    (:db-after (d/with db0 {:tx-data tx1}))
    (:db-after (d/with db0 {:tx-data tx2})))

  (let [db1 (:db-after (d/with db0 {:tx-data tx1}))
        db2 (:db-after (d/with db1 {:tx-data tx2}))]
    db2)

1 Answer

0 votes
by

Thanks for the report! I've made a ticket for Dev to review after the break.

...