mirror of
https://github.com/penpot/penpot.git
synced 2026-09-16 17:06:17 +00:00
* ✨ Add export job model, store and scheduler to exporter * ✨ Render wasm exports on pooled worker threads * ✨ Add export job REST API to exporter * ✨ Use export job API and allow cancelling wasm exports * 🔧 Show export jobs in the internal debug panel * 🔧 Pass flags and export job settings to the exporter container * 📚 Document the exporter job API and its redis layout
111 lines
4.3 KiB
Clojure
111 lines
4.3 KiB
Clojure
;; 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 SUBSIDIARY SL
|
|
|
|
(ns app.handlers
|
|
(:require
|
|
[app.auth :as auth]
|
|
[app.common.data :as d]
|
|
[app.common.logging :as l]
|
|
[app.common.spec :as us]
|
|
[app.handlers.export :as export]
|
|
[app.util.transit :as t]
|
|
[clojure.spec.alpha :as s]
|
|
[promesa.core :as p]))
|
|
|
|
(l/set-level! :debug)
|
|
|
|
(def ^:private error-codes
|
|
#{:queue-full})
|
|
|
|
(defn on-error
|
|
[error exchange]
|
|
(let [{:keys [type code] :as data} (ex-data error)]
|
|
(cond
|
|
(and (= :validation type)
|
|
(contains? error-codes code))
|
|
(let [data {:type :validation
|
|
:code code
|
|
:hint (ex-message error)}]
|
|
(l/warn :hint "rejecting export request" :code code)
|
|
(-> exchange
|
|
(assoc :response/status 429)
|
|
(assoc :response/body (t/encode data))
|
|
(assoc :response/headers {"content-type" "application/transit+json"})))
|
|
|
|
(= :authentication type)
|
|
(let [data {:type :authentication
|
|
:code code
|
|
:hint (ex-message error)}]
|
|
(-> exchange
|
|
(assoc :response/status 401)
|
|
(assoc :response/body (t/encode data))
|
|
(assoc :response/headers {"content-type" "application/transit+json"})))
|
|
|
|
(or (= :validation type)
|
|
(= :assertion type))
|
|
(let [explain (us/pretty-explain data)
|
|
data (-> data
|
|
(assoc :explain explain)
|
|
(assoc :type :validation)
|
|
(dissoc ::s/problems ::s/value ::s/spec))]
|
|
(-> exchange
|
|
(assoc :response/status 400)
|
|
(assoc :response/body (t/encode data))
|
|
(assoc :response/headers {"content-type" "application/transit+json"})))
|
|
|
|
(= :not-found type)
|
|
(-> exchange
|
|
(assoc :response/status 404)
|
|
(assoc :response/body (t/encode data))
|
|
(assoc :response/headers {"content-type" "application/transit+json"}))
|
|
|
|
(and (= :internal type)
|
|
(= :browser-not-ready code))
|
|
(let [data {:type :server-error
|
|
:code :internal
|
|
:hint (ex-message error)
|
|
:data data}]
|
|
(-> exchange
|
|
(assoc :response/status 503)
|
|
(assoc :response/body (t/encode data))
|
|
(assoc :response/headers {"content-type" "application/transit+json"})))
|
|
|
|
:else
|
|
(let [data {:type :server-error
|
|
:code code
|
|
:hint (ex-message error)
|
|
:data data}]
|
|
(l/error :hint "unexpected internal error" :cause error)
|
|
(-> exchange
|
|
(assoc :response/status 500)
|
|
(assoc :response/body (t/encode (d/without-nils data)))
|
|
(assoc :response/headers {"content-type" "application/transit+json"}))))))
|
|
|
|
(defn handler
|
|
"The original `POST /api/export` entry point, and the one the browser backend
|
|
still goes through. The export runs as soon as it is asked for, and the
|
|
contract is unchanged: `:wait` answers with the finished resource, otherwise
|
|
with the resource handle while the work runs."
|
|
[{:keys [:request/params :request/auth-token] :as exchange}]
|
|
(let [{:keys [cmd wait] :as params} (export/conform-params params)]
|
|
(l/debug :hint "process-request" :cmd cmd)
|
|
(->> (auth/resolve-profile-id auth-token)
|
|
(p/mcat (fn [profile-id]
|
|
;; The session wins when there is one; the body value stays
|
|
;; the fallback so nothing that used to work stops working.
|
|
(export/export! auth-token (cond-> params
|
|
(some? profile-id)
|
|
(assoc :profile-id profile-id)))))
|
|
(p/mcat (fn [{:keys [resource pending]}]
|
|
(if wait
|
|
(p/fmap (fn [resource]
|
|
(assoc exchange :response/body resource))
|
|
pending)
|
|
(do
|
|
(p/merr (constantly nil) pending)
|
|
(p/resolved
|
|
(assoc exchange :response/body (dissoc resource :path))))))))))
|