db.cljs 6.7 KB

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