Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

♻️ Refactor frontend persistence layer #4463

Merged
merged 1 commit into from
Jun 4, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
1 change: 1 addition & 0 deletions .clj-kondo/hooks/export.clj
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@

(def registry (atom {}))


(defn potok-reify
[{:keys [:node :filename] :as params}]
(let [[rnode rtype & other] (:children node)
Expand Down
8 changes: 5 additions & 3 deletions CHANGES.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,9 +9,11 @@
### :heart: Community contributions (Thank you!)

### :sparkles: New features
- Improve auth process [Taiga #Change Auth Process](https://tree.taiga.io/project/penpot/us/7094)
- Add locking degrees increment (hold shift) on path edition [Taiga #7761](https://tree.taiga.io/project/penpot/issue/7761)
- Allow library colors as recent colors [Taiga issue #7640](https://tree.taiga.io/project/penpot/issue/7640)

- Improve auth process [Taiga #7094](https://tree.taiga.io/project/penpot/us/7094)
- Add locking degrees increment (hold shift) on path edition [Taiga Issue #7761](https://tree.taiga.io/project/penpot/issue/7761)
- Persistence & Concurrent Edition Enhancements [Taiga #5657](https://tree.taiga.io/project/penpot/us/5657)
- Allow library colors as recent colors [Taiga Issue #7640](https://tree.taiga.io/project/penpot/issue/7640)

### :bug: Bugs fixed

Expand Down
4 changes: 2 additions & 2 deletions backend/src/app/rpc/commands/files_update.clj
Original file line number Diff line number Diff line change
Expand Up @@ -262,8 +262,8 @@
;; Send asynchronous notifications
(send-notifications! cfg params)

;; Retrieve and return lagged data
(get-lagged-changes conn params))))
{:revn (:revn file)
:lagged (get-lagged-changes conn params)})))

(defn- soft-validate-file-schema!
[file]
Expand Down
166 changes: 166 additions & 0 deletions frontend/src/app/main/data/changes.cljs
Original file line number Diff line number Diff line change
@@ -0,0 +1,166 @@
;; This Source Code Form is subject to the terms of the Mozilla Public
;; License, v. 2.0. If a copy of the MPL was not distributed with this
;; file, You can obtain one at http://mozilla.org/MPL/2.0/.
;;
;; Copyright (c) KALEIDOS INC

(ns app.main.data.changes
(:require
[app.common.data :as d]
[app.common.data.macros :as dm]
[app.common.files.changes :as cpc]
[app.common.logging :as log]
[app.common.types.shape-tree :as ctst]
[app.common.uuid :as uuid]
[app.main.features :as features]
[app.main.worker :as uw]
[app.util.time :as dt]
[beicon.v2.core :as rx]
[potok.v2.core :as ptk]))

;; Change this to :info :debug or :trace to debug this module
(log/set-level! :debug)

(def page-change?
#{:add-page :mod-page :del-page :mov-page})
(def update-layout-attr?
#{:hidden})

(def commit?
(ptk/type? ::commit))

(defn update-indexes
"Given a commit, send the changes to the worker for updating the
indexes."
[{:keys [changes] :as commit}]
(ptk/reify ::update-indexes
ptk/WatchEvent
(watch [_ _ _]
(let [changes (->> changes
(map (fn [{:keys [id type page] :as change}]
(cond-> change
(and (page-change? type) (nil? (:page-id change)))
(assoc :page-id (or id (:id page))))))
(filter :page-id)
(group-by :page-id))]

(->> (rx/from changes)
(rx/merge-map (fn [[page-id changes]]
(log/debug :hint "update-indexes" :page-id page-id :changes (count changes))
(uw/ask! {:cmd :update-page-index
:page-id page-id
:changes changes})))
(rx/ignore))))))

(defn- get-pending-commits
[{:keys [persistence]}]
(->> (:queue persistence)
(map (d/getf (:index persistence)))
(not-empty)))

(defn commit
"Create a commit event instance"
[{:keys [commit-id redo-changes undo-changes origin save-undo? features
file-id file-revn undo-group tags stack-undo? source]}]

(dm/assert!
"expect valid vector of changes"
(and (cpc/check-changes! redo-changes)
(cpc/check-changes! undo-changes)))

(let [commit-id (or commit-id (uuid/next))
commit {:id commit-id
:created-at (dt/now)
:source (d/nilv source :local)
:origin (ptk/type origin)
:features features
:file-id file-id
:file-revn file-revn
:changes redo-changes
:redo-changes redo-changes
:undo-changes undo-changes
:save-undo? save-undo?
:undo-group undo-group
:tags tags
:stack-undo? stack-undo?}]

(ptk/reify ::commit
cljs.core/IDeref
(-deref [_] commit)

ptk/UpdateEvent
(update [_ state]
(let [current-file-id (get state :current-file-id)
path (if (= file-id current-file-id)
[:workspace-data]
[:workspace-libraries file-id :data])

not-local? (not= source :local)
pending (if not-local?
(get-pending-commits state)
nil)

undo-changes (if pending
(->> pending
(map :undo-changes)
(reverse)
(mapcat identity)
(vec))
nil)

redo-changes (if pending
(into redo-changes
(comp
(map :redo-changes)
(mapcat identity))
pending)
redo-changes)]

(d/update-in-when state path
(fn [file]
(let [file (cpc/process-changes file undo-changes false)
file (cpc/process-changes file redo-changes false)
pids (into #{} (map :page-id) redo-changes)]
(reduce #(ctst/update-object-indices %1 %2) file pids)))))))))

(defn- resolve-file-revn
[state file-id]
(let [file (:workspace-file state)]
(if (= (:id file) file-id)
(:revn file)
(dm/get-in state [:workspace-libraries file-id :revn]))))

(defn commit-changes
"Schedules a list of changes to execute now, and add the corresponding undo changes to
the undo stack.

Options:
- save-undo?: if set to false, do not add undo changes.
- undo-group: if some consecutive changes (or even transactions) share the same
undo-group, they will be undone or redone in a single step
"
[{:keys [redo-changes undo-changes save-undo? undo-group tags stack-undo? file-id]
:or {save-undo? true
stack-undo? false
undo-group (uuid/next)
tags #{}}
:as params}]
(ptk/reify ::commit-changes
ptk/WatchEvent
(watch [_ state _]
(let [file-id (or file-id (:current-file-id state))
uchg (vec undo-changes)
rchg (vec redo-changes)
features (features/get-team-enabled-features state)]

(rx/of (-> params
(assoc :undo-group undo-group)
(assoc :features features)
(assoc :tags tags)
(assoc :stack-undo? stack-undo?)
(assoc :save-undo? save-undo?)
(assoc :file-id file-id)
(assoc :file-revn (resolve-file-revn state file-id))
(assoc :undo-changes uchg)
(assoc :redo-changes rchg)
(commit)))))))
2 changes: 1 addition & 1 deletion frontend/src/app/main/data/exports.cljs
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
(:require
[app.common.uuid :as uuid]
[app.main.data.modal :as modal]
[app.main.data.workspace.persistence :as dwp]
[app.main.data.persistence :as dwp]
[app.main.data.workspace.state-helpers :as wsh]
[app.main.refs :as refs]
[app.main.repo :as rp]
Expand Down