bamarco / datahike

A durable datalog implementation adaptable for distribution.

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

datahike Gitter

This project is a port of datascript to the hitchhiker-tree. All datascript tests are passing, but we are still working on the internals. Having said this we consider datahike usable for small projects, since datascript is very mature and deployed in many applications and the hitchhiker-tree implementation is at least heavily tested through generative testing. We are only providing the glue code between the two projects and the storage backends for the hitchhiker-tree through konserve. The codebase is subject to change though. We would like to hear experience reports and are happy if you join us.

Usage

Add to your leiningen dependencies:

Clojars Project

In general all datascript documentation applies.

The code is currently a drop-in replacement for datascript on the JVM. If you are interested in this topic, please play around and give suggestions.

The following example is taken from the store test which tests writing and reading the hitchhiker-tree. Notice that you have control when you flush to the store and can also use batching.

(ns datahike.test.store
  (:require
   #?(:cljs [cljs.test    :as t :refer-macros [is are deftest testing]]
      :clj  [clojure.test :as t :refer        [is are deftest testing]])
   [datahike.core :as d]
   [datahike.db :as db]
   [datahike.query-v3 :as q]
   [datahike.test.core :as tdc]
   [hitchhiker.konserve :as kons]
   [hitchhiker.tree.core :as hc :refer [<??]]
   [konserve.filestore :refer [new-fs-store]]))


(def db (d/db-with
         (d/empty-db {:name {:db/index true}})
         [{ :db/id 1, :name  "Ivan", :age   15 }
          { :db/id 2, :name  "Petr", :age   37 }
          { :db/id 3, :name  "Ivan", :age   37 }
          { :db/id 4, :age 15 }]))

(def store (kons/add-hitchhiker-tree-handlers
            (async/<!! (new-fs-store "/tmp/datahike-play"))))


(def backend (kons/->KonserveBackend store))

(defn store-db [db backend]
  (let [{:keys [eavt-durable aevt-durable avet-durable]} db]
    {:eavt-key (kons/get-root-key (:tree (<?? (hc/flush-tree eavt-durable backend))))
     :aevt-key (kons/get-root-key (:tree (<?? (hc/flush-tree aevt-durable backend))))
     :avet-key (kons/get-root-key (:tree (<?? (hc/flush-tree avet-durable backend))))}))

(defn load-db [stored-db]
  (let [{:keys [eavt-key aevt-key avet-key]} stored-db
        empty (d/empty-db)
        eavt-durable (<?? (kons/create-tree-from-root-key store eavt-key))]
    (assoc empty
           :max-eid (datahike.db/init-max-eid (:eavt empty) eavt-durable)
           :eavt-durable eavt-durable
           :aevt-durable (<?? (kons/create-tree-from-root-key store aevt-key))
           :avet-durable (<?? (kons/create-tree-from-root-key store avet-key)))))

(let [stored-db (store-db db backend)
      loaded-db (load-db stored-db)]
    (is (= (d/q '[:find ?e
                  :where [?e :name]] loaded-db)

           #{[3] [2] [1]}))
    (let [updated (d/db-with loaded-db
                             [{:db/id -1 :name "Hiker" :age 9999}])]
      (is (= (d/q '[:find ?e
                    :where [?e :name "Hiker"]] updated)

             #{[5]}))))

TODO

  • GC or eager deletion of fragments
  • use core.async in the future to provide durability also in a ClojureScript environment. core.async needs to be balanced with query performance though.
  • run comprehensive query suite and compare to datascript and datomic

License

Copyright © 2014–2018 Christian Weilbach, Nikita Prokopov

Licensed under Eclipse Public License (see LICENSE).

About

A durable datalog implementation adaptable for distribution.

License:Eclipse Public License 1.0


Languages

Language:Clojure 94.5%Language:JavaScript 4.9%Language:HTML 0.6%Language:Shell 0.0%