Skip to content

Instantly share code, notes, and snippets.

@hden
Created August 5, 2023 02:35
Show Gist options
  • Save hden/d3348cb1c795c9422ae655343b5fbf40 to your computer and use it in GitHub Desktop.
Save hden/d3348cb1c795c9422ae655343b5fbf40 to your computer and use it in GitHub Desktop.
Async datascript reader using firestore
(ns dev.core
(:require [clojure.edn :as edn]
[datascript.core :as d]
[datascript.storage :refer [IStorage]])
(:import
(com.google.cloud.firestore DocumentReference
EventListener
FieldMask
Firestore
FirestoreOptions)
(com.google.auth.oauth2 GoogleCredentials)))
(defn freeze
"clj->edn"
[& xs]
(binding [*print-length* nil
*print-dup* nil
*print-level* nil
*print-readably* true]
(apply pr-str xs)))
(defn thaw
"edn->clj"
[s]
(edn/read-string s))
(extend-protocol IStorage
DocumentReference
(-store [ref addr+data-seq]
(let [fields (into {}
(map (fn [[addr data]]
(println ::store addr data)
[(str addr) (freeze data)]))
addr+data-seq)]
(.get (.update ref fields))))
(-restore [ref addr]
(println ::restore addr)
(let [field (str addr)
fields (FieldMask/of (into-array String [field]))
future (.get ref fields)
document (.get future)]
(when (and (some? document) (.exists document))
(when-let [data (.getString document field)]
(thaw data))))))
(defn reset-storage!
[^DocumentReference storage]
(.get (.set storage {}))
storage)
(defn create-reader
[{:keys [^DocumentReference storage]}]
(let [reader (atom (d/restore storage))
listener (reify EventListener
(onEvent [_ document ex]
(when ex
(println ::ex ex))
(when (and (some? document) (.exists document))
(reset! reader (d/restore storage)))))]
(.addSnapshotListener storage listener)
reader))
(def firestore
(let [builder (.toBuilder (FirestoreOptions/getDefaultInstance))]
(doto builder
(.setProjectId "project-id")
(.setCredentials (GoogleCredentials/getApplicationDefault)))
(.getService (.build builder))))
(def storage
(-> firestore
(.collection "datascript")
(.document "test")
(reset-storage!)))
(defn -main
[& args]
(let [writer (d/create-conn {} {:storage storage})
reader (create-reader {:storage storage})]
(d/transact! writer [{:db/id -1
:foo "bar"}])
(Thread/sleep 1000)
(println "reader>" (d/q '[:find (pull ?e [*])
:where [?e :foo "bar"]]
@reader))))
@hden
Copy link
Author

hden commented Aug 5, 2023

output

:dev.core/store 268435457 {:level 0, :keys []}
:dev.core/store 268435458 {:level 0, :keys []}
:dev.core/store 268435459 {:level 0, :keys []}
:dev.core/store 0 {:schema {}, :max-tx 536870912, :aevt 268435458, :max-addr 268435459, :avet 268435459, :branching-factor 512, :max-eid 0, :ref-type :soft, :eavt 268435457}
:dev.core/store 1 []
:dev.core/restore 0
:dev.core/restore 1
:dev.core/store 1 [[[1 :foo bar 536870913]]]
:dev.core/restore 0
:dev.core/restore 1
:dev.core/restore 268435457
:dev.core/restore 268435458
reader> ([{:db/id 1, :foo bar}])

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