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})]
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}))))))
(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)]
(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)

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))
(= (:data-type last-version) :delete))
(save-keyframe storage document-id document (:version last-version) 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
(.run-query storage :create-document-frame!
{:repository repository
:document-id document-id
:type "delete"
:encoding "edn"
:version (inc (:version (get-last-document-version storage document-id repository)))

Bruno Burke
committed
:reference nil
:data (encoding/encode-document "")}))