mirror of
https://github.com/penpot/penpot.git
synced 2025-01-08 07:50:43 -05:00
♻️ Refactor temporal files management on exporter
This commit is contained in:
parent
d021ac0226
commit
ebe8fdcba8
8 changed files with 57 additions and 40 deletions
|
@ -8,10 +8,10 @@
|
|||
(:require
|
||||
["process" :as proc]
|
||||
[app.browser :as bwr]
|
||||
[app.redis :as redis]
|
||||
[app.common.logging :as l]
|
||||
[app.config]
|
||||
[app.http :as http]
|
||||
[app.redis :as redis]
|
||||
[promesa.core :as p]))
|
||||
|
||||
(enable-console-print!)
|
||||
|
|
|
@ -128,8 +128,8 @@
|
|||
|
||||
(defn- join-pdf
|
||||
[file-id paths]
|
||||
(p/let [tmpdir (sh/mktmpdir! "join-pdf")
|
||||
path (path/join tmpdir (str/concat file-id ".pdf"))]
|
||||
(p/let [prefix (str/concat "penpot.tmp.pdfunite." file-id ".")
|
||||
path (sh/tempfile :prefix prefix :suffix ".pdf")]
|
||||
(sh/run-cmd! (str "pdfunite " (str/join " " paths) " " path))
|
||||
path))
|
||||
|
||||
|
@ -137,5 +137,4 @@
|
|||
[{:keys [path] :as resource} output-path]
|
||||
(p/do
|
||||
(sh/move! output-path path)
|
||||
(sh/rmdir! (path/dirname output-path))
|
||||
resource))
|
||||
|
|
|
@ -102,8 +102,6 @@
|
|||
total (count exports)
|
||||
topic (str profile-id)
|
||||
|
||||
to-delete (atom #{})
|
||||
|
||||
on-progress (fn [{:keys [done]}]
|
||||
(when-not wait
|
||||
(let [data {:type :export-update
|
||||
|
@ -137,7 +135,6 @@
|
|||
:on-progress on-progress)
|
||||
|
||||
append (fn [{:keys [filename path] :as object}]
|
||||
(swap! to-delete conj path)
|
||||
(rsc/add-to-zip! zip path filename))
|
||||
|
||||
proc (-> (p/do
|
||||
|
@ -146,7 +143,6 @@
|
|||
(p/let [proc (rd/render export append)]
|
||||
(p/recur (rest exports)))))
|
||||
(.finalize zip))
|
||||
(p/then (fn [_] (p/run! #(sh/rmdir! (path/dirname %)) @to-delete)))
|
||||
(p/then (constantly resource))
|
||||
(p/catch on-error))
|
||||
]
|
||||
|
|
|
@ -14,15 +14,15 @@
|
|||
[app.common.data :as d]
|
||||
[app.common.exceptions :as ex]
|
||||
[app.common.uuid :as uuid]
|
||||
[app.util.shell :as sh]
|
||||
[app.util.mime :as mime]
|
||||
[app.util.shell :as sh]
|
||||
[cljs.core :as c]
|
||||
[cuerdas.core :as str]
|
||||
[promesa.core :as p]))
|
||||
|
||||
(defn- get-path
|
||||
[type id]
|
||||
(path/join (os/tmpdir) (str/concat "exporter-resource." (c/name type) "." id)))
|
||||
(path/join sh/tmpdir (str/concat "penpot.resource." (c/name type) "." id)))
|
||||
|
||||
(defn create
|
||||
"Generates ephimeral resource object."
|
||||
|
|
|
@ -36,9 +36,8 @@
|
|||
:userAgent bw/default-user-agent})
|
||||
|
||||
(render-object [page {:keys [id] :as object}]
|
||||
(p/let [tmpdir (sh/mktmpdir! "bitmap-render")
|
||||
path (path/join tmpdir (str/concat id (mime/get-extension type)))
|
||||
node (bw/select page (str/concat "#screenshot-" id))]
|
||||
(p/let [path (sh/tempfile :prefix "penpot.tmp.render.bitmap." :suffix (mime/get-extension type))
|
||||
node (bw/select page (str/concat "#screenshot-" id))]
|
||||
(bw/wait-for node)
|
||||
(case type
|
||||
:png (bw/screenshot node {:omit-background? true :type type :path path})
|
||||
|
|
|
@ -44,8 +44,7 @@
|
|||
|
||||
(render-object [page base-uri {:keys [id] :as object}]
|
||||
(p/let [uri (prepare-uri base-uri id)
|
||||
tmp (sh/mktmpdir! "pdf-render")
|
||||
path (path/join tmp (str/concat id (mime/get-extension type)))]
|
||||
path (sh/tempfile :prefix "penpot.tmp.render.pdf." :suffix (mime/get-extension type))]
|
||||
(l/info :uri uri)
|
||||
(bw/nav! page uri)
|
||||
(p/let [dom (bw/select page (dm/str "#screenshot-" id))]
|
||||
|
|
|
@ -116,24 +116,20 @@
|
|||
(defn render
|
||||
[{:keys [page-id file-id objects token scale type]} on-object]
|
||||
(letfn [(convert-to-ppm [pngpath]
|
||||
(l/trace :fn :convert-to-ppm)
|
||||
(let [basepath (path/dirname pngpath)
|
||||
ppmpath (path/join basepath "origin.ppm")]
|
||||
(let [ppmpath (str/concat pngpath "origin.ppm")]
|
||||
(l/trace :fn :convert-to-ppm :path ppmpath)
|
||||
(-> (sh/run-cmd! (str "convert " pngpath " " ppmpath))
|
||||
(p/then (constantly ppmpath)))))
|
||||
|
||||
(trace-color-mask [pbmpath]
|
||||
(l/trace :fn :trace-color-mask :pbmpath pbmpath)
|
||||
(let [basepath (path/dirname pbmpath)
|
||||
basename (path/basename pbmpath ".pbm")
|
||||
svgpath (path/join basepath (str basename ".svg"))]
|
||||
(let [svgpath (str/concat pbmpath ".svg")]
|
||||
(-> (sh/run-cmd! (str "potrace --flat -b svg " pbmpath " -o " svgpath))
|
||||
(p/then (constantly svgpath)))))
|
||||
|
||||
(generate-color-layer [ppmpath color]
|
||||
(l/trace :fn :generate-color-layer :ppmpath ppmpath :color color)
|
||||
(let [basepath (path/dirname ppmpath)
|
||||
pbmpath (path/join basepath (str "mask-" (subs color 1) ".pbm"))]
|
||||
(let [pbmpath (str/concat ppmpath ".mask-" (subs color 1) ".pbm")]
|
||||
(-> (sh/run-cmd! (str/format "ppmcolormask \"%s\" %s" color ppmpath))
|
||||
(p/then (fn [stdout]
|
||||
(-> (sh/write-file! pbmpath stdout)
|
||||
|
@ -247,15 +243,14 @@
|
|||
|
||||
(trace-node [{:keys [data] :as node}]
|
||||
(l/trace :fn :trace-node)
|
||||
(p/let [tdpath (sh/mktmpdir! "svgexport")
|
||||
pngpath (path/join tdpath "origin.png")
|
||||
(p/let [pngpath (sh/tempfile :prefix "penpot.tmp.render.svg.parse."
|
||||
:suffix ".origin.png")
|
||||
_ (sh/write-file! pngpath data)
|
||||
ppmpath (convert-to-ppm pngpath)
|
||||
svgdata (convert-to-svg ppmpath node)]
|
||||
(-> node
|
||||
(dissoc :data)
|
||||
(assoc :tempdir tdpath
|
||||
:svgdata svgdata))))
|
||||
(assoc :svgdata svgdata))))
|
||||
|
||||
(extract-element-attrs [^js element]
|
||||
(let [^js attrs (.. element -attributes)
|
||||
|
@ -289,17 +284,11 @@
|
|||
shot (bw/screenshot text-node {:omit-background? true :type "png"})]
|
||||
[shot node]))
|
||||
|
||||
(clean-temp-data [{:keys [tempdir] :as node}]
|
||||
(p/do!
|
||||
(sh/rmdir! tempdir)
|
||||
(dissoc node :tempdir)))
|
||||
|
||||
(extract-txt-node [page item]
|
||||
(-> (p/resolved item)
|
||||
(p/then (partial resolve-text-node page))
|
||||
(p/then extract-single-node)
|
||||
(p/then trace-node)
|
||||
(p/then clean-temp-data)))
|
||||
(p/then trace-node)))
|
||||
|
||||
(extract-txt-nodes [page {:keys [id] :as objects}]
|
||||
(l/trace :fn :process-text-nodes)
|
||||
|
@ -323,9 +312,8 @@
|
|||
:userAgent bw/default-user-agent})
|
||||
|
||||
(render-object [page {:keys [id] :as object}]
|
||||
(p/let [tmpdir (sh/mktmpdir! "svg-render")
|
||||
path (path/join tmpdir (str/concat id (mime/get-extension type)))
|
||||
node (bw/select page (str/concat "#screenshot-" id))]
|
||||
(p/let [path (sh/tempfile :prefix "penpot.tmp.render.svg." :suffix (mime/get-extension type))
|
||||
node (bw/select page (str/concat "#screenshot-" id))]
|
||||
(bw/wait-for node)
|
||||
(p/let [xmldata (extract-svg page object)
|
||||
txtdata (extract-txt-nodes page object)
|
||||
|
|
|
@ -12,13 +12,49 @@
|
|||
["os" :as os]
|
||||
["path" :as path]
|
||||
[app.common.logging :as l]
|
||||
[app.common.uuid :as uuid]
|
||||
[app.common.exceptions :as ex]
|
||||
[cuerdas.core :as str]
|
||||
[promesa.core :as p]))
|
||||
|
||||
(l/set-level! :trace)
|
||||
|
||||
(defn mktmpdir!
|
||||
[prefix]
|
||||
(.mkdtemp fs/promises (path/join (os/tmpdir) prefix)))
|
||||
(def tempfile-minage (* 1000 60 60 1)) ;; 1h
|
||||
|
||||
(def tmpdir
|
||||
(let [path (path/join (os/tmpdir) "penpot")]
|
||||
(when-not (fs/existsSync path)
|
||||
(fs/mkdirSync path #js {:recursive true}))
|
||||
path))
|
||||
|
||||
|
||||
(defn- schedule-deletion!
|
||||
[path]
|
||||
(letfn [(remote-tempfile []
|
||||
(when (fs/existsSync path)
|
||||
(l/trace :hint "permanently remove tempfile" :path path)
|
||||
(fs/rmSync path #js {:recursive true})))]
|
||||
(let [ts (js/Date.now)]
|
||||
(l/trace :hint "schedule tempfile deletion"
|
||||
:path path
|
||||
:scheduled-at (.. (js/Date. (+ (js/Date.now) tempfile-minage)) toString))
|
||||
(js/setTimeout remote-tempfile tempfile-minage))))
|
||||
|
||||
(defn tempfile
|
||||
[& {:keys [prefix suffix]
|
||||
:or {prefix "penpot."
|
||||
suffix ".tmp"}}]
|
||||
(loop [i 0]
|
||||
(if (< i 1000)
|
||||
(let [path (path/join tmpdir (str/concat prefix (uuid/next) "-" i suffix))]
|
||||
(if (fs/existsSync path)
|
||||
(recur (inc i))
|
||||
(do
|
||||
(schedule-deletion! path)
|
||||
path)))
|
||||
(ex/raise :type :internal
|
||||
:code :unable-to-locate-temporal-file
|
||||
:hint "unable to find a tempfile candidate"))))
|
||||
|
||||
(defn move!
|
||||
[origin-path dest-path]
|
||||
|
|
Loading…
Reference in a new issue