reducecombine / fridge

Ideas for awesomer Clojure development
0 stars 0 forks source link

datomic.api wrapper #6

Open vemv opened 5 years ago

vemv commented 5 years ago

Problem statement

Possible solution

Create a wrapper backed by utils.spec.

Non-goals

Create an abstraction or convenience layer over Datomic. API should remain 99% as-is.

Considerations

1.-

clojure.test/*assert* should be observed; if false, most development niceties should be disabled

2.-

I found the following pattern in the wild:

[datomic.client.api :as d.sync]
[datomic.client.api.async :as d.async]

The distinction is useful but ad-hoc. The following naming:

[<prefix>.datomic.client.sync]
[<prefix>.datomic.client.async]

Would lead to non-ad-hoc aliases:

[<prefix>.datomic.sync :as datomic.sync]
[<prefix>.datomic.async :as datomic.async]

i.e., we can make things homogeneous and unmistakable.

vemv commented 5 years ago

Specific example:

:db.error/past-tx-instant Time conflict: Thu Apr 25 04:26:57 CEST 2019 is older than database basis

Tells you nothing about the transaction that failed. That forces one to go on a hunt for the culprit.


A good place to fix this would be in the implicit derefing. As mentioned, we will do derefing within the library.

So the call to deref can be extended to:

(let [tx-data ...
      tx (transact conn tx-data)]
  (try
    @tx
    (catch Exception e
      (throw (ex-info "Oops" {:original-exception e
                              :tx-data tx-data})))))

Furthermore, if we detect that e matches :db.error/past-tx-instant, we can get the latest transaction and print it. i.e we show the old transaction that caused the new one to fail.