db.cljs 6.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168
  1. (ns frontend.db
  2. (:require [clojure.core.async :as async]
  3. [datascript.core :as d]
  4. [frontend.db-schema :as db-schema]
  5. [frontend.db.conn :as conn]
  6. [frontend.db.default :as default-db]
  7. [frontend.db.model]
  8. [frontend.db.query-custom]
  9. [frontend.db.query-react]
  10. [frontend.db.react]
  11. [frontend.idb :as idb]
  12. [frontend.namespaces :refer [import-vars]]
  13. [frontend.state :as state]
  14. [frontend.util :as util]
  15. [promesa.core :as p]))
  16. (import-vars
  17. [frontend.db.conn
  18. ;; TODO: remove later
  19. conns
  20. get-repo-path
  21. datascript-db
  22. remove-db!
  23. get-conn
  24. me-tx
  25. remove-conn!]
  26. [frontend.db.utils
  27. date->int db->json db->edn-str db->string get-max-tx-id get-tx-id
  28. group-by-page seq-flatten sort-by-pos
  29. string->db with-repo
  30. entity pull pull-many transact! get-key-value]
  31. [frontend.db.model
  32. block-and-children-transform blocks-count blocks-count-cache clean-export! cloned? delete-blocks get-pre-block
  33. delete-file! delete-file-blocks! delete-file-pages! delete-file-tx delete-files delete-pages-by-files
  34. filter-only-public-pages-and-blocks get-all-block-contents get-all-tagged-pages
  35. get-all-templates get-block-and-children get-block-by-uuid get-block-children sort-by-left
  36. get-block-parent get-block-parents parents-collapsed? get-block-referenced-blocks
  37. get-block-children-ids get-block-immediate-children get-block-page
  38. get-blocks-contents get-custom-css
  39. get-date-scheduled-or-deadlines get-db-type get-file
  40. get-file-blocks get-file-contents get-file-last-modified-at get-file-no-sub get-file-page get-file-page-id file-exists?
  41. get-file-pages get-files get-files-blocks get-files-full get-journals-length
  42. get-latest-journals get-matched-blocks get-page get-page-alias get-page-alias-names get-page-blocks get-page-linked-refs-refed-pages
  43. get-page-blocks-count get-page-blocks-no-cache get-page-file get-page-format get-page-properties
  44. get-page-referenced-blocks get-page-referenced-pages get-page-unlinked-references get-page-referenced-blocks-no-cache
  45. get-all-pages get-pages get-pages-relation get-pages-that-mentioned-page get-public-pages get-tag-pages
  46. journal-page? local-native-fs? mark-repo-as-cloned! page-alias-set page-blocks-transform pull-block
  47. set-file-last-modified-at! transact-files-db! get-modified-pages page-empty? page-empty-or-dummy? get-alias-source-page
  48. set-file-content! has-children? get-namespace-pages get-all-namespace-relation]
  49. [frontend.db.react
  50. get-current-marker get-current-page get-current-priority set-key-value
  51. transact-react! remove-key! remove-q! remove-query-component! add-q! add-query-component! clear-query-state!
  52. clear-query-state-without-refs-and-embeds! get-block-blocks-cache-atom get-page-blocks-cache-atom kv q
  53. query-state query-components query-entity-in-component remove-custom-query! set-new-result! sub-key-value refresh!]
  54. [frontend.db.query-custom
  55. custom-query]
  56. [frontend.db.query-react
  57. react-query custom-query-result-transform]
  58. [frontend.db.default built-in-pages-names built-in-pages])
  59. ;; persisting DBs between page reloads
  60. (defn persist! [repo]
  61. (let [key (datascript-db repo)
  62. conn (get-conn repo false)]
  63. (when conn
  64. (let [db (d/db conn)
  65. db-str (if db (db->string db) "")]
  66. (p/let [_ (idb/set-batch! [{:key key :value db-str}])]
  67. (state/set-last-persist-transact-id! repo false (get-max-tx-id db)))))))
  68. (defonce persistent-jobs (atom {}))
  69. (defn clear-repo-persistent-job!
  70. [repo]
  71. (when-let [old-job (get @persistent-jobs repo)]
  72. (js/clearTimeout old-job)))
  73. (defn- persist-if-idle!
  74. [repo]
  75. (clear-repo-persistent-job! repo)
  76. (let [job (js/setTimeout
  77. (fn []
  78. (if (and (state/input-idle? repo)
  79. (state/db-idle? repo))
  80. (do
  81. (persist! repo)
  82. ;; (state/set-db-persisted! repo true)
  83. )
  84. (persist-if-idle! repo)))
  85. 3000)]
  86. (swap! persistent-jobs assoc repo job)))
  87. ;; only save when user's idle
  88. ;; TODO: pass as a parameter
  89. (defonce *sync-search-indice-f (atom nil))
  90. (defn- repo-listen-to-tx!
  91. [repo conn]
  92. (d/listen! conn :persistence
  93. (fn [tx-report]
  94. (when-not (util/electron?)
  95. (let [tx-id (get-tx-id tx-report)]
  96. (state/set-last-transact-time! repo (util/time-ms))
  97. (persist-if-idle! repo)))
  98. ;; rebuild search indices
  99. (let [data (:tx-data tx-report)
  100. datoms (filter
  101. (fn [datom]
  102. (contains? #{:block/name :block/content} (:a datom)))
  103. data)]
  104. (when-let [f @*sync-search-indice-f]
  105. (f datoms))))))
  106. (defn- listen-and-persist!
  107. [repo]
  108. (when-let [conn (get-conn repo false)]
  109. (repo-listen-to-tx! repo conn)))
  110. (defn start-db-conn!
  111. ([me repo]
  112. (start-db-conn! me repo {}))
  113. ([me repo option]
  114. (conn/start! me repo
  115. (assoc option
  116. :listen-handler listen-and-persist!))))
  117. (defn restore!
  118. [{:keys [repos] :as me} old-db-schema restore-config-handler]
  119. (let [logged? (:name me)]
  120. (doall
  121. (for [{:keys [url]} repos]
  122. (let [repo url]
  123. (p/let [db-name (datascript-db repo)
  124. db-conn (d/create-conn db-schema/schema)
  125. _ (d/transact! db-conn [{:schema/version db-schema/version}])
  126. _ (swap! conns assoc db-name db-conn)
  127. stored (idb/get-item db-name)
  128. _ (if stored
  129. (let [stored-db (string->db stored)
  130. attached-db (d/db-with stored-db (concat
  131. [(me-tx stored-db me)]
  132. default-db/built-in-pages))]
  133. (conn/reset-conn! db-conn attached-db))
  134. (when logged?
  135. (d/transact! db-conn [(me-tx (d/db db-conn) me)])))]
  136. (restore-config-handler repo)
  137. (listen-and-persist! repo)))))))
  138. (defn run-batch-txs!
  139. []
  140. (let [chan (state/get-db-batch-txs-chan)]
  141. (async/go-loop []
  142. (let [f (async/<! chan)]
  143. (f))
  144. (recur))
  145. chan))
  146. (defn new-block-id
  147. []
  148. (d/squuid))