Newer
Older

Bruno Burke
committed
(:require [document-storage.postgres.encoding :as encoding]
[editscript.core :as escript]
[clj-helper.vector :as vhelper])
(:import [java.util.concurrent ArrayBlockingQueue]))

Bruno Burke
committed
(defn get-document-frame-by-version [storage document-id version repository]
(.run-query storage :get-document-frame-by-version
{:repository repository
:version version
:document-id document-id}))
(defn get-document-frame-by-id [storage frame-id repository]
(.run-query storage :get-document-frame
{:repository repository
:id frame-id}))
(defn get-last-document-frame [storage document-id repository]

Bruno Burke
committed
;;;TODO check if this can be speed up by using index in db

Bruno Burke
committed
(when-let [frame (.run-query storage :get-last-document-frame
{:repository repository
:document-id document-id})]

Bruno Burke
committed
frame))
(defn get-last-document-version [storage document-id repository]

Bruno Burke
committed
(when-let [frame (get-last-document-frame storage document-id repository)]
{:version (:version frame)
:data-type (keyword (:data_type frame))}))

Bruno Burke
committed
(defn restore-document-version [storage document-id version repository]
(when-let [frames (.run-query storage :select-relevant-document-frames-by-version
{:repository repository
:document-id document-id
:version version})]
(let [next-frames (into {} (map (juxt :reference identity)) frames)
keyframe (vhelper/get-by frames (comp name :data_type) "key")]
(if keyframe
(loop [active-frame keyframe
data (encoding/decode-document (:data active-frame))]
(let [next-frame (get next-frames (:id active-frame))]
(if-not next-frame
data
(recur next-frame (escript/patch
data
(escript/edits->script (encoding/decode-document (:data next-frame))))))))
(throw
(ex-info (str "No keyframe for document " document-id " with version " version " in repository " repository)
{:document-id document-id
:version version
:repository repository}))))))

Bruno Burke
committed
(defn log-request [storage repository document-id version]
(.start (Thread. (fn []
(.run-query storage :log-request!
{:repository repository
:document-id document-id
:version version})
(.run-query storage :create-document-stats!
{:repository repository
:document-id document-id
:version version})))))
(defn load-document
([storage document-id repository]

Bruno Burke
committed
(when-let [last-document-version (get-last-document-version storage document-id repository)]
(when-not (= (name (:data-type last-document-version)) "delete")
(load-document storage document-id (:version last-document-version) repository))))
(let [restore-document-fn #(restore-document-version storage document-id version repository)]

Bruno Burke
committed
(log-request storage repository document-id version)
(if (.cached-repository? storage repository)
(cache/load-cached-document storage repository document-id version restore-document-fn)
(restore-document-fn)))))
(defn save-keyframe [storage document-id document last-version repository]
(let [doc (encoding/encode-document document)
last-version (or last-version 0)]
;;VALUES (:uuid, :document-id, :type, :encoding, :version, :reference, :data)
(.run-query storage :create-document-frame!
{:repository repository
:document-id document-id
:type "key"
:encoding "nippy"
:version (inc last-version)
(defn overwrite-keyframe [storage document-id document version repository]
(let [doc (encoding/encode-document document)
version (or version 0)]
;;VALUES (:uuid, :document-id, :type, :encoding, :version, :reference, :data)
(.run-query storage :overwrite-document-frame!
{:repository repository
:document-id document-id
:type "key"
:encoding "nippy"
:version version
:reference nil
:data doc})))

Bruno Burke
committed
(defn save-pframe [storage document-id doc last-version repository]
(let [last-doc (load-document storage document-id last-version repository)
last-frame (get-document-frame-by-version storage document-id last-version repository)
diff (escript/diff last-doc doc {:str-diff? false :algo :quick})

Bruno Burke
committed
diff-doc (encoding/encode-document (escript/get-edits diff))]
(.run-query storage :create-document-frame!
{:repository repository
:document-id document-id
:type "diff"
:encoding "nippy"

Bruno Burke
committed
:version (inc last-version)
:reference (:id last-frame) ;;;FIXME save ID in reference not version
:data diff-doc})))
(def get-repo-queue (memoize (fn [reponame]
(new ArrayBlockingQueue 1 true))))

Bruno Burke
committed
(defn save-document [storage document-id document repository options]
(let [queue (get-repo-queue repository)
job-id (gensym)]
(.put queue job-id)
(cache/update-query-cache-document storage repository document-id document)
(let [save-result (if-let [last-version (get-last-document-version storage document-id repository)]
(if (or (true? (:force-keyframe options))
(false? (.versioned-repository? storage repository))

Bruno Burke
committed
(= (keyword (name (:data-type last-version))) :delete))
(let [version-num (:version last-version)]
(if (.versioned-repository? storage repository)
(save-keyframe storage document-id document version-num repository)
(overwrite-keyframe storage document-id document version-num repository)))
(save-pframe storage document-id document (:version last-version) repository))
(save-keyframe storage document-id document -1 repository))]
(.take queue)
save-result)))

Bruno Burke
committed
(defn delete-document [storage document-id repository]

Bruno Burke
committed
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
(if (true? (.delete-permanently? storage repository))
(doseq [v (map :version (.list-versions storage document-id repository))]
(.run-query storage :overwrite-document-frame!
{:repository repository
:document-id document-id
:type "delete"
:encoding "edn"
:version v
:reference nil
:data (encoding/encode-document "")}))
(when-let [last-version-num (:version (get-last-document-version storage document-id repository))]
(if (.versioned-repository? storage repository)
(.run-query storage :create-document-frame!
{:repository repository
:document-id document-id
:type "delete"
:encoding "edn"
:version (inc last-version-num)
:reference nil
:data (encoding/encode-document "")})
(.run-query storage :overwrite-document-frame!
{:repository repository
:document-id document-id
:type "delete"
:encoding "edn"
:version last-version-num
:reference nil
:data (encoding/encode-document "")})))))