Created
August 5, 2023 02:35
-
-
Save hden/d3348cb1c795c9422ae655343b5fbf40 to your computer and use it in GitHub Desktop.
Async datascript reader using firestore
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
(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)))) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
output