Skip to content

Conversation

@bamarco
Copy link
Contributor

@bamarco bamarco commented Aug 3, 2017

There are some issues we are solving for datsync to make the datomic/datascript transition smoother and I wanted to get your thoughts on the possiblity of adding tx-middleware to datascript.

This would address issues #193 and #174
We will be using something along these lines in datsync, but I think it fits better in datascript itself.

  • we still need to put the actual validation in as describe in Editable schema #174 but the stub for it is hooked in
  • In init-db I added an options map to turn off validation when it is undesirable which would allow people affected by Allow skipping schema validation #193 to make their own create-conn function in user space that skips validation
  • tx-middleware will allow you to use schema-middleware to check txs for schema changes and put them into the schema map, but this would also open up capabilities like adding validation middleware for all the datomic :db/valueType for people who want type safety rather than speed and other things of that nature
  • right now i put the schema-middleware in datascript.db but it could be put in its own ns if you think that makes more sense
  • brings us closer to full ident support without performance hits on people who don't need that

Usage would look like

(defn test-schema-middleware []
  (let [conn (ds/create-conn)]
    (ds/transact!
      conn
      [{:db/ident :test
        :db/cardinality :db.cardinality/many}]
      {:datascript.db/tx-middleware datascript.db/schema-middleware})
    (ds/transact!
      conn
      [{:db/id -1
        :test :a}
       {:db/id -1
        :test :b}])
    @conn))

This change is Reviewable

@metasoarous
Copy link

FWIW @tonsky, this was the original inspiration behind #150. At the time, Datsync and Posh were both needing to override various behavior of vanilla DataScript, and thought protocols might simplify things. Upon further reflection though, much of the behavior we wanted to override could be expressed via transaction middleware. I think if we get the shape of the tx-middleware idea right, it will be a much more composable way of getting much of the desired flexibility.

@bamarco Would you please describe the signature of the tx-middleware function to clarify how it handles database, tx-data and tx-report?

@tonsky Please let us know if you have any questions or concerns.

@bamarco
Copy link
Contributor Author

bamarco commented Sep 5, 2017

As currently written, tx-middleware is a function which takes a transaction-fn and returns a transaction-fn. The transaction-fn has the signature of datascript.db/transact-tx-data which takes in an initial-tx-report and some txs.

(defn schema-middleware [transact]
  (fn [report txs]
    (let [{:as report :keys [db-after tx-data]} (transact report txs)
          db-after' (transduce
                    (filter schema-datom?)
                    conj-schema-datom
                    db-after
                    tx-data)]
      (if (= (:schema db-after) (:schema db-after'))
        report
        (assoc report
          :db-after (replace-schema db-after (:schema db-after')))))))

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants