mirror of
https://github.com/penpot/penpot.git
synced 2025-12-11 22:14:05 +01:00
♻️ Refactor time related namespaces
Mainly removes the custom app.util.time namespace from frontend and backend and normalize all to use the app.common.time namespace
This commit is contained in:
@@ -45,10 +45,16 @@
|
||||
:potok/reify-type
|
||||
{:level :error}
|
||||
|
||||
:missing-protocol-method
|
||||
{:level :off}
|
||||
|
||||
:unresolved-namespace
|
||||
{:level :warning
|
||||
:exclude [data_readers]}
|
||||
|
||||
:unused-value
|
||||
{:level :off}
|
||||
|
||||
:single-key-in
|
||||
{:level :warning}
|
||||
|
||||
@@ -64,6 +70,9 @@
|
||||
:redundant-nested-call
|
||||
{:level :off}
|
||||
|
||||
:redundant-str-call
|
||||
{:level :off}
|
||||
|
||||
:earmuffed-var-not-dynamic
|
||||
{:level :off}
|
||||
|
||||
|
||||
@@ -30,7 +30,7 @@
|
||||
[app.srepl.helpers :as srepl.helpers]
|
||||
[app.srepl.main :as srepl]
|
||||
[app.util.blob :as blob]
|
||||
[app.util.time :as dt]
|
||||
[app.common.time :as ct]
|
||||
[clj-async-profiler.core :as prof]
|
||||
[clojure.contrib.humanize :as hum]
|
||||
[clojure.java.io :as io]
|
||||
|
||||
@@ -13,6 +13,7 @@
|
||||
[app.common.exceptions :as ex]
|
||||
[app.common.logging :as l]
|
||||
[app.common.schema :as sm]
|
||||
[app.common.time :as ct]
|
||||
[app.common.uri :as u]
|
||||
[app.config :as cf]
|
||||
[app.db :as db]
|
||||
@@ -28,7 +29,6 @@
|
||||
[app.tokens :as tokens]
|
||||
[app.util.inet :as inet]
|
||||
[app.util.json :as json]
|
||||
[app.util.time :as dt]
|
||||
[buddy.sign.jwk :as jwk]
|
||||
[buddy.sign.jwt :as jwt]
|
||||
[clojure.set :as set]
|
||||
@@ -514,7 +514,7 @@
|
||||
[cfg info request]
|
||||
(let [info (assoc info
|
||||
:iss :prepared-register
|
||||
:exp (dt/in-future {:hours 48}))
|
||||
:exp (ct/in-future {:hours 48}))
|
||||
|
||||
params {:token (tokens/generate (::setup/props cfg) info)
|
||||
:provider (:provider (:path-params request))
|
||||
@@ -571,7 +571,7 @@
|
||||
token (or (:invitation-token info)
|
||||
(tokens/generate (::setup/props cfg)
|
||||
{:iss :auth
|
||||
:exp (dt/in-future "15m")
|
||||
:exp (ct/in-future "15m")
|
||||
:profile-id (:id profile)}))
|
||||
props (audit/profile->props profile)
|
||||
context (d/without-nils {:external-session-id (:external-session-id info)})]
|
||||
@@ -619,7 +619,7 @@
|
||||
:invitation-token (:invitation-token params)
|
||||
:external-session-id esid
|
||||
:props props
|
||||
:exp (dt/in-future "4h")}
|
||||
:exp (ct/in-future "4h")}
|
||||
state (tokens/generate (::setup/props cfg)
|
||||
(d/without-nils params))
|
||||
uri (build-auth-uri cfg state)]
|
||||
|
||||
@@ -16,6 +16,7 @@
|
||||
[app.common.files.validate :as fval]
|
||||
[app.common.logging :as l]
|
||||
[app.common.schema :as sm]
|
||||
[app.common.time :as ct]
|
||||
[app.common.types.file :as ctf]
|
||||
[app.common.uuid :as uuid]
|
||||
[app.config :as cf]
|
||||
@@ -28,7 +29,6 @@
|
||||
[app.storage :as sto]
|
||||
[app.util.blob :as blob]
|
||||
[app.util.pointer-map :as pmap]
|
||||
[app.util.time :as dt]
|
||||
[app.worker :as-alias wrk]
|
||||
[clojure.set :as set]
|
||||
[cuerdas.core :as str]
|
||||
@@ -540,14 +540,13 @@
|
||||
|
||||
Returns nil"
|
||||
[{:keys [::timestamp] :as cfg} file & {:as opts}]
|
||||
(assert (ct/inst? timestamp) "expected valid timestamp")
|
||||
|
||||
(assert (dt/instant? timestamp) "expected valid timestamp")
|
||||
(let [file (-> file
|
||||
(assoc :created-at timestamp)
|
||||
(assoc :modified-at timestamp)
|
||||
(cond-> (not (::overwrite cfg))
|
||||
(assoc :ignore-sync-until (dt/plus timestamp (dt/duration {:seconds 5}))))
|
||||
(update :revn inc)
|
||||
(assoc :ignore-sync-until (ct/plus timestamp (ct/duration {:seconds 5}))))
|
||||
(update :features
|
||||
(fn [features]
|
||||
(-> (::features cfg #{})
|
||||
|
||||
@@ -17,6 +17,7 @@
|
||||
[app.common.fressian :as fres]
|
||||
[app.common.logging :as l]
|
||||
[app.common.spec :as us]
|
||||
[app.common.time :as ct]
|
||||
[app.common.types.file :as ctf]
|
||||
[app.common.uuid :as uuid]
|
||||
[app.config :as cf]
|
||||
@@ -30,7 +31,6 @@
|
||||
[app.storage.tmp :as tmp]
|
||||
[app.tasks.file-gc]
|
||||
[app.util.events :as events]
|
||||
[app.util.time :as dt]
|
||||
[app.worker :as-alias wrk]
|
||||
[clojure.java.io :as jio]
|
||||
[clojure.set :as set]
|
||||
@@ -434,7 +434,7 @@
|
||||
(defn read-import!
|
||||
"Do the importation of the specified resource in penpot custom binary
|
||||
format."
|
||||
[{:keys [::bfc/input ::bfc/timestamp] :or {timestamp (dt/now)} :as options}]
|
||||
[{:keys [::bfc/input ::bfc/timestamp] :or {timestamp (ct/now)} :as options}]
|
||||
|
||||
(dm/assert!
|
||||
"expected input stream"
|
||||
@@ -442,7 +442,7 @@
|
||||
|
||||
(dm/assert!
|
||||
"expected valid instant"
|
||||
(dt/instant? timestamp))
|
||||
(ct/inst? timestamp))
|
||||
|
||||
(let [version (read-header! input)]
|
||||
(read-import (assoc options ::version version ::bfc/timestamp timestamp))))
|
||||
@@ -682,7 +682,7 @@
|
||||
(io/coercible? output))
|
||||
|
||||
(let [id (uuid/next)
|
||||
tp (dt/tpoint)
|
||||
tp (ct/tpoint)
|
||||
ab (volatile! false)
|
||||
cs (volatile! nil)]
|
||||
(try
|
||||
@@ -720,7 +720,7 @@
|
||||
(satisfies? jio/IOFactory input))
|
||||
|
||||
(let [id (uuid/next)
|
||||
tp (dt/tpoint)
|
||||
tp (ct/tpoint)
|
||||
cs (volatile! nil)]
|
||||
|
||||
(l/info :hint "import: started" :id (str id))
|
||||
@@ -742,6 +742,6 @@
|
||||
(finally
|
||||
(l/info :hint "import: terminated"
|
||||
:id (str id)
|
||||
:elapsed (dt/format-duration (tp))
|
||||
:elapsed (ct/format-duration (tp))
|
||||
:error? (some? @cs))))))
|
||||
|
||||
|
||||
@@ -13,6 +13,7 @@
|
||||
[app.common.data :as d]
|
||||
[app.common.features :as cfeat]
|
||||
[app.common.logging :as l]
|
||||
[app.common.time :as ct]
|
||||
[app.common.transit :as t]
|
||||
[app.common.uuid :as uuid]
|
||||
[app.config :as cf]
|
||||
@@ -23,7 +24,6 @@
|
||||
[app.storage :as sto]
|
||||
[app.storage.tmp :as tmp]
|
||||
[app.util.events :as events]
|
||||
[app.util.time :as dt]
|
||||
[app.worker :as-alias wrk]
|
||||
[clojure.set :as set]
|
||||
[cuerdas.core :as str]
|
||||
@@ -344,7 +344,7 @@
|
||||
(defn export-team!
|
||||
[cfg team-id]
|
||||
(let [id (uuid/next)
|
||||
tp (dt/tpoint)
|
||||
tp (ct/tpoint)
|
||||
cfg (create-database cfg)]
|
||||
|
||||
(l/inf :hint "start"
|
||||
@@ -378,15 +378,15 @@
|
||||
(l/inf :hint "end"
|
||||
:operation "export"
|
||||
:id (str id)
|
||||
:elapsed (dt/format-duration elapsed)))))))
|
||||
:elapsed (ct/format-duration elapsed)))))))
|
||||
|
||||
(defn import-team!
|
||||
[cfg path]
|
||||
(let [id (uuid/next)
|
||||
tp (dt/tpoint)
|
||||
tp (ct/tpoint)
|
||||
|
||||
cfg (-> (create-database cfg path)
|
||||
(assoc ::bfc/timestamp (dt/now)))]
|
||||
(assoc ::bfc/timestamp (ct/now)))]
|
||||
|
||||
(l/inf :hint "start"
|
||||
:operation "import"
|
||||
@@ -434,4 +434,4 @@
|
||||
(l/inf :hint "end"
|
||||
:operation "import"
|
||||
:id (str id)
|
||||
:elapsed (dt/format-duration elapsed)))))))
|
||||
:elapsed (ct/format-duration elapsed)))))))
|
||||
|
||||
@@ -20,6 +20,7 @@
|
||||
[app.common.media :as cmedia]
|
||||
[app.common.schema :as sm]
|
||||
[app.common.thumbnails :as cth]
|
||||
[app.common.time :as ct]
|
||||
[app.common.types.color :as ctcl]
|
||||
[app.common.types.component :as ctc]
|
||||
[app.common.types.file :as ctf]
|
||||
@@ -35,7 +36,6 @@
|
||||
[app.storage :as sto]
|
||||
[app.storage.impl :as sto.impl]
|
||||
[app.util.events :as events]
|
||||
[app.util.time :as dt]
|
||||
[clojure.java.io :as jio]
|
||||
[cuerdas.core :as str]
|
||||
[datoteka.fs :as fs]
|
||||
@@ -92,7 +92,7 @@
|
||||
|
||||
(defn- default-now
|
||||
[o]
|
||||
(or o (dt/now)))
|
||||
(or o (ct/now)))
|
||||
|
||||
;; --- ENCODERS
|
||||
|
||||
@@ -937,10 +937,10 @@
|
||||
[file-id])))
|
||||
|
||||
(defn- import-files
|
||||
[{:keys [::bfc/timestamp ::bfc/input] :or {timestamp (dt/now)} :as cfg}]
|
||||
[{:keys [::bfc/timestamp ::bfc/input] :or {timestamp (ct/now)} :as cfg}]
|
||||
|
||||
(assert (instance? ZipFile input) "expected zip file")
|
||||
(assert (dt/instant? timestamp) "expected valid instant")
|
||||
(assert (ct/inst? timestamp) "expected valid instant")
|
||||
|
||||
(let [manifest (-> (read-manifest input)
|
||||
(validate-manifest))
|
||||
@@ -1000,7 +1000,7 @@
|
||||
"expected instance of jio/IOFactory for `input`")
|
||||
|
||||
(let [id (uuid/next)
|
||||
tp (dt/tpoint)
|
||||
tp (ct/tpoint)
|
||||
ab (volatile! false)
|
||||
cs (volatile! nil)]
|
||||
(try
|
||||
@@ -1046,7 +1046,7 @@
|
||||
"expected instance of jio/IOFactory for `input`")
|
||||
|
||||
(let [id (uuid/next)
|
||||
tp (dt/tpoint)
|
||||
tp (ct/tpoint)
|
||||
cs (volatile! nil)]
|
||||
|
||||
(l/info :hint "import: started" :id (str id))
|
||||
@@ -1061,7 +1061,7 @@
|
||||
(finally
|
||||
(l/info :hint "import: terminated"
|
||||
:id (str id)
|
||||
:elapsed (dt/format-duration (tp))
|
||||
:elapsed (ct/format-duration (tp))
|
||||
:error? (some? @cs))))))
|
||||
|
||||
(defn get-manifest
|
||||
|
||||
@@ -12,10 +12,10 @@
|
||||
[app.common.exceptions :as ex]
|
||||
[app.common.flags :as flags]
|
||||
[app.common.schema :as sm]
|
||||
[app.common.time :as ct]
|
||||
[app.common.uri :as u]
|
||||
[app.common.version :as v]
|
||||
[app.util.overrides]
|
||||
[app.util.time :as dt]
|
||||
[clojure.core :as c]
|
||||
[clojure.java.io :as io]
|
||||
[cuerdas.core :as str]
|
||||
@@ -59,10 +59,10 @@
|
||||
:smtp-default-reply-to "Penpot <no-reply@example.com>"
|
||||
:smtp-default-from "Penpot <no-reply@example.com>"
|
||||
|
||||
:profile-complaint-max-age (dt/duration {:days 7})
|
||||
:profile-complaint-max-age (ct/duration {:days 7})
|
||||
:profile-complaint-threshold 2
|
||||
|
||||
:profile-bounce-max-age (dt/duration {:days 7})
|
||||
:profile-bounce-max-age (ct/duration {:days 7})
|
||||
:profile-bounce-threshold 10
|
||||
|
||||
:telemetry-uri "https://telemetry.penpot.app/"
|
||||
@@ -102,10 +102,10 @@
|
||||
[:telemetry-with-taiga {:optional true} ::sm/boolean] ;; DELETE
|
||||
|
||||
[:auto-file-snapshot-every {:optional true} ::sm/int]
|
||||
[:auto-file-snapshot-timeout {:optional true} ::dt/duration]
|
||||
[:auto-file-snapshot-timeout {:optional true} ::ct/duration]
|
||||
|
||||
[:media-max-file-size {:optional true} ::sm/int]
|
||||
[:deletion-delay {:optional true} ::dt/duration] ;; REVIEW
|
||||
[:deletion-delay {:optional true} ::ct/duration] ;; REVIEW
|
||||
[:telemetry-enabled {:optional true} ::sm/boolean]
|
||||
[:default-blob-version {:optional true} ::sm/int]
|
||||
[:allow-demo-users {:optional true} ::sm/boolean]
|
||||
@@ -148,10 +148,10 @@
|
||||
|
||||
[:auth-data-cookie-domain {:optional true} :string]
|
||||
[:auth-token-cookie-name {:optional true} :string]
|
||||
[:auth-token-cookie-max-age {:optional true} ::dt/duration]
|
||||
[:auth-token-cookie-max-age {:optional true} ::ct/duration]
|
||||
|
||||
[:registration-domain-whitelist {:optional true} [::sm/set :string]]
|
||||
[:email-verify-threshold {:optional true} ::dt/duration]
|
||||
[:email-verify-threshold {:optional true} ::ct/duration]
|
||||
|
||||
[:github-client-id {:optional true} :string]
|
||||
[:github-client-secret {:optional true} :string]
|
||||
@@ -186,9 +186,9 @@
|
||||
[:ldap-starttls {:optional true} ::sm/boolean]
|
||||
[:ldap-user-query {:optional true} :string]
|
||||
|
||||
[:profile-bounce-max-age {:optional true} ::dt/duration]
|
||||
[:profile-bounce-max-age {:optional true} ::ct/duration]
|
||||
[:profile-bounce-threshold {:optional true} ::sm/int]
|
||||
[:profile-complaint-max-age {:optional true} ::dt/duration]
|
||||
[:profile-complaint-max-age {:optional true} ::ct/duration]
|
||||
[:profile-complaint-threshold {:optional true} ::sm/int]
|
||||
|
||||
[:redis-uri {:optional true} ::sm/uri]
|
||||
@@ -298,7 +298,7 @@
|
||||
(defn get-deletion-delay
|
||||
[]
|
||||
(or (c/get config :deletion-delay)
|
||||
(dt/duration {:days 7})))
|
||||
(ct/duration {:days 7})))
|
||||
|
||||
(defn get
|
||||
"A configuration getter. Helps code be more testable."
|
||||
|
||||
@@ -13,11 +13,11 @@
|
||||
[app.common.json :as json]
|
||||
[app.common.logging :as l]
|
||||
[app.common.schema :as sm]
|
||||
[app.common.time :as ct]
|
||||
[app.common.transit :as t]
|
||||
[app.common.uuid :as uuid]
|
||||
[app.db.sql :as sql]
|
||||
[app.metrics :as mtx]
|
||||
[app.util.time :as dt]
|
||||
[clojure.java.io :as io]
|
||||
[clojure.set :as set]
|
||||
[integrant.core :as ig]
|
||||
@@ -379,9 +379,9 @@
|
||||
|
||||
(defn is-row-deleted?
|
||||
[{:keys [deleted-at]}]
|
||||
(and (dt/instant? deleted-at)
|
||||
(and (ct/inst? deleted-at)
|
||||
(< (inst-ms deleted-at)
|
||||
(inst-ms (dt/now)))))
|
||||
(inst-ms (ct/now)))))
|
||||
|
||||
(defn get*
|
||||
"Retrieve a single row from database that matches a simple filters. Do
|
||||
@@ -605,7 +605,7 @@
|
||||
(string? o)
|
||||
(pginterval o)
|
||||
|
||||
(dt/duration? o)
|
||||
(ct/duration? o)
|
||||
(interval (inst-ms o))
|
||||
|
||||
:else
|
||||
|
||||
@@ -7,8 +7,8 @@
|
||||
(ns app.features.logical-deletion
|
||||
"A code related to handle logical deletion mechanism"
|
||||
(:require
|
||||
[app.config :as cf]
|
||||
[app.util.time :as dt]))
|
||||
[app.common.time :as ct]
|
||||
[app.config :as cf]))
|
||||
|
||||
(def ^:private canceled-status
|
||||
#{"canceled" "unpaid"})
|
||||
@@ -20,10 +20,10 @@
|
||||
(if-let [{:keys [type status]} (get team :subscription)]
|
||||
(cond
|
||||
(and (= "unlimited" type) (not (contains? canceled-status status)))
|
||||
(dt/duration {:days 30})
|
||||
(ct/duration {:days 30})
|
||||
|
||||
(and (= "enterprise" type) (not (contains? canceled-status status)))
|
||||
(dt/duration {:days 90})
|
||||
(ct/duration {:days 90})
|
||||
|
||||
:else
|
||||
(cf/get-deletion-delay))
|
||||
|
||||
@@ -9,18 +9,18 @@
|
||||
(:require
|
||||
[app.common.data :as d]
|
||||
[app.common.exceptions :as ex]
|
||||
[app.common.time :as ct]
|
||||
[app.common.uri :as u]
|
||||
[app.db :as db]
|
||||
[app.storage :as sto]
|
||||
[app.util.time :as dt]
|
||||
[integrant.core :as ig]
|
||||
[yetti.response :as-alias yres]))
|
||||
|
||||
(def ^:private cache-max-age
|
||||
(dt/duration {:hours 24}))
|
||||
(ct/duration {:hours 24}))
|
||||
|
||||
(def ^:private signature-max-age
|
||||
(dt/duration {:hours 24 :minutes 15}))
|
||||
(ct/duration {:hours 24 :minutes 15}))
|
||||
|
||||
(defn get-id
|
||||
[{:keys [path-params]}]
|
||||
|
||||
@@ -15,6 +15,7 @@
|
||||
[app.common.features :as cfeat]
|
||||
[app.common.logging :as l]
|
||||
[app.common.pprint :as pp]
|
||||
[app.common.time :as ct]
|
||||
[app.common.transit :as t]
|
||||
[app.common.uuid :as uuid]
|
||||
[app.config :as cf]
|
||||
@@ -31,7 +32,6 @@
|
||||
[app.storage.tmp :as tmp]
|
||||
[app.util.blob :as blob]
|
||||
[app.util.template :as tmpl]
|
||||
[app.util.time :as dt]
|
||||
[cuerdas.core :as str]
|
||||
[datoteka.io :as io]
|
||||
[emoji.core :as emj]
|
||||
@@ -137,7 +137,7 @@
|
||||
file (some-> params :file :path io/read* t/decode)]
|
||||
|
||||
(if (and file project-id)
|
||||
(let [fname (str "Imported: " (:name file) "(" (dt/now) ")")
|
||||
(let [fname (str "Imported: " (:name file) "(" (ct/now) ")")
|
||||
reuse-id? (contains? params :reuseid)
|
||||
file-id (or (and reuse-id? (ex/ignoring (-> params :file :filename parse-uuid)))
|
||||
(uuid/next))]
|
||||
@@ -222,7 +222,7 @@
|
||||
(-> (io/resource "app/templates/error-report.v3.tmpl")
|
||||
(tmpl/render (-> content
|
||||
(assoc :id id)
|
||||
(assoc :created-at (dt/format-instant created-at :rfc1123))))))]
|
||||
(assoc :created-at (ct/format-inst created-at :rfc1123))))))]
|
||||
|
||||
(if-let [report (get-report request)]
|
||||
(let [result (case (:version report)
|
||||
@@ -246,7 +246,7 @@
|
||||
(defn error-list-handler
|
||||
[{:keys [::db/pool]} _request]
|
||||
(let [items (->> (db/exec! pool [sql:error-reports])
|
||||
(map #(update % :created-at dt/format-instant :rfc1123)))]
|
||||
(map #(update % :created-at ct/format-inst :rfc1123)))]
|
||||
{::yres/status 200
|
||||
::yres/body (-> (io/resource "app/templates/error-list.tmpl")
|
||||
(tmpl/render {:items items}))
|
||||
|
||||
@@ -10,6 +10,7 @@
|
||||
[app.common.data :as d]
|
||||
[app.common.logging :as l]
|
||||
[app.common.schema :as sm]
|
||||
[app.common.time :as ct]
|
||||
[app.common.uri :as u]
|
||||
[app.config :as cf]
|
||||
[app.db :as db]
|
||||
@@ -18,7 +19,6 @@
|
||||
[app.main :as-alias main]
|
||||
[app.setup :as-alias setup]
|
||||
[app.tokens :as tokens]
|
||||
[app.util.time :as dt]
|
||||
[cuerdas.core :as str]
|
||||
[integrant.core :as ig]
|
||||
[yetti.request :as yreq]))
|
||||
@@ -35,10 +35,10 @@
|
||||
(def default-auth-data-cookie-name "auth-data")
|
||||
|
||||
;; Default value for cookie max-age
|
||||
(def default-cookie-max-age (dt/duration {:days 7}))
|
||||
(def default-cookie-max-age (ct/duration {:days 7}))
|
||||
|
||||
;; Default age for automatic session renewal
|
||||
(def default-renewal-max-age (dt/duration {:hours 6}))
|
||||
(def default-renewal-max-age (ct/duration {:hours 6}))
|
||||
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
;; PROTOCOLS
|
||||
@@ -66,7 +66,7 @@
|
||||
[:map {:title "session-params"}
|
||||
[:user-agent ::sm/text]
|
||||
[:profile-id ::sm/uuid]
|
||||
[:created-at ::sm/inst]])
|
||||
[:created-at ::ct/inst]])
|
||||
|
||||
(def ^:private valid-params?
|
||||
(sm/validator schema:params))
|
||||
@@ -95,7 +95,7 @@
|
||||
params))
|
||||
|
||||
(update! [_ params]
|
||||
(let [updated-at (dt/now)]
|
||||
(let [updated-at (ct/now)]
|
||||
(db/update! pool :http-session
|
||||
{:updated-at updated-at}
|
||||
{:id (:id params)})
|
||||
@@ -118,7 +118,7 @@
|
||||
params))
|
||||
|
||||
(update! [_ params]
|
||||
(let [updated-at (dt/now)]
|
||||
(let [updated-at (ct/now)]
|
||||
(swap! cache update (:id params) assoc :updated-at updated-at)
|
||||
(assoc params :updated-at updated-at)))
|
||||
|
||||
@@ -158,7 +158,7 @@
|
||||
(let [uagent (yreq/get-header request "user-agent")
|
||||
params {:profile-id profile-id
|
||||
:user-agent uagent
|
||||
:created-at (dt/now)}
|
||||
:created-at (ct/now)}
|
||||
token (gen-token props params)
|
||||
session (write! manager token params)]
|
||||
(l/trace :hint "create" :profile-id (str profile-id))
|
||||
@@ -203,8 +203,8 @@
|
||||
|
||||
(defn- renew-session?
|
||||
[{:keys [updated-at] :as session}]
|
||||
(and (dt/instant? updated-at)
|
||||
(let [elapsed (dt/diff updated-at (dt/now))]
|
||||
(and (ct/inst? updated-at)
|
||||
(let [elapsed (ct/diff updated-at (ct/now))]
|
||||
(neg? (compare default-renewal-max-age elapsed)))))
|
||||
|
||||
(defn- wrap-soft-auth
|
||||
@@ -256,14 +256,14 @@
|
||||
(defn- assign-auth-token-cookie
|
||||
[response {token :id updated-at :updated-at}]
|
||||
(let [max-age (cf/get :auth-token-cookie-max-age default-cookie-max-age)
|
||||
created-at (or updated-at (dt/now))
|
||||
renewal (dt/plus created-at default-renewal-max-age)
|
||||
expires (dt/plus created-at max-age)
|
||||
created-at (or updated-at (ct/now))
|
||||
renewal (ct/plus created-at default-renewal-max-age)
|
||||
expires (ct/plus created-at max-age)
|
||||
secure? (contains? cf/flags :secure-session-cookies)
|
||||
strict? (contains? cf/flags :strict-session-cookies)
|
||||
cors? (contains? cf/flags :cors)
|
||||
name (cf/get :auth-token-cookie-name default-auth-token-cookie-name)
|
||||
comment (str "Renewal at: " (dt/format-instant renewal :rfc1123))
|
||||
comment (str "Renewal at: " (ct/format-inst renewal :rfc1123))
|
||||
cookie {:path "/"
|
||||
:http-only true
|
||||
:expires expires
|
||||
@@ -279,11 +279,11 @@
|
||||
domain (cf/get :auth-data-cookie-domain)
|
||||
cname default-auth-data-cookie-name
|
||||
|
||||
created-at (or updated-at (dt/now))
|
||||
renewal (dt/plus created-at default-renewal-max-age)
|
||||
expires (dt/plus created-at max-age)
|
||||
created-at (or updated-at (ct/now))
|
||||
renewal (ct/plus created-at default-renewal-max-age)
|
||||
expires (ct/plus created-at max-age)
|
||||
|
||||
comment (str "Renewal at: " (dt/format-instant renewal :rfc1123))
|
||||
comment (str "Renewal at: " (ct/format-inst renewal :rfc1123))
|
||||
secure? (contains? cf/flags :secure-session-cookies)
|
||||
strict? (contains? cf/flags :strict-session-cookies)
|
||||
cors? (contains? cf/flags :cors)
|
||||
@@ -323,7 +323,7 @@
|
||||
(defmethod ig/assert-key ::tasks/gc
|
||||
[_ params]
|
||||
(assert (db/pool? (::db/pool params)) "expected valid database pool")
|
||||
(assert (dt/duration? (::tasks/max-age params))))
|
||||
(assert (ct/duration? (::tasks/max-age params))))
|
||||
|
||||
(defmethod ig/expand-key ::tasks/gc
|
||||
[k v]
|
||||
|
||||
@@ -11,12 +11,12 @@
|
||||
[app.common.logging :as l]
|
||||
[app.common.pprint :as pp]
|
||||
[app.common.schema :as sm]
|
||||
[app.common.time :as ct]
|
||||
[app.common.uuid :as uuid]
|
||||
[app.db :as db]
|
||||
[app.http.session :as session]
|
||||
[app.metrics :as mtx]
|
||||
[app.msgbus :as mbus]
|
||||
[app.util.time :as dt]
|
||||
[app.util.websocket :as ws]
|
||||
[integrant.core :as ig]
|
||||
[promesa.exec.csp :as sp]
|
||||
@@ -239,7 +239,7 @@
|
||||
|
||||
(defn- on-connect
|
||||
[{:keys [::mtx/metrics]} {:keys [::ws/id] :as wsp}]
|
||||
(let [created-at (dt/now)]
|
||||
(let [created-at (ct/now)]
|
||||
(l/trace :fn "on-connect" :conn-id id)
|
||||
(swap! state assoc id wsp)
|
||||
(mtx/run! metrics
|
||||
@@ -253,7 +253,7 @@
|
||||
(mtx/run! metrics :id :websocket-active-connections :dec 1)
|
||||
(mtx/run! metrics
|
||||
:id :websocket-session-timing
|
||||
:val (/ (inst-ms (dt/diff created-at (dt/now))) 1000.0))))))
|
||||
:val (/ (inst-ms (ct/diff created-at (ct/now))) 1000.0))))))
|
||||
|
||||
(defn- on-rcv-message
|
||||
[{:keys [::mtx/metrics ::profile-id ::session-id]} message]
|
||||
|
||||
@@ -11,6 +11,7 @@
|
||||
[app.common.data.macros :as dm]
|
||||
[app.common.logging :as l]
|
||||
[app.common.schema :as sm]
|
||||
[app.common.time :as ct]
|
||||
[app.common.uuid :as uuid]
|
||||
[app.config :as cf]
|
||||
[app.db :as db]
|
||||
@@ -23,7 +24,6 @@
|
||||
[app.setup :as-alias setup]
|
||||
[app.util.inet :as inet]
|
||||
[app.util.services :as-alias sv]
|
||||
[app.util.time :as dt]
|
||||
[app.worker :as wrk]
|
||||
[cuerdas.core :as str]))
|
||||
|
||||
@@ -108,9 +108,9 @@
|
||||
[::ip-addr {:optional true} ::sm/text]
|
||||
[::props {:optional true} [:map-of :keyword :any]]
|
||||
[::context {:optional true} [:map-of :keyword :any]]
|
||||
[::tracked-at {:optional true} ::sm/inst]
|
||||
[::tracked-at {:optional true} ::ct/inst]
|
||||
[::webhooks/event? {:optional true} ::sm/boolean]
|
||||
[::webhooks/batch-timeout {:optional true} ::dt/duration]
|
||||
[::webhooks/batch-timeout {:optional true} ::ct/duration]
|
||||
[::webhooks/batch-key {:optional true}
|
||||
[:or ::sm/fn ::sm/text :keyword]]])
|
||||
|
||||
@@ -199,7 +199,7 @@
|
||||
(defn- handle-event!
|
||||
[cfg event]
|
||||
(let [params (event->params event)
|
||||
tnow (dt/now)]
|
||||
tnow (ct/now)]
|
||||
|
||||
(when (contains? cf/flags :audit-log)
|
||||
;; NOTE: this operation may cause primary key conflicts on inserts
|
||||
@@ -273,7 +273,7 @@
|
||||
(let [event (-> (d/without-nils event)
|
||||
(check-event))]
|
||||
(db/run! cfg (fn [cfg]
|
||||
(let [tnow (dt/now)
|
||||
(let [tnow (ct/now)
|
||||
params (-> (event->params event)
|
||||
(assoc :created-at tnow)
|
||||
(update :tracked-at #(or % tnow)))]
|
||||
|
||||
@@ -9,6 +9,7 @@
|
||||
[app.common.exceptions :as ex]
|
||||
[app.common.logging :as l]
|
||||
[app.common.schema :as sm]
|
||||
[app.common.time :as ct]
|
||||
[app.common.transit :as t]
|
||||
[app.common.uuid :as uuid]
|
||||
[app.config :as cf]
|
||||
@@ -16,7 +17,6 @@
|
||||
[app.http.client :as http]
|
||||
[app.setup :as-alias setup]
|
||||
[app.tokens :as tokens]
|
||||
[app.util.time :as dt]
|
||||
[integrant.core :as ig]
|
||||
[lambdaisland.uri :as u]
|
||||
[promesa.exec :as px]))
|
||||
@@ -55,7 +55,7 @@
|
||||
[{:keys [::uri] :as cfg} events]
|
||||
(let [token (tokens/generate (::setup/props cfg)
|
||||
{:iss "authentication"
|
||||
:iat (dt/now)
|
||||
:iat (ct/now)
|
||||
:uid uuid/zero})
|
||||
body (t/encode {:events events})
|
||||
headers {"content-type" "application/transit+json"
|
||||
|
||||
@@ -10,13 +10,13 @@
|
||||
[app.common.data :as d]
|
||||
[app.common.data.macros :as dm]
|
||||
[app.common.logging :as l]
|
||||
[app.common.time :as ct]
|
||||
[app.common.transit :as t]
|
||||
[app.common.uri :as uri]
|
||||
[app.config :as cf]
|
||||
[app.db :as db]
|
||||
[app.http.client :as http]
|
||||
[app.loggers.audit :as audit]
|
||||
[app.util.time :as dt]
|
||||
[app.worker :as wrk]
|
||||
[clojure.data.json :as json]
|
||||
[cuerdas.core :as str]
|
||||
@@ -124,7 +124,7 @@
|
||||
{:id (:id whook)})))
|
||||
|
||||
(db/update! pool :webhook
|
||||
{:updated-at (dt/now)
|
||||
{:updated-at (ct/now)
|
||||
:error-code nil
|
||||
:error-count 0}
|
||||
{:id (:id whook)})))
|
||||
@@ -132,7 +132,7 @@
|
||||
(report-delivery! [whook req rsp err]
|
||||
(db/insert! pool :webhook-delivery
|
||||
{:webhook-id (:id whook)
|
||||
:created-at (dt/now)
|
||||
:created-at (ct/now)
|
||||
:error-code err
|
||||
:req-data (db/tjson req)
|
||||
:rsp-data (db/tjson rsp)}))]
|
||||
@@ -155,7 +155,7 @@
|
||||
(let [req {:uri (:uri whook)
|
||||
:headers {"content-type" (:mtype whook)
|
||||
"user-agent" (str/ffmt "penpot/%" (:main cf/version))}
|
||||
:timeout (dt/duration "4s")
|
||||
:timeout (ct/duration "4s")
|
||||
:method :post
|
||||
:body body}]
|
||||
(try
|
||||
|
||||
@@ -11,6 +11,7 @@
|
||||
[app.auth.oidc.providers :as-alias oidc.providers]
|
||||
[app.common.exceptions :as ex]
|
||||
[app.common.logging :as l]
|
||||
[app.common.time :as ct]
|
||||
[app.config :as cf]
|
||||
[app.db :as-alias db]
|
||||
[app.email :as-alias email]
|
||||
@@ -38,7 +39,7 @@
|
||||
[app.storage.gc-touched :as-alias sto.gc-touched]
|
||||
[app.storage.s3 :as-alias sto.s3]
|
||||
[app.svgo :as-alias svgo]
|
||||
[app.util.time :as dt]
|
||||
[app.util.cron]
|
||||
[app.worker :as-alias wrk]
|
||||
[clojure.test :as test]
|
||||
[clojure.tools.namespace.repl :as repl]
|
||||
@@ -298,8 +299,8 @@
|
||||
|
||||
:app.http.assets/routes
|
||||
{::http.assets/path (cf/get :assets-path)
|
||||
::http.assets/cache-max-age (dt/duration {:hours 24})
|
||||
::http.assets/cache-max-agesignature-max-age (dt/duration {:hours 24 :minutes 5})
|
||||
::http.assets/cache-max-age (ct/duration {:hours 24})
|
||||
::http.assets/cache-max-agesignature-max-age (ct/duration {:hours 24 :minutes 5})
|
||||
::sto/storage (ig/ref ::sto/storage)}
|
||||
|
||||
::rpc/climit
|
||||
@@ -480,33 +481,33 @@
|
||||
{::wrk/registry (ig/ref ::wrk/registry)
|
||||
::db/pool (ig/ref ::db/pool)
|
||||
::wrk/entries
|
||||
[{:cron #app/cron "0 0 0 * * ?" ;; daily
|
||||
[{:cron #penpot/cron "0 0 0 * * ?" ;; daily
|
||||
:task :session-gc}
|
||||
|
||||
{:cron #app/cron "0 0 0 * * ?" ;; daily
|
||||
{:cron #penpot/cron "0 0 0 * * ?" ;; daily
|
||||
:task :objects-gc}
|
||||
|
||||
{:cron #app/cron "0 0 0 * * ?" ;; daily
|
||||
{:cron #penpot/cron "0 0 0 * * ?" ;; daily
|
||||
:task :storage-gc-deleted}
|
||||
|
||||
{:cron #app/cron "0 0 0 * * ?" ;; daily
|
||||
{:cron #penpot/cron "0 0 0 * * ?" ;; daily
|
||||
:task :storage-gc-touched}
|
||||
|
||||
{:cron #app/cron "0 0 0 * * ?" ;; daily
|
||||
{:cron #penpot/cron "0 0 0 * * ?" ;; daily
|
||||
:task :tasks-gc}
|
||||
|
||||
{:cron #app/cron "0 0 2 * * ?" ;; daily
|
||||
{:cron #penpot/cron "0 0 2 * * ?" ;; daily
|
||||
:task :file-gc-scheduler}
|
||||
|
||||
{:cron #app/cron "0 30 */3,23 * * ?"
|
||||
{:cron #penpot/cron "0 30 */3,23 * * ?"
|
||||
:task :telemetry}
|
||||
|
||||
(when (contains? cf/flags :audit-log-archive)
|
||||
{:cron #app/cron "0 */5 * * * ?" ;; every 5m
|
||||
{:cron #penpot/cron "0 */5 * * * ?" ;; every 5m
|
||||
:task :audit-log-archive})
|
||||
|
||||
(when (contains? cf/flags :audit-log-gc)
|
||||
{:cron #app/cron "30 */5 * * * ?" ;; every 5m
|
||||
{:cron #penpot/cron "30 */5 * * * ?" ;; every 5m
|
||||
:task :audit-log-gc})]}
|
||||
|
||||
::wrk/dispatcher
|
||||
|
||||
@@ -14,11 +14,11 @@
|
||||
[app.common.media :as cm]
|
||||
[app.common.schema :as sm]
|
||||
[app.common.schema.openapi :as-alias oapi]
|
||||
[app.common.time :as ct]
|
||||
[app.config :as cf]
|
||||
[app.db :as-alias db]
|
||||
[app.storage :as-alias sto]
|
||||
[app.storage.tmp :as tmp]
|
||||
[app.util.time :as dt]
|
||||
[buddy.core.bytes :as bb]
|
||||
[buddy.core.codecs :as bc]
|
||||
[clojure.java.shell :as sh]
|
||||
@@ -243,7 +243,7 @@
|
||||
(ex/raise :type :validation
|
||||
:code :invalid-svg-file
|
||||
:hint "uploaded svg does not provides dimensions"))
|
||||
(merge input info {:ts (dt/now)}))
|
||||
(merge input info {:ts (ct/now)}))
|
||||
|
||||
(let [instance (Info. (str path))
|
||||
mtype' (.getProperty instance "Mime type")]
|
||||
@@ -263,7 +263,7 @@
|
||||
(assoc input
|
||||
:width width
|
||||
:height height
|
||||
:ts (dt/now)))))))
|
||||
:ts (ct/now)))))))
|
||||
|
||||
(defmethod process-error org.im4java.core.InfoException
|
||||
[error]
|
||||
|
||||
@@ -10,10 +10,10 @@
|
||||
[app.common.data :as d]
|
||||
[app.common.logging :as l]
|
||||
[app.common.schema :as sm]
|
||||
[app.common.time :as ct]
|
||||
[app.common.transit :as t]
|
||||
[app.config :as cfg]
|
||||
[app.redis :as rds]
|
||||
[app.util.time :as dt]
|
||||
[app.worker :as wrk]
|
||||
[integrant.core :as ig]
|
||||
[promesa.core :as p]
|
||||
@@ -56,7 +56,7 @@
|
||||
[k v]
|
||||
{k (-> (d/without-nils v)
|
||||
(assoc ::buffer-size 128)
|
||||
(assoc ::timeout (dt/duration {:seconds 30})))})
|
||||
(assoc ::timeout (ct/duration {:seconds 30})))})
|
||||
|
||||
(def ^:private schema:params
|
||||
[:map ::rds/redis ::wrk/executor])
|
||||
|
||||
@@ -12,10 +12,10 @@
|
||||
[app.common.exceptions :as ex]
|
||||
[app.common.logging :as l]
|
||||
[app.common.schema :as sm]
|
||||
[app.common.time :as ct]
|
||||
[app.metrics :as mtx]
|
||||
[app.redis.script :as-alias rscript]
|
||||
[app.util.cache :as cache]
|
||||
[app.util.time :as dt]
|
||||
[app.worker :as-alias wrk]
|
||||
[clojure.core :as c]
|
||||
[clojure.java.io :as io]
|
||||
@@ -114,7 +114,7 @@
|
||||
(let [cpus (px/get-available-processors)
|
||||
threads (max 1 (int (* cpus 0.2)))]
|
||||
{k (-> (d/without-nils v)
|
||||
(assoc ::timeout (dt/duration "10s"))
|
||||
(assoc ::timeout (ct/duration "10s"))
|
||||
(assoc ::io-threads (max 3 threads))
|
||||
(assoc ::worker-threads (max 3 threads)))}))
|
||||
|
||||
@@ -125,7 +125,7 @@
|
||||
[::uri ::sm/uri]
|
||||
[::worker-threads ::sm/int]
|
||||
[::io-threads ::sm/int]
|
||||
[::timeout ::dt/duration]])
|
||||
[::timeout ::ct/duration]])
|
||||
|
||||
(defmethod ig/assert-key ::redis
|
||||
[_ params]
|
||||
@@ -331,7 +331,7 @@
|
||||
(p/rejected cause))))
|
||||
|
||||
(eval-script [sha]
|
||||
(let [tpoint (dt/tpoint)]
|
||||
(let [tpoint (ct/tpoint)]
|
||||
(->> (.evalsha ^RedisScriptingAsyncCommands cmd
|
||||
^String sha
|
||||
^ScriptOutputType ScriptOutputType/MULTI
|
||||
@@ -346,7 +346,7 @@
|
||||
:name (name sname)
|
||||
:sha sha
|
||||
:params (str/join "," (::rscript/vals script))
|
||||
:elapsed (dt/format-duration elapsed))
|
||||
:elapsed (ct/format-duration elapsed))
|
||||
result)))
|
||||
(p/merr on-error))))
|
||||
|
||||
|
||||
@@ -12,6 +12,7 @@
|
||||
[app.common.logging :as l]
|
||||
[app.common.schema :as sm]
|
||||
[app.common.spec :as us]
|
||||
[app.common.time :as ct]
|
||||
[app.config :as cf]
|
||||
[app.db :as db]
|
||||
[app.http :as-alias http]
|
||||
@@ -31,7 +32,6 @@
|
||||
[app.storage :as-alias sto]
|
||||
[app.util.inet :as inet]
|
||||
[app.util.services :as sv]
|
||||
[app.util.time :as dt]
|
||||
[clojure.spec.alpha :as s]
|
||||
[cuerdas.core :as str]
|
||||
[integrant.core :as ig]
|
||||
@@ -103,7 +103,7 @@
|
||||
data (-> params
|
||||
(assoc ::handler-name handler-name)
|
||||
(assoc ::ip-addr ip-addr)
|
||||
(assoc ::request-at (dt/now))
|
||||
(assoc ::request-at (ct/now))
|
||||
(assoc ::external-session-id session-id)
|
||||
(assoc ::external-event-origin event-origin)
|
||||
(assoc ::session/id (::session/id request))
|
||||
@@ -130,7 +130,7 @@
|
||||
[{:keys [::mtx/metrics ::metrics-id]} f mdata]
|
||||
(let [labels (into-array String [(::sv/name mdata)])]
|
||||
(fn [cfg params]
|
||||
(let [tp (dt/tpoint)]
|
||||
(let [tp (ct/tpoint)]
|
||||
(try
|
||||
(f cfg params)
|
||||
(finally
|
||||
|
||||
@@ -11,11 +11,11 @@
|
||||
[app.common.exceptions :as ex]
|
||||
[app.common.logging :as l]
|
||||
[app.common.schema :as sm]
|
||||
[app.common.time :as ct]
|
||||
[app.metrics :as mtx]
|
||||
[app.rpc :as-alias rpc]
|
||||
[app.util.cache :as cache]
|
||||
[app.util.services :as-alias sv]
|
||||
[app.util.time :as dt]
|
||||
[app.worker :as-alias wrk]
|
||||
[clojure.edn :as edn]
|
||||
[clojure.set :as set]
|
||||
@@ -154,7 +154,7 @@
|
||||
:id limit-id
|
||||
:label limit-label
|
||||
:queue queue
|
||||
:elapsed (some-> elapsed dt/format-duration)
|
||||
:elapsed (some-> elapsed ct/format-duration)
|
||||
:params @limit-params)))
|
||||
|
||||
(def ^:private idseq (AtomicLong. 0))
|
||||
@@ -171,7 +171,7 @@
|
||||
mlabels (into-array String [(id->str limit-id)])
|
||||
limit-id (id->str limit-id limit-key)
|
||||
limiter (cache/get cache limit-id (partial create-limiter config))
|
||||
tpoint (dt/tpoint)
|
||||
tpoint (ct/tpoint)
|
||||
req-id (.incrementAndGet ^AtomicLong idseq)]
|
||||
(try
|
||||
(let [stats (pbh/get-stats limiter)]
|
||||
|
||||
@@ -7,6 +7,7 @@
|
||||
(ns app.rpc.commands.access-token
|
||||
(:require
|
||||
[app.common.schema :as sm]
|
||||
[app.common.time :as ct]
|
||||
[app.common.uuid :as uuid]
|
||||
[app.db :as db]
|
||||
[app.main :as-alias main]
|
||||
@@ -15,8 +16,7 @@
|
||||
[app.rpc.quotes :as quotes]
|
||||
[app.setup :as-alias setup]
|
||||
[app.tokens :as tokens]
|
||||
[app.util.services :as sv]
|
||||
[app.util.time :as dt]))
|
||||
[app.util.services :as sv]))
|
||||
|
||||
(defn- decode-row
|
||||
[row]
|
||||
@@ -24,13 +24,13 @@
|
||||
|
||||
(defn create-access-token
|
||||
[{:keys [::db/conn ::setup/props]} profile-id name expiration]
|
||||
(let [created-at (dt/now)
|
||||
(let [created-at (ct/now)
|
||||
token-id (uuid/next)
|
||||
token (tokens/generate props {:iss "access-token"
|
||||
:tid token-id
|
||||
:iat created-at})
|
||||
|
||||
expires-at (some-> expiration dt/in-future)
|
||||
expires-at (some-> expiration ct/in-future)
|
||||
token (db/insert! conn :access-token
|
||||
{:id token-id
|
||||
:name name
|
||||
@@ -49,7 +49,7 @@
|
||||
(def ^:private schema:create-access-token
|
||||
[:map {:title "create-access-token"}
|
||||
[:name [:string {:max 250 :min 1}]]
|
||||
[:expiration {:optional true} ::dt/duration]])
|
||||
[:expiration {:optional true} ::ct/duration]])
|
||||
|
||||
(sv/defmethod ::create-access-token
|
||||
{::doc/added "1.18"
|
||||
|
||||
@@ -10,6 +10,7 @@
|
||||
[app.common.data :as d]
|
||||
[app.common.logging :as l]
|
||||
[app.common.schema :as sm]
|
||||
[app.common.time :as ct]
|
||||
[app.common.uuid :as uuid]
|
||||
[app.config :as cf]
|
||||
[app.db :as db]
|
||||
@@ -20,8 +21,7 @@
|
||||
[app.rpc.doc :as-alias doc]
|
||||
[app.rpc.helpers :as rph]
|
||||
[app.util.inet :as inet]
|
||||
[app.util.services :as sv]
|
||||
[app.util.time :as dt]))
|
||||
[app.util.services :as sv]))
|
||||
|
||||
(def ^:private event-columns
|
||||
[:id
|
||||
@@ -49,7 +49,7 @@
|
||||
|
||||
(defn- adjust-timestamp
|
||||
[{:keys [timestamp created-at] :as event}]
|
||||
(let [margin (inst-ms (dt/diff timestamp created-at))]
|
||||
(let [margin (inst-ms (ct/diff timestamp created-at))]
|
||||
(if (or (neg? margin)
|
||||
(> margin 3600000))
|
||||
;; If event is in future or lags more than 1 hour, we reasign
|
||||
@@ -63,7 +63,7 @@
|
||||
[{:keys [::db/pool]} {:keys [::rpc/profile-id events] :as params}]
|
||||
(let [request (-> params meta ::http/request)
|
||||
ip-addr (inet/parse-request request)
|
||||
tnow (dt/now)
|
||||
tnow (ct/now)
|
||||
xform (comp
|
||||
(map (fn [event]
|
||||
(-> event
|
||||
|
||||
@@ -12,6 +12,7 @@
|
||||
[app.common.features :as cfeat]
|
||||
[app.common.logging :as l]
|
||||
[app.common.schema :as sm]
|
||||
[app.common.time :as ct]
|
||||
[app.common.uuid :as uuid]
|
||||
[app.config :as cf]
|
||||
[app.db :as db]
|
||||
@@ -30,7 +31,6 @@
|
||||
[app.setup.welcome-file :refer [create-welcome-file]]
|
||||
[app.tokens :as tokens]
|
||||
[app.util.services :as sv]
|
||||
[app.util.time :as dt]
|
||||
[app.worker :as wrk]
|
||||
[cuerdas.core :as str]))
|
||||
|
||||
@@ -42,7 +42,7 @@
|
||||
|
||||
(defn- elapsed-verify-threshold?
|
||||
[profile]
|
||||
(let [elapsed (dt/diff (:modified-at profile) (dt/now))
|
||||
(let [elapsed (ct/diff (:modified-at profile) (ct/now))
|
||||
verify-threshold (cf/get :email-verify-threshold)]
|
||||
(pos? (compare elapsed verify-threshold))))
|
||||
|
||||
@@ -85,7 +85,7 @@
|
||||
(ex/raise :type :validation
|
||||
:code :wrong-credentials))
|
||||
(when-let [deleted-at (:deleted-at profile)]
|
||||
(when (dt/is-after? (dt/now) deleted-at)
|
||||
(when (ct/is-after? (ct/now) deleted-at)
|
||||
(ex/raise :type :validation
|
||||
:code :wrong-credentials)))
|
||||
|
||||
@@ -244,7 +244,7 @@
|
||||
:backend "penpot"
|
||||
:iss :prepared-register
|
||||
:profile-id (:id profile)
|
||||
:exp (dt/in-future {:days 7})
|
||||
:exp (ct/in-future {:days 7})
|
||||
:props {:newsletter-updates (or accept-newsletter-updates false)}}
|
||||
|
||||
params (d/without-nils params)
|
||||
@@ -344,7 +344,7 @@
|
||||
[{:keys [::db/conn] :as cfg} profile]
|
||||
(let [vtoken (tokens/generate (::setup/props cfg)
|
||||
{:iss :verify-email
|
||||
:exp (dt/in-future "72h")
|
||||
:exp (ct/in-future "72h")
|
||||
:profile-id (:id profile)
|
||||
:email (:email profile)})
|
||||
;; NOTE: this token is mainly used for possible complains
|
||||
@@ -352,7 +352,7 @@
|
||||
ptoken (tokens/generate (::setup/props cfg)
|
||||
{:iss :profile-identity
|
||||
:profile-id (:id profile)
|
||||
:exp (dt/in-future {:days 30})})]
|
||||
:exp (ct/in-future {:days 30})})]
|
||||
(eml/send! {::eml/conn conn
|
||||
::eml/factory eml/register
|
||||
:public-uri (cf/get :public-uri)
|
||||
@@ -466,7 +466,7 @@
|
||||
|
||||
(when (= action "resend-email-verification")
|
||||
(db/update! conn :profile
|
||||
{:modified-at (dt/now)}
|
||||
{:modified-at (ct/now)}
|
||||
{:id (:id profile)})
|
||||
(send-email-verification! cfg profile))
|
||||
|
||||
@@ -495,7 +495,7 @@
|
||||
(letfn [(create-recovery-token [{:keys [id] :as profile}]
|
||||
(let [token (tokens/generate (::setup/props cfg)
|
||||
{:iss :password-recovery
|
||||
:exp (dt/in-future "15m")
|
||||
:exp (ct/in-future "15m")
|
||||
:profile-id id})]
|
||||
(assoc profile :token token)))
|
||||
|
||||
@@ -503,7 +503,7 @@
|
||||
(let [ptoken (tokens/generate (::setup/props cfg)
|
||||
{:iss :profile-identity
|
||||
:profile-id (:id profile)
|
||||
:exp (dt/in-future {:days 30})})]
|
||||
:exp (ct/in-future {:days 30})})]
|
||||
(eml/send! {::eml/conn conn
|
||||
::eml/factory eml/password-recovery
|
||||
:public-uri (cf/get :public-uri)
|
||||
@@ -544,7 +544,7 @@
|
||||
:else
|
||||
(do
|
||||
(db/update! conn :profile
|
||||
{:modified-at (dt/now)}
|
||||
{:modified-at (ct/now)}
|
||||
{:id (:id profile)})
|
||||
(->> profile
|
||||
(create-recovery-token)
|
||||
|
||||
@@ -13,6 +13,7 @@
|
||||
[app.common.features :as cfeat]
|
||||
[app.common.logging :as l]
|
||||
[app.common.schema :as sm]
|
||||
[app.common.time :as ct]
|
||||
[app.config :as cf]
|
||||
[app.db :as db]
|
||||
[app.http.sse :as sse]
|
||||
@@ -26,7 +27,6 @@
|
||||
[app.rpc.doc :as-alias doc]
|
||||
[app.tasks.file-gc]
|
||||
[app.util.services :as sv]
|
||||
[app.util.time :as dt]
|
||||
[app.worker :as-alias wrk]
|
||||
[promesa.exec :as px]
|
||||
[yetti.response :as yres]))
|
||||
@@ -114,7 +114,7 @@
|
||||
3 (px/invoke! executor (partial bf.v3/import-files! cfg)))]
|
||||
|
||||
(db/update! pool :project
|
||||
{:modified-at (dt/now)}
|
||||
{:modified-at (ct/now)}
|
||||
{:id project-id}
|
||||
{::db/return-keys false})
|
||||
|
||||
|
||||
@@ -11,6 +11,7 @@
|
||||
[app.common.exceptions :as ex]
|
||||
[app.common.geom.point :as gpt]
|
||||
[app.common.schema :as sm]
|
||||
[app.common.time :as ct]
|
||||
[app.common.uri :as uri]
|
||||
[app.common.uuid :as uuid]
|
||||
[app.config :as cf]
|
||||
@@ -29,7 +30,6 @@
|
||||
[app.rpc.retry :as rtry]
|
||||
[app.util.pointer-map :as pmap]
|
||||
[app.util.services :as sv]
|
||||
[app.util.time :as dt]
|
||||
[clojure.set :as set]
|
||||
[cuerdas.core :as str]))
|
||||
|
||||
@@ -222,7 +222,7 @@
|
||||
|
||||
(defn upsert-comment-thread-status!
|
||||
([conn profile-id thread-id]
|
||||
(upsert-comment-thread-status! conn profile-id thread-id (dt/in-future "1s")))
|
||||
(upsert-comment-thread-status! conn profile-id thread-id (ct/in-future "1s")))
|
||||
([conn profile-id thread-id mod-at]
|
||||
(db/exec-one! conn [sql:upsert-comment-thread-status thread-id profile-id mod-at mod-at])))
|
||||
|
||||
|
||||
@@ -8,6 +8,7 @@
|
||||
"A demo specific mutations."
|
||||
(:require
|
||||
[app.common.exceptions :as ex]
|
||||
[app.common.time :as ct]
|
||||
[app.config :as cf]
|
||||
[app.db :as db]
|
||||
[app.loggers.audit :as audit]
|
||||
@@ -16,7 +17,6 @@
|
||||
[app.rpc.commands.profile :as profile]
|
||||
[app.rpc.doc :as-alias doc]
|
||||
[app.util.services :as sv]
|
||||
[app.util.time :as dt]
|
||||
[buddy.core.codecs :as bc]
|
||||
[buddy.core.nonce :as bn]))
|
||||
|
||||
@@ -45,15 +45,13 @@
|
||||
params {:email email
|
||||
:fullname fullname
|
||||
:is-active true
|
||||
:deleted-at (dt/in-future (cf/get-deletion-delay))
|
||||
:deleted-at (ct/in-future (cf/get-deletion-delay))
|
||||
:password (profile/derive-password cfg password)
|
||||
:props {}}]
|
||||
|
||||
|
||||
(let [profile (db/tx-run! cfg (fn [{:keys [::db/conn]}]
|
||||
(->> (auth/create-profile! conn params)
|
||||
(auth/create-profile-rels! conn))))]
|
||||
(with-meta {:email email
|
||||
:password password}
|
||||
{::audit/profile-id (:id profile)}))))
|
||||
:props {}}
|
||||
profile (db/tx-run! cfg (fn [{:keys [::db/conn]}]
|
||||
(->> (auth/create-profile! conn params)
|
||||
(auth/create-profile-rels! conn))))]
|
||||
(with-meta {:email email
|
||||
:password password}
|
||||
{::audit/profile-id (:id profile)})))
|
||||
|
||||
|
||||
@@ -16,6 +16,7 @@
|
||||
[app.common.logging :as l]
|
||||
[app.common.schema :as sm]
|
||||
[app.common.schema.desc-js-like :as-alias smdj]
|
||||
[app.common.time :as ct]
|
||||
[app.common.types.components-list :as ctkl]
|
||||
[app.common.types.file :as ctf]
|
||||
[app.common.uri :as uri]
|
||||
@@ -37,7 +38,6 @@
|
||||
[app.util.blob :as blob]
|
||||
[app.util.pointer-map :as pmap]
|
||||
[app.util.services :as sv]
|
||||
[app.util.time :as dt]
|
||||
[app.worker :as wrk]
|
||||
[cuerdas.core :as str]
|
||||
[promesa.exec :as px]))
|
||||
@@ -52,7 +52,7 @@
|
||||
;; --- HELPERS
|
||||
|
||||
(def long-cache-duration
|
||||
(dt/duration {:days 7}))
|
||||
(ct/duration {:days 7}))
|
||||
|
||||
(defn decode-row
|
||||
[{:keys [data changes features] :as row}]
|
||||
@@ -187,10 +187,10 @@
|
||||
[:name [:string {:max 250}]]
|
||||
[:revn [::sm/int {:min 0}]]
|
||||
[:vern [::sm/int {:min 0}]]
|
||||
[:modified-at ::dt/instant]
|
||||
[:modified-at ::ct/inst]
|
||||
[:is-shared ::sm/boolean]
|
||||
[:project-id ::sm/uuid]
|
||||
[:created-at ::dt/instant]
|
||||
[:created-at ::ct/inst]
|
||||
[:data {:optional true} ::sm/any]])
|
||||
|
||||
(def schema:permissions-mixin
|
||||
@@ -304,7 +304,7 @@
|
||||
(defn get-file-etag
|
||||
[{:keys [::rpc/profile-id]} {:keys [modified-at revn vern permissions]}]
|
||||
(str profile-id "/" revn "/" vern "/" (hash fmg/available-migrations) "/"
|
||||
(dt/format-instant modified-at :iso)
|
||||
(ct/format-inst modified-at :iso)
|
||||
"/"
|
||||
(uri/map->query-string permissions)))
|
||||
|
||||
@@ -356,7 +356,7 @@
|
||||
[:map {:title "FileFragment"}
|
||||
[:id ::sm/uuid]
|
||||
[:file-id ::sm/uuid]
|
||||
[:created-at ::dt/instant]
|
||||
[:created-at ::ct/inst]
|
||||
[:content any?]])
|
||||
|
||||
(def schema:get-file-fragment
|
||||
@@ -770,7 +770,7 @@
|
||||
[conn {:keys [id name]}]
|
||||
(db/update! conn :file
|
||||
{:name name
|
||||
:modified-at (dt/now)}
|
||||
:modified-at (ct/now)}
|
||||
{:id id}
|
||||
{::db/return-keys true}))
|
||||
|
||||
@@ -783,8 +783,8 @@
|
||||
[:id ::sm/uuid]
|
||||
[:project-id ::sm/uuid]
|
||||
[:name [:string {:max 250}]]
|
||||
[:created-at ::dt/instant]
|
||||
[:modified-at ::dt/instant]]
|
||||
[:created-at ::ct/inst]
|
||||
[:modified-at ::ct/inst]]
|
||||
|
||||
::sm/params
|
||||
[:map {:title "RenameFileParams"}
|
||||
@@ -795,8 +795,8 @@
|
||||
[:map {:title "SimplifiedFile"}
|
||||
[:id ::sm/uuid]
|
||||
[:name [:string {:max 250}]]
|
||||
[:created-at ::dt/instant]
|
||||
[:modified-at ::dt/instant]]
|
||||
[:created-at ::ct/inst]
|
||||
[:modified-at ::ct/inst]]
|
||||
|
||||
::db/transaction true}
|
||||
[{:keys [::db/conn] :as cfg} {:keys [::rpc/profile-id id] :as params}]
|
||||
@@ -839,7 +839,7 @@
|
||||
(db/update! cfg :file
|
||||
{:revn (inc (:revn file))
|
||||
:data (blob/encode (:data file))
|
||||
:modified-at (dt/now)
|
||||
:modified-at (ct/now)
|
||||
:has-media-trimmed false}
|
||||
{:id file-id})
|
||||
|
||||
@@ -900,7 +900,7 @@
|
||||
(db/delete! conn :file-library-rel {:library-file-id id})
|
||||
(db/update! conn :file
|
||||
{:is-shared false
|
||||
:modified-at (dt/now)}
|
||||
:modified-at (ct/now)}
|
||||
{:id id})
|
||||
(select-keys file [:id :name :is-shared]))
|
||||
|
||||
@@ -909,7 +909,7 @@
|
||||
(let [file (assoc file :is-shared true)]
|
||||
(db/update! conn :file
|
||||
{:is-shared true
|
||||
:modified-at (dt/now)}
|
||||
:modified-at (ct/now)}
|
||||
{:id id})
|
||||
file)
|
||||
|
||||
@@ -945,7 +945,7 @@
|
||||
[conn team file-id]
|
||||
(let [delay (ldel/get-deletion-delay team)
|
||||
file (db/update! conn :file
|
||||
{:deleted-at (dt/in-future delay)}
|
||||
{:deleted-at (ct/in-future delay)}
|
||||
{:id file-id}
|
||||
{::db/return-keys [:id :name :is-shared :deleted-at
|
||||
:project-id :created-at :modified-at]})]
|
||||
@@ -1043,7 +1043,7 @@
|
||||
(defn update-sync
|
||||
[conn {:keys [file-id library-id] :as params}]
|
||||
(db/update! conn :file-library-rel
|
||||
{:synced-at (dt/now)}
|
||||
{:synced-at (ct/now)}
|
||||
{:file-id file-id
|
||||
:library-file-id library-id}
|
||||
{::db/return-keys true}))
|
||||
@@ -1068,14 +1068,14 @@
|
||||
[conn {:keys [file-id date] :as params}]
|
||||
(db/update! conn :file
|
||||
{:ignore-sync-until date
|
||||
:modified-at (dt/now)}
|
||||
:modified-at (ct/now)}
|
||||
{:id file-id}
|
||||
{::db/return-keys true}))
|
||||
|
||||
(def ^:private schema:ignore-file-library-sync-status
|
||||
[:map {:title "ignore-file-library-sync-status"}
|
||||
[:file-id ::sm/uuid]
|
||||
[:date ::dt/instant]])
|
||||
[:date ::ct/inst]])
|
||||
|
||||
;; TODO: improve naming
|
||||
(sv/defmethod ::ignore-file-library-sync-status
|
||||
|
||||
@@ -9,6 +9,7 @@
|
||||
[app.binfile.common :as bfc]
|
||||
[app.common.features :as cfeat]
|
||||
[app.common.schema :as sm]
|
||||
[app.common.time :as ct]
|
||||
[app.common.types.file :as ctf]
|
||||
[app.config :as cf]
|
||||
[app.db :as db]
|
||||
@@ -22,7 +23,6 @@
|
||||
[app.rpc.quotes :as quotes]
|
||||
[app.util.pointer-map :as pmap]
|
||||
[app.util.services :as sv]
|
||||
[app.util.time :as dt]
|
||||
[clojure.set :as set]))
|
||||
|
||||
(defn create-file-role!
|
||||
@@ -63,7 +63,7 @@
|
||||
(create-file-role! conn))
|
||||
|
||||
(db/update! conn :project
|
||||
{:modified-at (dt/now)}
|
||||
{:modified-at (ct/now)}
|
||||
{:id project-id})
|
||||
|
||||
file)))
|
||||
|
||||
@@ -11,6 +11,7 @@
|
||||
[app.common.files.migrations :as fmg]
|
||||
[app.common.logging :as l]
|
||||
[app.common.schema :as sm]
|
||||
[app.common.time :as ct]
|
||||
[app.common.uuid :as uuid]
|
||||
[app.config :as cf]
|
||||
[app.db :as db]
|
||||
@@ -26,7 +27,6 @@
|
||||
[app.storage :as sto]
|
||||
[app.util.blob :as blob]
|
||||
[app.util.services :as sv]
|
||||
[app.util.time :as dt]
|
||||
[cuerdas.core :as str]))
|
||||
|
||||
(defn decode-row
|
||||
@@ -69,8 +69,8 @@
|
||||
|
||||
(defn- generate-snapshot-label
|
||||
[]
|
||||
(let [ts (-> (dt/now)
|
||||
(dt/format-instant)
|
||||
(let [ts (-> (ct/now)
|
||||
(ct/format-inst)
|
||||
(str/replace #"[T:\.]" "-")
|
||||
(str/rtrim "Z"))]
|
||||
(str "snapshot-" ts)))
|
||||
@@ -89,9 +89,9 @@
|
||||
deleted-at
|
||||
(cond
|
||||
(= deleted-at :default)
|
||||
(dt/plus (dt/now) (cf/get-deletion-delay))
|
||||
(ct/plus (ct/now) (cf/get-deletion-delay))
|
||||
|
||||
(dt/instant? deleted-at)
|
||||
(ct/inst? deleted-at)
|
||||
deleted-at
|
||||
|
||||
:else
|
||||
@@ -304,7 +304,7 @@
|
||||
(defn- delete-file-snapshot!
|
||||
[conn snapshot-id]
|
||||
(db/update! conn :file-change
|
||||
{:deleted-at (dt/now)}
|
||||
{:deleted-at (ct/now)}
|
||||
{:id snapshot-id}
|
||||
{::db/return-keys false})
|
||||
nil)
|
||||
|
||||
@@ -10,6 +10,7 @@
|
||||
[app.common.features :as cfeat]
|
||||
[app.common.files.changes :as cpc]
|
||||
[app.common.schema :as sm]
|
||||
[app.common.time :as ct]
|
||||
[app.common.uuid :as uuid]
|
||||
[app.config :as cf]
|
||||
[app.db :as db]
|
||||
@@ -27,7 +28,6 @@
|
||||
[app.util.blob :as blob]
|
||||
[app.util.pointer-map :as pmap]
|
||||
[app.util.services :as sv]
|
||||
[app.util.time :as dt]
|
||||
[clojure.set :as set]))
|
||||
|
||||
;; --- MUTATION COMMAND: create-temp-file
|
||||
@@ -72,7 +72,7 @@
|
||||
params
|
||||
(-> params
|
||||
(assoc :profile-id profile-id)
|
||||
(assoc :deleted-at (dt/in-future {:days 1}))
|
||||
(assoc :deleted-at (ct/in-future {:days 1}))
|
||||
(assoc :features features))]
|
||||
|
||||
(files.create/create-file cfg params)))
|
||||
@@ -97,7 +97,7 @@
|
||||
{:id (uuid/next)
|
||||
:session-id session-id
|
||||
:profile-id profile-id
|
||||
:created-at (dt/now)
|
||||
:created-at (ct/now)
|
||||
:file-id id
|
||||
:revn revn
|
||||
:data nil
|
||||
|
||||
@@ -13,6 +13,7 @@
|
||||
[app.common.geom.shapes :as gsh]
|
||||
[app.common.schema :as sm]
|
||||
[app.common.thumbnails :as thc]
|
||||
[app.common.time :as ct]
|
||||
[app.common.types.shape-tree :as ctt]
|
||||
[app.config :as cf]
|
||||
[app.db :as db]
|
||||
@@ -30,13 +31,12 @@
|
||||
[app.storage :as sto]
|
||||
[app.util.pointer-map :as pmap]
|
||||
[app.util.services :as sv]
|
||||
[app.util.time :as dt]
|
||||
[cuerdas.core :as str]))
|
||||
|
||||
;; --- FEATURES
|
||||
|
||||
(def long-cache-duration
|
||||
(dt/duration {:days 7}))
|
||||
(ct/duration {:days 7}))
|
||||
|
||||
;; --- COMMAND QUERY: get-file-object-thumbnails
|
||||
|
||||
@@ -247,7 +247,7 @@
|
||||
(defn- create-file-object-thumbnail!
|
||||
[{:keys [::sto/storage] :as cfg} file object-id media tag]
|
||||
(let [file-id (:id file)
|
||||
timestamp (dt/now)
|
||||
timestamp (ct/now)
|
||||
media (persist-thumbnail! storage media timestamp)
|
||||
[th1 th2] (db/tx-run! cfg (fn [{:keys [::db/conn]}]
|
||||
(let [th1 (db/exec-one! conn [sql:get-file-object-thumbnail file-id object-id tag])
|
||||
@@ -302,7 +302,7 @@
|
||||
{::sql/for-update true})]
|
||||
(sto/touch-object! storage media-id)
|
||||
(db/update! conn :file-tagged-object-thumbnail
|
||||
{:deleted-at (dt/now)}
|
||||
{:deleted-at (ct/now)}
|
||||
{:file-id file-id
|
||||
:object-id object-id
|
||||
:tag tag})))
|
||||
@@ -338,7 +338,7 @@
|
||||
hash (sto/calculate-hash path)
|
||||
data (-> (sto/content path)
|
||||
(sto/wrap-with-hash hash))
|
||||
tnow (dt/now)
|
||||
tnow (ct/now)
|
||||
media (sto/put-object! storage
|
||||
{::sto/content data
|
||||
::sto/deduplicate? true
|
||||
|
||||
@@ -15,6 +15,7 @@
|
||||
[app.common.files.validate :as val]
|
||||
[app.common.logging :as l]
|
||||
[app.common.schema :as sm]
|
||||
[app.common.time :as ct]
|
||||
[app.common.uuid :as uuid]
|
||||
[app.config :as cf]
|
||||
[app.db :as db]
|
||||
@@ -36,7 +37,6 @@
|
||||
[app.util.blob :as blob]
|
||||
[app.util.pointer-map :as pmap]
|
||||
[app.util.services :as sv]
|
||||
[app.util.time :as dt]
|
||||
[app.worker :as wrk]
|
||||
[clojure.set :as set]
|
||||
[promesa.exec :as px]))
|
||||
@@ -123,7 +123,7 @@
|
||||
[:update-file/global]]
|
||||
|
||||
::webhooks/event? true
|
||||
::webhooks/batch-timeout (dt/duration "2m")
|
||||
::webhooks/batch-timeout (ct/duration "2m")
|
||||
::webhooks/batch-key (webhooks/key-fn ::rpc/profile-id :id)
|
||||
|
||||
::sm/params schema:update-file
|
||||
@@ -156,9 +156,9 @@
|
||||
(assoc :file file)
|
||||
(assoc :changes changes))
|
||||
|
||||
cfg (assoc cfg ::timestamp (dt/now))
|
||||
cfg (assoc cfg ::timestamp (ct/now))
|
||||
|
||||
tpoint (dt/tpoint)]
|
||||
tpoint (ct/tpoint)]
|
||||
|
||||
|
||||
(when (not= (:vern params)
|
||||
@@ -199,7 +199,7 @@
|
||||
(errors/request->context))]
|
||||
(-> (update-file* cfg params)
|
||||
(rph/with-defer #(let [elapsed (tpoint)]
|
||||
(l/trace :hint "update-file" :time (dt/format-duration elapsed))))))))))
|
||||
(l/trace :hint "update-file" :time (ct/format-duration elapsed))))))))))
|
||||
|
||||
(defn- update-file*
|
||||
"Internal function, part of the update-file process, that encapsulates
|
||||
@@ -244,8 +244,8 @@
|
||||
:created-at timestamp
|
||||
:updated-at timestamp
|
||||
:deleted-at (if (::snapshot-data file)
|
||||
(dt/plus timestamp (ldel/get-deletion-delay team))
|
||||
(dt/plus timestamp (dt/duration {:hours 1})))
|
||||
(ct/plus timestamp (ldel/get-deletion-delay team))
|
||||
(ct/plus timestamp (ct/duration {:hours 1})))
|
||||
:file-id (:id file)
|
||||
:revn (:revn file)
|
||||
:version (:version file)
|
||||
@@ -306,7 +306,7 @@
|
||||
[{:keys [::db/conn ::timestamp]} file]
|
||||
(let [;; The timestamp can be nil because this function is also
|
||||
;; intended to be used outside of this module
|
||||
modified-at (or timestamp (dt/now))]
|
||||
modified-at (or timestamp (ct/now))]
|
||||
|
||||
(db/update! conn :project
|
||||
{:modified-at modified-at}
|
||||
@@ -360,7 +360,7 @@
|
||||
;; TODO: reuse operations if file is migrated
|
||||
;; TODO: move encoding to a separated thread
|
||||
file (if (take-snapshot? file)
|
||||
(let [tpoint (dt/tpoint)
|
||||
(let [tpoint (ct/tpoint)
|
||||
snapshot (-> (:data file)
|
||||
(feat.fdata/process-pointers deref)
|
||||
(feat.fdata/process-objects (partial into {}))
|
||||
@@ -372,7 +372,7 @@
|
||||
:file-id (str (:id file))
|
||||
:revn (:revn file)
|
||||
:label label
|
||||
:elapsed (dt/format-duration elapsed))
|
||||
:elapsed (ct/format-duration elapsed))
|
||||
|
||||
(-> file
|
||||
(assoc ::snapshot-data snapshot)
|
||||
@@ -452,11 +452,11 @@
|
||||
(when (contains? cf/flags :auto-file-snapshot)
|
||||
(let [freq (or (cf/get :auto-file-snapshot-every) 20)
|
||||
timeout (or (cf/get :auto-file-snapshot-timeout)
|
||||
(dt/duration {:hours 1}))]
|
||||
(ct/duration {:hours 1}))]
|
||||
|
||||
(or (= 1 freq)
|
||||
(zero? (mod revn freq))
|
||||
(> (inst-ms (dt/diff modified-at (dt/now)))
|
||||
(> (inst-ms (ct/diff modified-at (ct/now)))
|
||||
(inst-ms timeout))))))
|
||||
|
||||
(def ^:private sql:lagged-changes
|
||||
@@ -496,5 +496,5 @@
|
||||
:file-id (:id file)
|
||||
:session-id session-id
|
||||
:revn (:revn file)
|
||||
:modified-at (dt/now)
|
||||
:modified-at (ct/now)
|
||||
:changes lchanges}))))
|
||||
|
||||
@@ -9,6 +9,7 @@
|
||||
[app.common.data.macros :as dm]
|
||||
[app.common.exceptions :as ex]
|
||||
[app.common.schema :as sm]
|
||||
[app.common.time :as ct]
|
||||
[app.common.uuid :as uuid]
|
||||
[app.db :as db]
|
||||
[app.db.sql :as-alias sql]
|
||||
@@ -26,7 +27,6 @@
|
||||
[app.rpc.quotes :as quotes]
|
||||
[app.storage :as sto]
|
||||
[app.util.services :as sv]
|
||||
[app.util.time :as dt]
|
||||
[app.worker :as-alias wrk]
|
||||
[promesa.exec :as px]))
|
||||
|
||||
@@ -124,7 +124,7 @@
|
||||
content (-> (sto/content resource)
|
||||
(sto/wrap-with-hash hash))]
|
||||
{::sto/content content
|
||||
::sto/touched-at (dt/now)
|
||||
::sto/touched-at (ct/now)
|
||||
::sto/deduplicate? true
|
||||
:content-type mtype
|
||||
:bucket "team-font-variant"})))
|
||||
@@ -217,7 +217,7 @@
|
||||
{::sql/for-update true})
|
||||
|
||||
delay (ldel/get-deletion-delay team)
|
||||
tnow (dt/in-future delay)]
|
||||
tnow (ct/in-future delay)]
|
||||
|
||||
(teams/check-edition-permissions! (:permissions team))
|
||||
|
||||
@@ -261,7 +261,7 @@
|
||||
|
||||
(teams/check-edition-permissions! (:permissions team))
|
||||
(db/update! conn :team-font-variant
|
||||
{:deleted-at (dt/in-future delay)}
|
||||
{:deleted-at (ct/in-future delay)}
|
||||
{:id (:id variant)}
|
||||
{::db/return-keys false})
|
||||
|
||||
|
||||
@@ -13,6 +13,7 @@
|
||||
[app.common.exceptions :as ex]
|
||||
[app.common.features :as cfeat]
|
||||
[app.common.schema :as sm]
|
||||
[app.common.time :as ct]
|
||||
[app.common.uuid :as uuid]
|
||||
[app.config :as cf]
|
||||
[app.db :as db]
|
||||
@@ -28,7 +29,6 @@
|
||||
[app.setup.templates :as tmpl]
|
||||
[app.storage.tmp :as tmp]
|
||||
[app.util.services :as sv]
|
||||
[app.util.time :as dt]
|
||||
[app.worker :as-alias wrk]
|
||||
[promesa.exec :as px]))
|
||||
|
||||
@@ -104,7 +104,7 @@
|
||||
(db/exec-one! conn ["SET CONSTRAINTS ALL DEFERRED"])
|
||||
|
||||
(binding [bfc/*state* (volatile! {:index {file-id (uuid/next)}})]
|
||||
(duplicate-file (assoc cfg ::bfc/timestamp (dt/now))
|
||||
(duplicate-file (assoc cfg ::bfc/timestamp (ct/now))
|
||||
(-> params
|
||||
(assoc :profile-id profile-id)
|
||||
(assoc :reset-shared-flag true)))))))
|
||||
@@ -164,7 +164,7 @@
|
||||
(db/tx-run! cfg (fn [cfg]
|
||||
;; Defer all constraints
|
||||
(db/exec-one! cfg ["SET CONSTRAINTS ALL DEFERRED"])
|
||||
(-> (assoc cfg ::bfc/timestamp (dt/now))
|
||||
(-> (assoc cfg ::bfc/timestamp (ct/now))
|
||||
(duplicate-project (assoc params :profile-id profile-id))))))
|
||||
|
||||
(defn duplicate-team
|
||||
@@ -320,7 +320,7 @@
|
||||
;; trully different modification date to each file.
|
||||
(px/sleep 10)
|
||||
(db/update! conn :project
|
||||
{:modified-at (dt/now)}
|
||||
{:modified-at (ct/now)}
|
||||
{:id project-id}))
|
||||
|
||||
nil))
|
||||
@@ -425,7 +425,7 @@
|
||||
(db/tx-run! cfg
|
||||
(fn [{:keys [::db/conn] :as cfg}]
|
||||
(db/update! conn :project
|
||||
{:modified-at (dt/now)}
|
||||
{:modified-at (ct/now)}
|
||||
{:id project-id}
|
||||
{::db/return-keys false})
|
||||
|
||||
|
||||
@@ -10,6 +10,7 @@
|
||||
[app.common.exceptions :as ex]
|
||||
[app.common.media :as cm]
|
||||
[app.common.schema :as sm]
|
||||
[app.common.time :as ct]
|
||||
[app.common.uuid :as uuid]
|
||||
[app.config :as cf]
|
||||
[app.db :as db]
|
||||
@@ -23,7 +24,6 @@
|
||||
[app.storage :as sto]
|
||||
[app.storage.tmp :as tmp]
|
||||
[app.util.services :as sv]
|
||||
[app.util.time :as dt]
|
||||
[app.worker :as-alias wrk]
|
||||
[cuerdas.core :as str]
|
||||
[datoteka.io :as io]
|
||||
@@ -67,7 +67,7 @@
|
||||
mobj (create-file-media-object cfg params)]
|
||||
|
||||
(db/update! conn :file
|
||||
{:modified-at (dt/now)
|
||||
{:modified-at (ct/now)
|
||||
:has-media-trimmed false}
|
||||
{:id file-id}
|
||||
{::db/return-keys false})
|
||||
@@ -192,7 +192,7 @@
|
||||
mobj (create-file-media-object-from-url cfg (assoc params :profile-id profile-id))]
|
||||
|
||||
(db/update! pool :file
|
||||
{:modified-at (dt/now)
|
||||
{:modified-at (ct/now)
|
||||
:has-media-trimmed false}
|
||||
{:id file-id}
|
||||
{::db/return-keys false})
|
||||
|
||||
@@ -10,6 +10,7 @@
|
||||
[app.common.data :as d]
|
||||
[app.common.exceptions :as ex]
|
||||
[app.common.schema :as sm]
|
||||
[app.common.time :as ct]
|
||||
[app.common.types.plugins :refer [schema:plugin-registry]]
|
||||
[app.common.uuid :as uuid]
|
||||
[app.config :as cf]
|
||||
@@ -28,7 +29,6 @@
|
||||
[app.storage :as sto]
|
||||
[app.tokens :as tokens]
|
||||
[app.util.services :as sv]
|
||||
[app.util.time :as dt]
|
||||
[app.worker :as wrk]
|
||||
[cuerdas.core :as str]
|
||||
[promesa.exec :as px]))
|
||||
@@ -70,8 +70,8 @@
|
||||
[:is-blocked {:optional true} ::sm/boolean]
|
||||
[:is-demo {:optional true} ::sm/boolean]
|
||||
[:is-muted {:optional true} ::sm/boolean]
|
||||
[:created-at {:optional true} ::sm/inst]
|
||||
[:modified-at {:optional true} ::sm/inst]
|
||||
[:created-at {:optional true} ::ct/inst]
|
||||
[:modified-at {:optional true} ::ct/inst]
|
||||
[:default-project-id {:optional true} ::sm/uuid]
|
||||
[:default-team-id {:optional true} ::sm/uuid]
|
||||
[:props {:optional true} schema:props]])
|
||||
@@ -352,13 +352,13 @@
|
||||
[{:keys [::db/conn] :as cfg} {:keys [profile email] :as params}]
|
||||
(let [token (tokens/generate (::setup/props cfg)
|
||||
{:iss :change-email
|
||||
:exp (dt/in-future "15m")
|
||||
:exp (ct/in-future "15m")
|
||||
:profile-id (:id profile)
|
||||
:email email})
|
||||
ptoken (tokens/generate (::setup/props cfg)
|
||||
{:iss :profile-identity
|
||||
:profile-id (:id profile)
|
||||
:exp (dt/in-future {:days 30})})]
|
||||
:exp (ct/in-future {:days 30})})]
|
||||
|
||||
(when (not= email (:email profile))
|
||||
(check-profile-existence! conn params))
|
||||
@@ -444,7 +444,7 @@
|
||||
::db/transaction true}
|
||||
[{:keys [::db/conn] :as cfg} {:keys [::rpc/profile-id] :as params}]
|
||||
(let [teams (get-owned-teams conn profile-id)
|
||||
deleted-at (dt/now)]
|
||||
deleted-at (ct/now)]
|
||||
|
||||
;; If we found owned teams with participants, we don't allow
|
||||
;; delete profile until the user properly transfer ownership or
|
||||
|
||||
@@ -9,6 +9,7 @@
|
||||
[app.common.data.macros :as dm]
|
||||
[app.common.exceptions :as ex]
|
||||
[app.common.schema :as sm]
|
||||
[app.common.time :as ct]
|
||||
[app.db :as db]
|
||||
[app.db.sql :as-alias sql]
|
||||
[app.features.logical-deletion :as ldel]
|
||||
@@ -21,7 +22,6 @@
|
||||
[app.rpc.permissions :as perms]
|
||||
[app.rpc.quotes :as quotes]
|
||||
[app.util.services :as sv]
|
||||
[app.util.time :as dt]
|
||||
[app.worker :as wrk]))
|
||||
|
||||
;; --- Check Project Permissions
|
||||
@@ -218,7 +218,7 @@
|
||||
(sv/defmethod ::update-project-pin
|
||||
{::doc/added "1.18"
|
||||
::sm/params schema:update-project-pin
|
||||
::webhooks/batch-timeout (dt/duration "5s")
|
||||
::webhooks/batch-timeout (ct/duration "5s")
|
||||
::webhooks/batch-key (webhooks/key-fn ::rpc/profile-id :id)
|
||||
::webhooks/event? true
|
||||
::db/transaction true}
|
||||
@@ -257,7 +257,7 @@
|
||||
[conn team project-id]
|
||||
(let [delay (ldel/get-deletion-delay team)
|
||||
project (db/update! conn :project
|
||||
{:deleted-at (dt/in-future delay)}
|
||||
{:deleted-at (ct/in-future delay)}
|
||||
{:id project-id}
|
||||
{::db/return-keys true})]
|
||||
|
||||
|
||||
@@ -11,6 +11,7 @@
|
||||
[app.common.exceptions :as ex]
|
||||
[app.common.features :as cfeat]
|
||||
[app.common.schema :as sm]
|
||||
[app.common.time :as ct]
|
||||
[app.common.types.team :as tt]
|
||||
[app.common.uuid :as uuid]
|
||||
[app.config :as cf]
|
||||
@@ -30,7 +31,6 @@
|
||||
[app.setup :as-alias setup]
|
||||
[app.storage :as sto]
|
||||
[app.util.services :as sv]
|
||||
[app.util.time :as dt]
|
||||
[app.worker :as wrk]
|
||||
[clojure.set :as set]))
|
||||
|
||||
@@ -666,7 +666,7 @@
|
||||
|
||||
(let [delay (ldel/get-deletion-delay team)
|
||||
team (db/update! conn :team
|
||||
{:deleted-at (dt/in-future delay)}
|
||||
{:deleted-at (ct/in-future delay)}
|
||||
{:id id}
|
||||
{::db/return-keys true})]
|
||||
|
||||
|
||||
@@ -12,6 +12,7 @@
|
||||
[app.common.features :as cfeat]
|
||||
[app.common.logging :as l]
|
||||
[app.common.schema :as sm]
|
||||
[app.common.time :as ct]
|
||||
[app.common.types.team :as types.team]
|
||||
[app.common.uuid :as uuid]
|
||||
[app.config :as cf]
|
||||
@@ -29,7 +30,6 @@
|
||||
[app.setup :as-alias setup]
|
||||
[app.tokens :as tokens]
|
||||
[app.util.services :as sv]
|
||||
[app.util.time :as dt]
|
||||
[cuerdas.core :as str]))
|
||||
|
||||
;; --- Mutation: Create Team Invitation
|
||||
@@ -62,7 +62,7 @@
|
||||
(tokens/generate (::setup/props cfg)
|
||||
{:iss :profile-identity
|
||||
:profile-id profile-id
|
||||
:exp (dt/in-future {:days 30})}))
|
||||
:exp (ct/in-future {:days 30})}))
|
||||
|
||||
(def ^:private schema:create-invitation
|
||||
[:map {:title "params:create-invitation"}
|
||||
@@ -126,7 +126,7 @@
|
||||
(teams/check-email-spam conn email true)
|
||||
|
||||
(let [id (uuid/next)
|
||||
expire (dt/in-future "168h") ;; 7 days
|
||||
expire (ct/in-future "168h") ;; 7 days
|
||||
invitation (db/exec-one! conn [sql:upsert-team-invitation id
|
||||
(:id team) (str/lower email)
|
||||
(:id profile)
|
||||
@@ -418,7 +418,7 @@
|
||||
:code :insufficient-permissions))
|
||||
|
||||
(db/update! conn :team-invitation
|
||||
{:role (name role) :updated-at (dt/now)}
|
||||
{:role (name role) :updated-at (ct/now)}
|
||||
{:team-id team-id :email-to (profile/clean-email email)})
|
||||
|
||||
nil))
|
||||
@@ -471,7 +471,7 @@
|
||||
(when-let [request (db/get* conn :team-access-request
|
||||
{:team-id team-id
|
||||
:requester-id profile-id})]
|
||||
(when (dt/is-after? (:valid-until request) (dt/now))
|
||||
(when (ct/is-after? (:valid-until request) (ct/now))
|
||||
(ex/raise :type :validation
|
||||
:code :request-already-sent
|
||||
:hint "you have already made a request to join this team less than 24 hours ago"))))
|
||||
@@ -487,8 +487,8 @@
|
||||
"Create or update team access request for provided team and profile-id"
|
||||
[conn team-id requester-id]
|
||||
(check-existing-team-access-request conn team-id requester-id)
|
||||
(let [valid-until (dt/in-future {:hours 24})
|
||||
auto-join-until (dt/in-future {:days 7})
|
||||
(let [valid-until (ct/in-future {:hours 24})
|
||||
auto-join-until (ct/in-future {:days 7})
|
||||
request-id (uuid/next)]
|
||||
(db/exec-one! conn [sql:upsert-team-access-request
|
||||
request-id team-id requester-id
|
||||
|
||||
@@ -8,6 +8,7 @@
|
||||
(:require
|
||||
[app.common.exceptions :as ex]
|
||||
[app.common.schema :as sm]
|
||||
[app.common.time :as ct]
|
||||
[app.common.types.team :as types.team]
|
||||
[app.config :as cf]
|
||||
[app.db :as db]
|
||||
@@ -23,8 +24,7 @@
|
||||
[app.setup :as-alias setup]
|
||||
[app.tokens :as tokens]
|
||||
[app.tokens.spec.team-invitation :as-alias spec.team-invitation]
|
||||
[app.util.services :as sv]
|
||||
[app.util.time :as dt]))
|
||||
[app.util.services :as sv]))
|
||||
|
||||
(defmulti process-token (fn [_ _ claims] (:iss claims)))
|
||||
|
||||
@@ -126,7 +126,7 @@
|
||||
(def schema:team-invitation-claims
|
||||
[:map {:title "TeamInvitationClaims"}
|
||||
[:iss :keyword]
|
||||
[:exp ::dt/instant]
|
||||
[:exp ::ct/inst]
|
||||
[:profile-id ::sm/uuid]
|
||||
[:role ::types.team/role]
|
||||
[:team-id ::sm/uuid]
|
||||
|
||||
@@ -9,6 +9,7 @@
|
||||
[app.common.data.macros :as dm]
|
||||
[app.common.exceptions :as ex]
|
||||
[app.common.schema :as sm]
|
||||
[app.common.time :as ct]
|
||||
[app.common.uri :as u]
|
||||
[app.common.uuid :as uuid]
|
||||
[app.db :as db]
|
||||
@@ -19,7 +20,6 @@
|
||||
[app.rpc.doc :as-alias doc]
|
||||
[app.rpc.permissions :as perms]
|
||||
[app.util.services :as sv]
|
||||
[app.util.time :as dt]
|
||||
[cuerdas.core :as str]))
|
||||
|
||||
(defn get-webhooks-permissions
|
||||
@@ -54,7 +54,7 @@
|
||||
(http/req! cfg
|
||||
{:method :head
|
||||
:uri (str (:uri params))
|
||||
:timeout (dt/duration "3s")}
|
||||
:timeout (ct/duration "3s")}
|
||||
{:sync? true}))]
|
||||
(if (ex/exception? response)
|
||||
(if-let [hint (webhooks/interpret-exception response)]
|
||||
|
||||
@@ -10,9 +10,9 @@
|
||||
[app.common.exceptions :as ex]
|
||||
[app.common.logging :as l]
|
||||
[app.common.schema :as sm]
|
||||
[app.common.time :as ct]
|
||||
[app.config :as cf]
|
||||
[app.db :as db]
|
||||
[app.util.time :as dt]
|
||||
[app.worker :as wrk]
|
||||
[cuerdas.core :as str]))
|
||||
|
||||
@@ -95,7 +95,7 @@
|
||||
"- Total: ~(::total params) (INCR ~(::incr params 1))\n")]
|
||||
(wrk/submit! {::db/conn conn
|
||||
::wrk/task :sendmail
|
||||
::wrk/delay (dt/duration "30s")
|
||||
::wrk/delay (ct/duration "30s")
|
||||
::wrk/max-retries 4
|
||||
::wrk/priority 200
|
||||
::wrk/dedupe true
|
||||
|
||||
@@ -47,6 +47,7 @@
|
||||
[app.common.exceptions :as ex]
|
||||
[app.common.logging :as l]
|
||||
[app.common.schema :as sm]
|
||||
[app.common.time :as ct]
|
||||
[app.common.uri :as uri]
|
||||
[app.common.uuid :as uuid]
|
||||
[app.config :as cf]
|
||||
@@ -58,7 +59,6 @@
|
||||
[app.rpc.rlimit.result :as-alias lresult]
|
||||
[app.util.inet :as inet]
|
||||
[app.util.services :as-alias sv]
|
||||
[app.util.time :as dt]
|
||||
[app.worker :as wrk]
|
||||
[clojure.edn :as edn]
|
||||
[cuerdas.core :as str]
|
||||
@@ -67,7 +67,7 @@
|
||||
[promesa.exec :as px]))
|
||||
|
||||
(def ^:private default-timeout
|
||||
(dt/duration 400))
|
||||
(ct/duration 400))
|
||||
|
||||
(def ^:private default-options
|
||||
{:codec rds/string-codec
|
||||
@@ -94,6 +94,10 @@
|
||||
(defmulti parse-limit (fn [[_ strategy _]] strategy))
|
||||
(defmulti process-limit (fn [_ _ _ o] (::strategy o)))
|
||||
|
||||
(defn- ->seconds
|
||||
[d]
|
||||
(-> d inst-ms (/ 1000) int))
|
||||
|
||||
(sm/register!
|
||||
{:type ::rpc/rlimit
|
||||
:pred #(instance? clojure.lang.Agent %)})
|
||||
@@ -115,7 +119,7 @@
|
||||
[:map
|
||||
[::capacity ::sm/int]
|
||||
[::rate ::sm/int]
|
||||
[::internal ::dt/duration]
|
||||
[::internal ::ct/duration]
|
||||
[::params [::sm/vec :any]]]
|
||||
[:map
|
||||
[::nreq ::sm/int]
|
||||
@@ -157,7 +161,7 @@
|
||||
(assert (valid-limit-tuple? vlimit) "expected valid limit tuple")
|
||||
|
||||
(if-let [[_ capacity rate interval] (re-find bucket-opts-re opts)]
|
||||
(let [interval (dt/duration interval)
|
||||
(let [interval (ct/duration interval)
|
||||
rate (parse-long rate)
|
||||
capacity (parse-long capacity)]
|
||||
{::name name
|
||||
@@ -166,7 +170,7 @@
|
||||
::rate rate
|
||||
::interval interval
|
||||
::opts opts
|
||||
::params [(dt/->seconds interval) rate capacity]
|
||||
::params [(->seconds interval) rate capacity]
|
||||
::key (str "ratelimit.bucket." (d/name name))})
|
||||
(ex/raise :type :validation
|
||||
:code :invalid-bucket-limit-opts
|
||||
@@ -176,7 +180,7 @@
|
||||
[redis user-id now {:keys [::key ::params ::service ::capacity ::interval ::rate] :as limit}]
|
||||
(let [script (-> bucket-rate-limit-script
|
||||
(assoc ::rscript/keys [(str key "." service "." user-id)])
|
||||
(assoc ::rscript/vals (conj params (dt/->seconds now))))
|
||||
(assoc ::rscript/vals (conj params (->seconds now))))
|
||||
result (rds/eval redis script)
|
||||
allowed? (boolean (nth result 0))
|
||||
remaining (nth result 1)
|
||||
@@ -191,16 +195,16 @@
|
||||
:remaining remaining)
|
||||
(-> limit
|
||||
(assoc ::lresult/allowed allowed?)
|
||||
(assoc ::lresult/reset (dt/plus now reset))
|
||||
(assoc ::lresult/reset (ct/plus now reset))
|
||||
(assoc ::lresult/remaining remaining))))
|
||||
|
||||
(defmethod process-limit :window
|
||||
[redis user-id now {:keys [::nreq ::unit ::key ::service] :as limit}]
|
||||
(let [ts (dt/truncate now unit)
|
||||
ttl (dt/diff now (dt/plus ts {unit 1}))
|
||||
(let [ts (ct/truncate now unit)
|
||||
ttl (ct/diff now (ct/plus ts {unit 1}))
|
||||
script (-> window-rate-limit-script
|
||||
(assoc ::rscript/keys [(str key "." service "." user-id "." (dt/format-instant ts))])
|
||||
(assoc ::rscript/vals [nreq (dt/->seconds ttl)]))
|
||||
(assoc ::rscript/keys [(str key "." service "." user-id "." (ct/format-inst ts))])
|
||||
(assoc ::rscript/vals [nreq (->seconds ttl)]))
|
||||
result (rds/eval redis script)
|
||||
allowed? (boolean (nth result 0))
|
||||
remaining (nth result 1)]
|
||||
@@ -214,7 +218,7 @@
|
||||
(-> limit
|
||||
(assoc ::lresult/allowed allowed?)
|
||||
(assoc ::lresult/remaining remaining)
|
||||
(assoc ::lresult/reset (dt/plus ts {unit 1})))))
|
||||
(assoc ::lresult/reset (ct/plus ts {unit 1})))))
|
||||
|
||||
(defn- process-limits!
|
||||
[redis user-id limits now]
|
||||
@@ -223,7 +227,7 @@
|
||||
(d/index-by ::name ::lresult/remaining)
|
||||
(uri/map->query-string))
|
||||
reset (->> results
|
||||
(d/index-by ::name (comp dt/->seconds ::lresult/reset))
|
||||
(d/index-by ::name (comp ->seconds ::lresult/reset))
|
||||
(uri/map->query-string))
|
||||
|
||||
rejected (d/seek (complement ::lresult/allowed) results)]
|
||||
@@ -261,7 +265,7 @@
|
||||
(let [redis (rds/get-or-connect redis ::rpc/rlimit default-options)
|
||||
uid (get-uid params)
|
||||
;; FIXME: why not clasic try/catch?
|
||||
result (ex/try! (process-limits! redis uid limits (dt/now)))]
|
||||
result (ex/try! (process-limits! redis uid limits (ct/now)))]
|
||||
|
||||
(l/trc :hint "process-limits"
|
||||
:service sname
|
||||
@@ -321,7 +325,7 @@
|
||||
(sm/check-fn schema:config))
|
||||
|
||||
(def ^:private check-refresh
|
||||
(sm/check-fn ::dt/duration))
|
||||
(sm/check-fn ::ct/duration))
|
||||
|
||||
(def ^:private check-limits
|
||||
(sm/check-fn schema:limits))
|
||||
@@ -351,7 +355,7 @@
|
||||
config)))]
|
||||
|
||||
(when-let [config (some->> path slurp edn/read-string check-config)]
|
||||
(let [refresh (->> config meta :refresh dt/duration check-refresh)
|
||||
(let [refresh (->> config meta :refresh ct/duration check-refresh)
|
||||
limits (->> config compile-pass-1 compile-pass-2 check-limits)]
|
||||
|
||||
{::refresh refresh
|
||||
@@ -410,7 +414,7 @@
|
||||
(l/info :hint "initializing rlimit config reader" :path (str path))
|
||||
|
||||
;; Initialize the state with initial refresh value
|
||||
(send-via executor state (constantly {::refresh (dt/duration "5s")}))
|
||||
(send-via executor state (constantly {::refresh (ct/duration "5s")}))
|
||||
|
||||
;; Force a refresh
|
||||
(refresh-config (assoc cfg ::path path ::state state)))
|
||||
|
||||
@@ -11,11 +11,11 @@
|
||||
[app.common.exceptions :as ex]
|
||||
[app.common.json :as json]
|
||||
[app.common.logging :as l]
|
||||
[app.common.time :as ct]
|
||||
[app.config :as cf]
|
||||
[app.srepl.cli :as cli]
|
||||
[app.srepl.main]
|
||||
[app.util.locks :as locks]
|
||||
[app.util.time :as dt]
|
||||
[clojure.core :as c]
|
||||
[clojure.core.server :as ccs]
|
||||
[clojure.main :as cm]
|
||||
@@ -77,7 +77,7 @@
|
||||
(loop []
|
||||
(when (try
|
||||
(let [data (read-line)
|
||||
tpoint (dt/tpoint)]
|
||||
tpoint (ct/tpoint)]
|
||||
|
||||
(l/dbg :hint "received" :data (if (= data ::eof) "EOF" data))
|
||||
|
||||
|
||||
@@ -10,13 +10,14 @@
|
||||
[app.auth :as auth]
|
||||
[app.common.exceptions :as ex]
|
||||
[app.common.schema :as sm]
|
||||
[app.common.schema.generators :as sg]
|
||||
[app.common.time :as ct]
|
||||
[app.common.uuid :as uuid]
|
||||
[app.db :as db]
|
||||
[app.rpc.commands.auth :as cmd.auth]
|
||||
[app.rpc.commands.profile :as cmd.profile]
|
||||
[app.setup :as-alias setup]
|
||||
[app.tokens :as tokens]
|
||||
[app.util.time :as dt]
|
||||
[cuerdas.core :as str]))
|
||||
|
||||
(defn coercer
|
||||
@@ -101,7 +102,7 @@
|
||||
(fn [{:keys [::db/conn] :as system}]
|
||||
(let [res (if soft
|
||||
(db/update! conn :profile
|
||||
{:deleted-at (dt/now)}
|
||||
{:deleted-at (ct/now)}
|
||||
{:email email :deleted-at nil})
|
||||
(db/delete! conn :profile
|
||||
{:email email}))]
|
||||
@@ -173,6 +174,21 @@
|
||||
:num-editors (get-customer-slots system id)
|
||||
:subscription (get props :subscription)})))
|
||||
|
||||
(def ^:private schema:timestamp
|
||||
(sm/type-schema
|
||||
{:type ::timestamp
|
||||
:pred ct/inst?
|
||||
:type-properties
|
||||
{:title "inst"
|
||||
:description "The same as :app.common.time/inst but encodes to epoch"
|
||||
:error/message "should be an instant"
|
||||
:gen/gen (->> (sg/small-int)
|
||||
(sg/fmap (fn [v] (ct/inst v))))
|
||||
:decode/string ct/inst
|
||||
:encode/string inst-ms
|
||||
:decode/json ct/inst
|
||||
:encode/json inst-ms}}))
|
||||
|
||||
(def ^:private schema:customer-subscription
|
||||
[:map {:title "CustomerSubscription"}
|
||||
[:id ::sm/text]
|
||||
@@ -198,15 +214,15 @@
|
||||
"year"]]
|
||||
[:quantity :int]
|
||||
[:description [:maybe ::sm/text]]
|
||||
[:created-at ::sm/timestamp]
|
||||
[:start-date [:maybe ::sm/timestamp]]
|
||||
[:ended-at [:maybe ::sm/timestamp]]
|
||||
[:trial-end [:maybe ::sm/timestamp]]
|
||||
[:trial-start [:maybe ::sm/timestamp]]
|
||||
[:cancel-at [:maybe ::sm/timestamp]]
|
||||
[:canceled-at [:maybe ::sm/timestamp]]
|
||||
[:current-period-end [:maybe ::sm/timestamp]]
|
||||
[:current-period-start [:maybe ::sm/timestamp]]
|
||||
[:created-at schema:timestamp]
|
||||
[:start-date [:maybe schema:timestamp]]
|
||||
[:ended-at [:maybe schema:timestamp]]
|
||||
[:trial-end [:maybe schema:timestamp]]
|
||||
[:trial-start [:maybe schema:timestamp]]
|
||||
[:cancel-at [:maybe schema:timestamp]]
|
||||
[:canceled-at [:maybe schema:timestamp]]
|
||||
[:current-period-end [:maybe schema:timestamp]]
|
||||
[:current-period-start [:maybe schema:timestamp]]
|
||||
[:cancel-at-period-end :boolean]
|
||||
|
||||
[:cancellation-details
|
||||
|
||||
@@ -12,11 +12,11 @@
|
||||
[app.common.data :as d]
|
||||
[app.common.files.migrations :as fmg]
|
||||
[app.common.files.validate :as cfv]
|
||||
[app.common.time :as ct]
|
||||
[app.db :as db]
|
||||
[app.main :as main]
|
||||
[app.rpc.commands.files :as files]
|
||||
[app.rpc.commands.files-snapshot :as fsnap]
|
||||
[app.util.time :as dt]))
|
||||
[app.rpc.commands.files-snapshot :as fsnap]))
|
||||
|
||||
(def ^:dynamic *system* nil)
|
||||
|
||||
@@ -165,7 +165,7 @@
|
||||
(when (string? label)
|
||||
(fsnap/create-file-snapshot! system file
|
||||
{:label label
|
||||
:deleted-at (dt/in-future {:days 30})
|
||||
:deleted-at (ct/in-future {:days 30})
|
||||
:created-by :admin}))
|
||||
|
||||
(let [file' (update file' :revn inc)]
|
||||
|
||||
@@ -19,6 +19,7 @@
|
||||
[app.common.pprint :as p]
|
||||
[app.common.schema :as sm]
|
||||
[app.common.spec :as us]
|
||||
[app.common.time :as ct]
|
||||
[app.common.uuid :as uuid]
|
||||
[app.config :as cf]
|
||||
[app.db :as db]
|
||||
@@ -38,7 +39,6 @@
|
||||
[app.srepl.helpers :as h]
|
||||
[app.util.blob :as blob]
|
||||
[app.util.pointer-map :as pmap]
|
||||
[app.util.time :as dt]
|
||||
[app.worker :as wrk]
|
||||
[clojure.java.io :as io]
|
||||
[clojure.pprint :refer [print-table]]
|
||||
@@ -476,7 +476,7 @@
|
||||
:max-jobs max-jobs
|
||||
:max-items max-items)
|
||||
|
||||
(let [tpoint (dt/tpoint)
|
||||
(let [tpoint (ct/tpoint)
|
||||
factory (px/thread-factory :virtual false :prefix "penpot/file-process/")
|
||||
executor (px/cached-executor :factory factory)
|
||||
sjobs (ps/create :permits max-jobs)
|
||||
@@ -506,7 +506,7 @@
|
||||
(Thread/sleep (int pause)))
|
||||
|
||||
(ps/release! sjobs)
|
||||
(let [elapsed (dt/format-duration (tpoint))]
|
||||
(let [elapsed (ct/format-duration (tpoint))]
|
||||
(l/trc :hint "process:file:end"
|
||||
:tid thread-id
|
||||
:file-id (str file-id)
|
||||
@@ -516,7 +516,7 @@
|
||||
process-file*
|
||||
(fn [idx file-id]
|
||||
(ps/acquire! sjobs)
|
||||
(px/run! executor (partial process-file file-id idx (dt/tpoint)))
|
||||
(px/run! executor (partial process-file file-id idx (ct/tpoint)))
|
||||
(inc idx))
|
||||
|
||||
process-files
|
||||
@@ -542,7 +542,7 @@
|
||||
(l/dbg :hint "process:error" :cause cause))
|
||||
|
||||
(finally
|
||||
(let [elapsed (dt/format-duration (tpoint))]
|
||||
(let [elapsed (ct/format-duration (tpoint))]
|
||||
(l/dbg :hint "process:end"
|
||||
:rollback rollback?
|
||||
:elapsed elapsed))))))
|
||||
@@ -556,7 +556,7 @@
|
||||
"Mark a project for deletion"
|
||||
[file-id]
|
||||
(let [file-id (h/parse-uuid file-id)
|
||||
tnow (dt/now)]
|
||||
tnow (ct/now)]
|
||||
|
||||
(audit/insert! main/system
|
||||
{::audit/name "delete-file"
|
||||
@@ -618,7 +618,7 @@
|
||||
::audit/props file
|
||||
::audit/context {:triggered-by "srepl"
|
||||
:cause "explicit call to restore-file!"}
|
||||
::audit/tracked-at (dt/now)})
|
||||
::audit/tracked-at (ct/now)})
|
||||
|
||||
(restore-file* system file-id))))))
|
||||
|
||||
@@ -626,7 +626,7 @@
|
||||
"Mark a project for deletion"
|
||||
[project-id]
|
||||
(let [project-id (h/parse-uuid project-id)
|
||||
tnow (dt/now)]
|
||||
tnow (ct/now)]
|
||||
|
||||
(audit/insert! main/system
|
||||
{::audit/name "delete-project"
|
||||
@@ -673,7 +673,7 @@
|
||||
::audit/props project
|
||||
::audit/context {:triggered-by "srepl"
|
||||
:cause "explicit call to restore-team!"}
|
||||
::audit/tracked-at (dt/now)})
|
||||
::audit/tracked-at (ct/now)})
|
||||
|
||||
(restore-project* system project-id))))))
|
||||
|
||||
@@ -681,7 +681,7 @@
|
||||
"Mark a team for deletion"
|
||||
[team-id]
|
||||
(let [team-id (h/parse-uuid team-id)
|
||||
tnow (dt/now)]
|
||||
tnow (ct/now)]
|
||||
|
||||
(audit/insert! main/system
|
||||
{::audit/name "delete-team"
|
||||
@@ -733,7 +733,7 @@
|
||||
::audit/props team
|
||||
::audit/context {:triggered-by "srepl"
|
||||
:cause "explicit call to restore-team!"}
|
||||
::audit/tracked-at (dt/now)})
|
||||
::audit/tracked-at (ct/now)})
|
||||
|
||||
(restore-team* system team-id))))))
|
||||
|
||||
@@ -741,7 +741,7 @@
|
||||
"Mark a profile for deletion."
|
||||
[profile-id]
|
||||
(let [profile-id (h/parse-uuid profile-id)
|
||||
tnow (dt/now)]
|
||||
tnow (ct/now)]
|
||||
|
||||
(audit/insert! main/system
|
||||
{::audit/name "delete-profile"
|
||||
@@ -775,7 +775,7 @@
|
||||
::audit/props (audit/profile->props profile)
|
||||
::audit/context {:triggered-by "srepl"
|
||||
:cause "explicit call to restore-profile!"}
|
||||
::audit/tracked-at (dt/now)})
|
||||
::audit/tracked-at (ct/now)})
|
||||
|
||||
(db/update! system :profile
|
||||
{:deleted-at nil}
|
||||
@@ -821,7 +821,7 @@
|
||||
{:deleted deleted :total total})))]
|
||||
|
||||
(let [path (fs/path path)
|
||||
deleted-at (dt/minus (dt/now) (cf/get-deletion-delay))]
|
||||
deleted-at (ct/minus (ct/now) (cf/get-deletion-delay))]
|
||||
|
||||
(when-not (fs/exists? path)
|
||||
(throw (ex-info "path does not exists" {:path path})))
|
||||
@@ -905,7 +905,7 @@
|
||||
(db/tx-run! main/system
|
||||
(fn [{:keys [::db/conn] :as cfg}]
|
||||
(db/exec-one! conn ["SET CONSTRAINTS ALL DEFERRED"])
|
||||
(let [team (-> (assoc cfg ::bfc/timestamp (dt/now))
|
||||
(let [team (-> (assoc cfg ::bfc/timestamp (ct/now))
|
||||
(mgmt/duplicate-team :team-id team-id :name name))
|
||||
rels (db/query conn :team-profile-rel {:team-id team-id})]
|
||||
|
||||
|
||||
@@ -12,13 +12,13 @@
|
||||
[app.common.data.macros :as dm]
|
||||
[app.common.logging :as l]
|
||||
[app.common.schema :as sm]
|
||||
[app.common.time :as ct]
|
||||
[app.common.uuid :as uuid]
|
||||
[app.config :as cf]
|
||||
[app.db :as db]
|
||||
[app.storage.fs :as sfs]
|
||||
[app.storage.impl :as impl]
|
||||
[app.storage.s3 :as ss3]
|
||||
[app.util.time :as dt]
|
||||
[cuerdas.core :as str]
|
||||
[datoteka.fs :as fs]
|
||||
[integrant.core :as ig])
|
||||
@@ -122,7 +122,7 @@
|
||||
(dissoc :id))
|
||||
|
||||
touched-at (if touch
|
||||
(or touched-at (dt/now))
|
||||
(or touched-at (ct/now))
|
||||
touched-at)
|
||||
|
||||
;; NOTE: for now we don't reuse the deleted objects, but in
|
||||
@@ -224,7 +224,7 @@
|
||||
(assert (valid-storage? storage))
|
||||
(let [id (if (impl/object? object-or-id) (:id object-or-id) object-or-id)]
|
||||
(-> (db/update! connectable :storage-object
|
||||
{:touched-at (dt/now)}
|
||||
{:touched-at (ct/now)}
|
||||
{:id id})
|
||||
(db/get-update-count)
|
||||
(pos?))))
|
||||
@@ -235,7 +235,7 @@
|
||||
[storage object]
|
||||
(assert (valid-storage? storage))
|
||||
(when (or (nil? (:expired-at object))
|
||||
(dt/is-after? (:expired-at object) (dt/now)))
|
||||
(ct/is-after? (:expired-at object) (ct/now)))
|
||||
(-> (impl/resolve-backend storage (:backend object))
|
||||
(impl/get-object-data object))))
|
||||
|
||||
@@ -244,7 +244,7 @@
|
||||
[storage object]
|
||||
(assert (valid-storage? storage))
|
||||
(when (or (nil? (:expired-at object))
|
||||
(dt/is-after? (:expired-at object) (dt/now)))
|
||||
(ct/is-after? (:expired-at object) (ct/now)))
|
||||
(-> (impl/resolve-backend storage (:backend object))
|
||||
(impl/get-object-bytes object))))
|
||||
|
||||
@@ -254,7 +254,7 @@
|
||||
([storage object options]
|
||||
(assert (valid-storage? storage))
|
||||
(when (or (nil? (:expired-at object))
|
||||
(dt/is-after? (:expired-at object) (dt/now)))
|
||||
(ct/is-after? (:expired-at object) (ct/now)))
|
||||
(-> (impl/resolve-backend storage (:backend object))
|
||||
(impl/get-object-url object options)))))
|
||||
|
||||
@@ -266,7 +266,7 @@
|
||||
(let [backend (impl/resolve-backend storage (:backend object))]
|
||||
(when (and (= :fs (::type backend))
|
||||
(or (nil? (:expired-at object))
|
||||
(dt/is-after? (:expired-at object) (dt/now))))
|
||||
(ct/is-after? (:expired-at object) (ct/now))))
|
||||
(-> (impl/get-object-url backend object nil) file-url->path))))
|
||||
|
||||
(defn del-object!
|
||||
@@ -274,7 +274,7 @@
|
||||
(assert (valid-storage? storage))
|
||||
(let [id (if (impl/object? object-or-id) (:id object-or-id) object-or-id)
|
||||
res (db/update! connectable :storage-object
|
||||
{:deleted-at (dt/now)}
|
||||
{:deleted-at (ct/now)}
|
||||
{:id id})]
|
||||
(pos? (db/get-update-count res))))
|
||||
|
||||
|
||||
@@ -15,10 +15,10 @@
|
||||
(:require
|
||||
[app.common.data :as d]
|
||||
[app.common.logging :as l]
|
||||
[app.common.time :as ct]
|
||||
[app.db :as db]
|
||||
[app.storage :as sto]
|
||||
[app.storage.impl :as impl]
|
||||
[app.util.time :as dt]
|
||||
[integrant.core :as ig]))
|
||||
|
||||
(def ^:private sql:lock-sobjects
|
||||
@@ -106,18 +106,18 @@
|
||||
|
||||
(defmethod ig/expand-key ::handler
|
||||
[k v]
|
||||
{k (assoc v ::min-age (dt/duration {:hours 2}))})
|
||||
{k (assoc v ::min-age (ct/duration {:hours 2}))})
|
||||
|
||||
(defmethod ig/init-key ::handler
|
||||
[_ {:keys [::min-age] :as cfg}]
|
||||
(fn [{:keys [props] :as task}]
|
||||
(let [min-age (dt/duration (or (:min-age props) min-age))]
|
||||
(let [min-age (ct/duration (or (:min-age props) min-age))]
|
||||
(db/tx-run! cfg (fn [cfg]
|
||||
(let [cfg (assoc cfg ::min-age min-age)
|
||||
total (clean-deleted! cfg)]
|
||||
|
||||
(l/inf :hint "task finished"
|
||||
:min-age (dt/format-duration min-age)
|
||||
:min-age (ct/format-duration min-age)
|
||||
:total total)
|
||||
|
||||
{:deleted total}))))))
|
||||
|
||||
@@ -12,11 +12,11 @@
|
||||
[app.common.exceptions :as ex]
|
||||
[app.common.logging :as l]
|
||||
[app.common.schema :as sm]
|
||||
[app.common.time :as ct]
|
||||
[app.common.uri :as u]
|
||||
[app.storage :as-alias sto]
|
||||
[app.storage.impl :as impl]
|
||||
[app.storage.tmp :as tmp]
|
||||
[app.util.time :as dt]
|
||||
[app.worker :as-alias wrk]
|
||||
[clojure.java.io :as io]
|
||||
[datoteka.fs :as fs]
|
||||
@@ -69,7 +69,7 @@
|
||||
20000)
|
||||
|
||||
(def default-timeout
|
||||
(dt/duration {:seconds 30}))
|
||||
(ct/duration {:seconds 30}))
|
||||
|
||||
(declare put-object)
|
||||
(declare get-object-bytes)
|
||||
@@ -338,11 +338,11 @@
|
||||
(p/fmap #(.asByteArray ^ResponseBytes %)))))
|
||||
|
||||
(def default-max-age
|
||||
(dt/duration {:minutes 10}))
|
||||
(ct/duration {:minutes 10}))
|
||||
|
||||
(defn- get-object-url
|
||||
[{:keys [::presigner ::bucket ::prefix]} {:keys [id]} {:keys [max-age] :or {max-age default-max-age}}]
|
||||
(assert (dt/duration? max-age) "expected valid duration instance")
|
||||
(assert (ct/duration? max-age) "expected valid duration instance")
|
||||
|
||||
(let [gor (.. (GetObjectRequest/builder)
|
||||
(bucket bucket)
|
||||
|
||||
@@ -12,8 +12,8 @@
|
||||
(:require
|
||||
[app.common.logging :as l]
|
||||
[app.common.schema :as sm]
|
||||
[app.common.time :as ct]
|
||||
[app.common.uuid :as uuid]
|
||||
[app.util.time :as dt]
|
||||
[app.worker :as wrk]
|
||||
[datoteka.fs :as fs]
|
||||
[datoteka.io :as io]
|
||||
@@ -38,7 +38,7 @@
|
||||
|
||||
(defmethod ig/expand-key ::cleaner
|
||||
[k v]
|
||||
{k (assoc v ::min-age (dt/duration "60m"))})
|
||||
{k (assoc v ::min-age (ct/duration "60m"))})
|
||||
|
||||
(defmethod ig/init-key ::cleaner
|
||||
[_ cfg]
|
||||
@@ -52,13 +52,13 @@
|
||||
|
||||
(defn- io-loop
|
||||
[{:keys [::min-age] :as cfg}]
|
||||
(l/inf :hint "started tmp cleaner" :default-min-age (dt/format-duration min-age))
|
||||
(l/inf :hint "started tmp cleaner" :default-min-age (ct/format-duration min-age))
|
||||
(try
|
||||
(loop []
|
||||
(when-let [[path min-age'] (sp/take! queue)]
|
||||
(let [min-age (or min-age' min-age)]
|
||||
(l/dbg :hint "schedule tempfile deletion" :path path
|
||||
:expires-at (dt/plus (dt/now) min-age))
|
||||
:expires-at (ct/plus (ct/now) min-age))
|
||||
(px/schedule! (inst-ms min-age) (partial remove-temp-file cfg path))
|
||||
(recur))))
|
||||
(catch InterruptedException _
|
||||
@@ -87,7 +87,7 @@
|
||||
path (fs/join default-tmp-dir (str prefix (uuid/next) suffix))
|
||||
path (Files/createFile path attrs)]
|
||||
(fs/delete-on-exit! path)
|
||||
(sp/offer! queue [path (some-> min-age dt/duration)])
|
||||
(sp/offer! queue [path (some-> min-age ct/duration)])
|
||||
path))
|
||||
|
||||
(defn tempfile-from
|
||||
|
||||
@@ -8,10 +8,10 @@
|
||||
"A generic task for object deletion cascade handling"
|
||||
(:require
|
||||
[app.common.logging :as l]
|
||||
[app.common.time :as ct]
|
||||
[app.db :as db]
|
||||
[app.rpc.commands.files :as files]
|
||||
[app.rpc.commands.profile :as profile]
|
||||
[app.util.time :as dt]
|
||||
[integrant.core :as ig]))
|
||||
|
||||
(def ^:dynamic *team-deletion* false)
|
||||
@@ -23,7 +23,7 @@
|
||||
[{:keys [::db/conn] :as cfg} {:keys [id deleted-at]}]
|
||||
(when-let [file (db/get* conn :file {:id id} {::db/remove-deleted false})]
|
||||
(l/trc :hint "marking for deletion" :rel "file" :id (str id)
|
||||
:deleted-at (dt/format-instant deleted-at))
|
||||
:deleted-at (ct/format-inst deleted-at))
|
||||
|
||||
(db/update! conn :file
|
||||
{:deleted-at deleted-at}
|
||||
@@ -62,7 +62,7 @@
|
||||
(defmethod delete-object :project
|
||||
[{:keys [::db/conn] :as cfg} {:keys [id deleted-at]}]
|
||||
(l/trc :hint "marking for deletion" :rel "project" :id (str id)
|
||||
:deleted-at (dt/format-instant deleted-at))
|
||||
:deleted-at (ct/format-inst deleted-at))
|
||||
|
||||
(db/update! conn :project
|
||||
{:deleted-at deleted-at}
|
||||
@@ -79,7 +79,7 @@
|
||||
(defmethod delete-object :team
|
||||
[{:keys [::db/conn] :as cfg} {:keys [id deleted-at]}]
|
||||
(l/trc :hint "marking for deletion" :rel "team" :id (str id)
|
||||
:deleted-at (dt/format-instant deleted-at))
|
||||
:deleted-at (ct/format-inst deleted-at))
|
||||
(db/update! conn :team
|
||||
{:deleted-at deleted-at}
|
||||
{:id id}
|
||||
@@ -101,7 +101,7 @@
|
||||
(defmethod delete-object :profile
|
||||
[{:keys [::db/conn] :as cfg} {:keys [id deleted-at]}]
|
||||
(l/trc :hint "marking for deletion" :rel "profile" :id (str id)
|
||||
:deleted-at (dt/format-instant deleted-at))
|
||||
:deleted-at (ct/format-inst deleted-at))
|
||||
|
||||
(db/update! conn :profile
|
||||
{:deleted-at deleted-at}
|
||||
|
||||
@@ -16,6 +16,7 @@
|
||||
[app.common.files.validate :as cfv]
|
||||
[app.common.logging :as l]
|
||||
[app.common.thumbnails :as thc]
|
||||
[app.common.time :as ct]
|
||||
[app.common.types.components-list :as ctkl]
|
||||
[app.common.types.file :as ctf]
|
||||
[app.common.types.shape-tree :as ctt]
|
||||
@@ -23,7 +24,6 @@
|
||||
[app.db :as db]
|
||||
[app.features.fdata :as feat.fdata]
|
||||
[app.storage :as sto]
|
||||
[app.util.time :as dt]
|
||||
[app.worker :as wrk]
|
||||
[integrant.core :as ig]))
|
||||
|
||||
@@ -282,7 +282,7 @@
|
||||
(defmethod ig/init-key ::handler
|
||||
[_ cfg]
|
||||
(fn [{:keys [props] :as task}]
|
||||
(let [min-age (dt/duration (or (:min-age props)
|
||||
(let [min-age (ct/duration (or (:min-age props)
|
||||
(cf/get-deletion-delay)))
|
||||
file-id (get props :file-id)
|
||||
cfg (-> cfg
|
||||
|
||||
@@ -8,9 +8,9 @@
|
||||
"A maintenance task that is responsible of properly scheduling the
|
||||
file-gc task for all files that matches the eligibility threshold."
|
||||
(:require
|
||||
[app.common.time :as ct]
|
||||
[app.config :as cf]
|
||||
[app.db :as db]
|
||||
[app.util.time :as dt]
|
||||
[app.worker :as wrk]
|
||||
[integrant.core :as ig]))
|
||||
|
||||
@@ -53,7 +53,7 @@
|
||||
(defmethod ig/init-key ::handler
|
||||
[_ cfg]
|
||||
(fn [{:keys [props] :as task}]
|
||||
(let [min-age (dt/duration (or (:min-age props) (::min-age cfg)))]
|
||||
(let [min-age (ct/duration (or (:min-age props) (::min-age cfg)))]
|
||||
(-> cfg
|
||||
(assoc ::db/rollback (:rollback? props))
|
||||
(assoc ::min-age min-age)
|
||||
|
||||
@@ -9,9 +9,9 @@
|
||||
of deleted or unreachable objects."
|
||||
(:require
|
||||
[app.common.logging :as l]
|
||||
[app.common.time :as ct]
|
||||
[app.db :as db]
|
||||
[app.storage :as sto]
|
||||
[app.util.time :as dt]
|
||||
[integrant.core :as ig]))
|
||||
|
||||
(def ^:private sql:get-profiles
|
||||
@@ -53,7 +53,7 @@
|
||||
(l/trc :hint "permanently delete"
|
||||
:rel "team"
|
||||
:id (str id)
|
||||
:deleted-at (dt/format-instant deleted-at))
|
||||
:deleted-at (ct/format-inst deleted-at))
|
||||
|
||||
;; Mark as deleted the storage object
|
||||
(some->> photo-id (sto/touch-object! storage))
|
||||
@@ -82,7 +82,7 @@
|
||||
:rel "team-font-variant"
|
||||
:id (str id)
|
||||
:team-id (str team-id)
|
||||
:deleted-at (dt/format-instant deleted-at))
|
||||
:deleted-at (ct/format-inst deleted-at))
|
||||
|
||||
;; Mark as deleted the all related storage objects
|
||||
(some->> (:woff1-file-id font) (sto/touch-object! storage))
|
||||
@@ -114,7 +114,7 @@
|
||||
:rel "project"
|
||||
:id (str id)
|
||||
:team-id (str team-id)
|
||||
:deleted-at (dt/format-instant deleted-at))
|
||||
:deleted-at (ct/format-inst deleted-at))
|
||||
|
||||
;; And finally, permanently delete the project.
|
||||
(db/delete! conn :project {:id id})
|
||||
@@ -140,7 +140,7 @@
|
||||
:rel "file"
|
||||
:id (str id)
|
||||
:project-id (str project-id)
|
||||
:deleted-at (dt/format-instant deleted-at))
|
||||
:deleted-at (ct/format-inst deleted-at))
|
||||
|
||||
(when (= "objects-storage" (:data-backend file))
|
||||
(sto/touch-object! storage (:data-ref-id file)))
|
||||
@@ -169,7 +169,7 @@
|
||||
:rel "file-thumbnail"
|
||||
:file-id (str file-id)
|
||||
:revn revn
|
||||
:deleted-at (dt/format-instant deleted-at))
|
||||
:deleted-at (ct/format-inst deleted-at))
|
||||
|
||||
;; Mark as deleted the storage object
|
||||
(some->> media-id (sto/touch-object! storage))
|
||||
@@ -198,7 +198,7 @@
|
||||
:rel "file-tagged-object-thumbnail"
|
||||
:file-id (str file-id)
|
||||
:object-id object-id
|
||||
:deleted-at (dt/format-instant deleted-at))
|
||||
:deleted-at (ct/format-inst deleted-at))
|
||||
|
||||
;; Mark as deleted the storage object
|
||||
(some->> media-id (sto/touch-object! storage))
|
||||
@@ -227,7 +227,7 @@
|
||||
:rel "file-data-fragment"
|
||||
:id (str id)
|
||||
:file-id (str file-id)
|
||||
:deleted-at (dt/format-instant deleted-at))
|
||||
:deleted-at (ct/format-inst deleted-at))
|
||||
|
||||
(some->> data-ref-id (sto/touch-object! storage))
|
||||
(db/delete! conn :file-data-fragment {:file-id file-id :id id})
|
||||
@@ -253,7 +253,7 @@
|
||||
:rel "file-media-object"
|
||||
:id (str id)
|
||||
:file-id (str file-id)
|
||||
:deleted-at (dt/format-instant deleted-at))
|
||||
:deleted-at (ct/format-inst deleted-at))
|
||||
|
||||
;; Mark as deleted the all related storage objects
|
||||
(some->> (:media-id fmo) (sto/touch-object! storage))
|
||||
@@ -282,7 +282,7 @@
|
||||
:rel "file-change"
|
||||
:id (str id)
|
||||
:file-id (str file-id)
|
||||
:deleted-at (dt/format-instant deleted-at))
|
||||
:deleted-at (ct/format-inst deleted-at))
|
||||
|
||||
(when (= "objects-storage" (:data-backend xlog))
|
||||
(sto/touch-object! storage (:data-ref-id xlog)))
|
||||
@@ -328,7 +328,7 @@
|
||||
(defmethod ig/init-key ::handler
|
||||
[_ cfg]
|
||||
(fn [{:keys [props] :as task}]
|
||||
(let [threshold (dt/duration (get props :deletion-threshold 0))
|
||||
(let [threshold (ct/duration (get props :deletion-threshold 0))
|
||||
cfg (assoc cfg ::deletion-threshold (db/interval threshold))]
|
||||
(loop [procs (map deref deletion-proc-vars)
|
||||
total 0]
|
||||
|
||||
@@ -10,8 +10,8 @@
|
||||
[app.common.data :as d]
|
||||
[app.common.data.macros :as dm]
|
||||
[app.common.exceptions :as ex]
|
||||
[app.common.time :as ct]
|
||||
[app.common.transit :as t]
|
||||
[app.util.time :as dt]
|
||||
[buddy.sign.jwe :as jwe]))
|
||||
|
||||
(defn generate
|
||||
@@ -22,7 +22,7 @@
|
||||
(bytes? tokens-key))
|
||||
|
||||
(let [payload (-> claims
|
||||
(assoc :iat (dt/now))
|
||||
(assoc :iat (ct/now))
|
||||
(d/without-nils)
|
||||
(t/encode))]
|
||||
(jwe/encrypt payload tokens-key {:alg :a256kw :enc :a256gcm})))
|
||||
@@ -35,8 +35,8 @@
|
||||
(defn verify
|
||||
[sprops {:keys [token] :as params}]
|
||||
(let [claims (decode sprops token)]
|
||||
(when (and (dt/instant? (:exp claims))
|
||||
(dt/is-before? (:exp claims) (dt/now)))
|
||||
(when (and (ct/inst? (:exp claims))
|
||||
(ct/is-before? (:exp claims) (ct/now)))
|
||||
(ex/raise :type :validation
|
||||
:code :invalid-token
|
||||
:reason :token-expired
|
||||
|
||||
@@ -9,7 +9,7 @@
|
||||
(:refer-clojure :exclude [get])
|
||||
(:require
|
||||
[app.common.schema :as sm]
|
||||
[app.util.time :as dt]
|
||||
[app.common.time :as ct]
|
||||
[promesa.exec :as px])
|
||||
(:import
|
||||
com.github.benmanes.caffeine.cache.AsyncCache
|
||||
@@ -51,7 +51,7 @@
|
||||
(let [cache (as-> (Caffeine/newBuilder) builder
|
||||
(if (fn? on-remove) (.removalListener builder (create-listener on-remove)) builder)
|
||||
(if executor (.executor builder ^Executor (px/resolve-executor executor)) builder)
|
||||
(if keepalive (.expireAfterAccess builder ^Duration (dt/duration keepalive)) builder)
|
||||
(if keepalive (.expireAfterAccess builder ^Duration (ct/duration keepalive)) builder)
|
||||
(if (int? max-size) (.maximumSize builder (long max-size)) builder)
|
||||
(.recordStats builder)
|
||||
(.buildAsync builder))
|
||||
|
||||
138
backend/src/app/util/cron.clj
Normal file
138
backend/src/app/util/cron.clj
Normal file
@@ -0,0 +1,138 @@
|
||||
;; 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.util.cron
|
||||
(:require
|
||||
[app.common.exceptions :as ex])
|
||||
(:import
|
||||
java.time.Instant
|
||||
java.util.Date
|
||||
org.apache.logging.log4j.core.util.CronExpression))
|
||||
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
;; Cron Expression
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
|
||||
;; Cron expressions are comprised of 6 required fields and one
|
||||
;; optional field separated by white space. The fields respectively
|
||||
;; are described as follows:
|
||||
;;
|
||||
;; Field Name Allowed Values Allowed Special Characters
|
||||
;; Seconds 0-59 , - * /
|
||||
;; Minutes 0-59 , - * /
|
||||
;; Hours 0-23 , - * /
|
||||
;; Day-of-month 1-31 , - * ? / L W
|
||||
;; Month 0-11 or JAN-DEC , - * /
|
||||
;; Day-of-Week 1-7 or SUN-SAT , - * ? / L #
|
||||
;; Year (Optional) empty, 1970-2199 , - * /
|
||||
;;
|
||||
;; The '*' character is used to specify all values. For example, "*"
|
||||
;; in the minute field means "every minute".
|
||||
;;
|
||||
;; The '?' character is allowed for the day-of-month and day-of-week
|
||||
;; fields. It is used to specify 'no specific value'. This is useful
|
||||
;; when you need to specify something in one of the two fields, but
|
||||
;; not the other.
|
||||
;;
|
||||
;; The '-' character is used to specify ranges For example "10-12" in
|
||||
;; the hour field means "the hours 10, 11 and 12".
|
||||
;;
|
||||
;; The ',' character is used to specify additional values. For
|
||||
;; example "MON,WED,FRI" in the day-of-week field means "the days
|
||||
;; Monday, Wednesday, and Friday".
|
||||
;;
|
||||
;; The '/' character is used to specify increments. For example "0/15"
|
||||
;; in the seconds field means "the seconds 0, 15, 30, and
|
||||
;; 45". And "5/15" in the seconds field means "the seconds 5, 20, 35,
|
||||
;; and 50". Specifying '*' before the '/' is equivalent to specifying
|
||||
;; 0 is the value to start with. Essentially, for each field in the
|
||||
;; expression, there is a set of numbers that can be turned on or
|
||||
;; off. For seconds and minutes, the numbers range from 0 to 59. For
|
||||
;; hours 0 to 23, for days of the month 0 to 31, and for months 0 to
|
||||
;; 11 (JAN to DEC). The "/" character simply helps you turn on
|
||||
;; every "nth" value in the given set. Thus "7/6" in the month field
|
||||
;; only turns on month "7", it does NOT mean every 6th month, please
|
||||
;; note that subtlety.
|
||||
;;
|
||||
;; The 'L' character is allowed for the day-of-month and day-of-week
|
||||
;; fields. This character is short-hand for "last", but it has
|
||||
;; different meaning in each of the two fields. For example, the
|
||||
;; value "L" in the day-of-month field means "the last day of the
|
||||
;; month" - day 31 for January, day 28 for February on non-leap
|
||||
;; years. If used in the day-of-week field by itself, it simply
|
||||
;; means "7" or "SAT". But if used in the day-of-week field after
|
||||
;; another value, it means "the last xxx day of the month" - for
|
||||
;; example "6L" means "the last friday of the month". You can also
|
||||
;; specify an offset from the last day of the month, such as "L-3"
|
||||
;; which would mean the third-to-last day of the calendar month. When
|
||||
;; using the 'L' option, it is important not to specify lists, or
|
||||
;; ranges of values, as you'll get confusing/unexpected results.
|
||||
;;
|
||||
;; The 'W' character is allowed for the day-of-month field. This
|
||||
;; character is used to specify the weekday (Monday-Friday) nearest
|
||||
;; the given day. As an example, if you were to specify "15W" as the
|
||||
;; value for the day-of-month field, the meaning is: "the nearest
|
||||
;; weekday to the 15th of the month". So if the 15th is a Saturday,
|
||||
;; the trigger will fire on Friday the 14th. If the 15th is a Sunday,
|
||||
;; the trigger will fire on Monday the 16th. If the 15th is a Tuesday,
|
||||
;; then it will fire on Tuesday the 15th. However if you specify "1W"
|
||||
;; as the value for day-of-month, and the 1st is a Saturday, the
|
||||
;; trigger will fire on Monday the 3rd, as it will not 'jump' over the
|
||||
;; boundary of a month's days. The 'W' character can only be specified
|
||||
;; when the day-of-month is a single day, not a range or list of days.
|
||||
;;
|
||||
;; The 'L' and 'W' characters can also be combined for the
|
||||
;; day-of-month expression to yield 'LW', which translates to "last
|
||||
;; weekday of the month".
|
||||
;;
|
||||
;; The '#' character is allowed for the day-of-week field. This
|
||||
;; character is used to specify "the nth" XXX day of the month. For
|
||||
;; example, the value of "6#3" in the day-of-week field means the
|
||||
;; third Friday of the month (day 6 = Friday and "#3" = the 3rd one in
|
||||
;; the month). Other examples: "2#1" = the first Monday of the month
|
||||
;; and "4#5" = the fifth Wednesday of the month. Note that if you
|
||||
;; specify "#5" and there is not 5 of the given day-of-week in the
|
||||
;; month, then no firing will occur that month. If the '#' character
|
||||
;; is used, there can only be one expression in the day-of-week
|
||||
;; field ("3#1,6#3" is not valid, since there are two expressions).
|
||||
;;
|
||||
;; The legal characters and the names of months and days of the week
|
||||
;; are not case sensitive.
|
||||
|
||||
(defn cron
|
||||
"Creates an instance of CronExpression from string."
|
||||
[s]
|
||||
(try
|
||||
(CronExpression. s)
|
||||
(catch java.text.ParseException e
|
||||
(ex/raise :type :parse
|
||||
:code :invalid-cron-expression
|
||||
:cause e
|
||||
:context {:expr s}))))
|
||||
|
||||
(defn cron-expr?
|
||||
[v]
|
||||
(instance? CronExpression v))
|
||||
|
||||
(defn next-valid-instant-from
|
||||
[^CronExpression cron ^Instant now]
|
||||
(assert (cron-expr? cron))
|
||||
(.toInstant (.getNextValidTimeAfter cron (Date/from now))))
|
||||
|
||||
(defn get-next
|
||||
[cron tnow]
|
||||
(let [nt (next-valid-instant-from cron tnow)]
|
||||
(cons nt (lazy-seq (get-next cron nt)))))
|
||||
|
||||
(defmethod print-method CronExpression
|
||||
[o w]
|
||||
(print-dup o w))
|
||||
|
||||
(defmethod print-dup CronExpression
|
||||
[mv ^java.io.Writer writer]
|
||||
;; Do not delete this comment
|
||||
;; (print-ctor o (fn [o w] (print-dup (.toString ^CronExpression o) w)) w)
|
||||
(.write writer (str "#penpot/cron \"" (.toString ^CronExpression mv) "\"")))
|
||||
@@ -37,9 +37,9 @@
|
||||
|
||||
(:require
|
||||
[app.common.fressian :as fres]
|
||||
[app.common.time :as ct]
|
||||
[app.common.transit :as t]
|
||||
[app.common.uuid :as uuid]
|
||||
[app.util.time :as dt]
|
||||
[clojure.core :as c]
|
||||
[clojure.data.json :as json])
|
||||
(:import
|
||||
@@ -104,7 +104,7 @@
|
||||
|
||||
(clone [this]
|
||||
(when-not loaded? (load! this))
|
||||
(let [mdata (assoc mdata :created-at (dt/now))
|
||||
(let [mdata (assoc mdata :created-at (ct/now))
|
||||
id (uuid/next)
|
||||
pmap (PointerMap. id
|
||||
mdata
|
||||
@@ -179,7 +179,7 @@
|
||||
(let [odata' (assoc odata key val)]
|
||||
(if (identical? odata odata')
|
||||
this
|
||||
(let [mdata (assoc mdata :created-at (dt/now))
|
||||
(let [mdata (assoc mdata :created-at (ct/now))
|
||||
id (if modified? id (uuid/next))
|
||||
pmap (PointerMap. id
|
||||
mdata
|
||||
@@ -197,7 +197,7 @@
|
||||
(let [odata' (dissoc odata key)]
|
||||
(if (identical? odata odata')
|
||||
this
|
||||
(let [mdata (assoc mdata :created-at (dt/now))
|
||||
(let [mdata (assoc mdata :created-at (ct/now))
|
||||
id (if modified? id (uuid/next))
|
||||
pmap (PointerMap. id
|
||||
mdata
|
||||
@@ -220,7 +220,7 @@
|
||||
(defn create
|
||||
([]
|
||||
(let [id (uuid/next)
|
||||
mdata (assoc *metadata* :created-at (dt/now))
|
||||
mdata (assoc *metadata* :created-at (ct/now))
|
||||
pmap (PointerMap. id mdata {} true true)]
|
||||
(some-> *tracked* (swap! assoc id pmap))
|
||||
pmap))
|
||||
@@ -239,7 +239,7 @@
|
||||
(do
|
||||
(some-> *tracked* (swap! assoc (get-id data) data))
|
||||
data)
|
||||
(let [mdata (assoc (meta data) :created-at (dt/now))
|
||||
(let [mdata (assoc (meta data) :created-at (ct/now))
|
||||
id (uuid/next)
|
||||
pmap (PointerMap. id
|
||||
mdata
|
||||
|
||||
@@ -1,399 +0,0 @@
|
||||
;; 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.util.time
|
||||
(:require
|
||||
[app.common.data.macros :as dm]
|
||||
[app.common.exceptions :as ex]
|
||||
[app.common.schema :as sm]
|
||||
[app.common.schema.openapi :as-alias oapi]
|
||||
[app.common.time :as common-time]
|
||||
[clojure.spec.alpha :as s]
|
||||
[clojure.test.check.generators :as tgen]
|
||||
[cuerdas.core :as str]
|
||||
[fipp.ednize :as fez])
|
||||
(:import
|
||||
java.nio.file.attribute.FileTime
|
||||
java.time.Duration
|
||||
java.time.Instant
|
||||
java.time.OffsetDateTime
|
||||
java.time.ZoneId
|
||||
java.time.ZonedDateTime
|
||||
java.time.format.DateTimeFormatter
|
||||
java.time.temporal.ChronoUnit
|
||||
java.time.temporal.Temporal
|
||||
java.time.temporal.TemporalAmount
|
||||
java.time.temporal.TemporalUnit
|
||||
java.util.Date
|
||||
org.apache.logging.log4j.core.util.CronExpression))
|
||||
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
;; Instant & Duration
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
|
||||
(defn temporal-unit
|
||||
[o]
|
||||
(if (instance? TemporalUnit o)
|
||||
o
|
||||
(case o
|
||||
:nanos ChronoUnit/NANOS
|
||||
:millis ChronoUnit/MILLIS
|
||||
:micros ChronoUnit/MICROS
|
||||
:seconds ChronoUnit/SECONDS
|
||||
:minutes ChronoUnit/MINUTES
|
||||
:hours ChronoUnit/HOURS
|
||||
:days ChronoUnit/DAYS)))
|
||||
|
||||
;; --- DURATION
|
||||
|
||||
(defn- obj->duration
|
||||
[params]
|
||||
(reduce-kv (fn [o k v]
|
||||
(.plus ^Duration o ^long v ^TemporalUnit (temporal-unit k)))
|
||||
(Duration/ofMillis 0)
|
||||
params))
|
||||
|
||||
(defn duration?
|
||||
[v]
|
||||
(instance? Duration v))
|
||||
|
||||
(defn duration
|
||||
[ms-or-obj]
|
||||
(cond
|
||||
(string? ms-or-obj)
|
||||
(Duration/parse (str "PT" ms-or-obj))
|
||||
|
||||
(duration? ms-or-obj)
|
||||
ms-or-obj
|
||||
|
||||
(integer? ms-or-obj)
|
||||
(Duration/ofMillis ms-or-obj)
|
||||
|
||||
:else
|
||||
(obj->duration ms-or-obj)))
|
||||
|
||||
(defn ->seconds
|
||||
[d]
|
||||
(-> d inst-ms (/ 1000) int))
|
||||
|
||||
(defn diff
|
||||
[t1 t2]
|
||||
(Duration/between t1 t2))
|
||||
|
||||
(defn truncate
|
||||
[o unit]
|
||||
(let [unit (temporal-unit unit)]
|
||||
(cond
|
||||
(instance? Instant o)
|
||||
(.truncatedTo ^Instant o ^TemporalUnit unit)
|
||||
|
||||
(instance? Duration o)
|
||||
(.truncatedTo ^Duration o ^TemporalUnit unit)
|
||||
|
||||
:else
|
||||
(throw (IllegalArgumentException. "only instant and duration allowed")))))
|
||||
|
||||
(s/def ::duration
|
||||
(s/conformer
|
||||
(fn [v]
|
||||
(cond
|
||||
(duration? v) v
|
||||
|
||||
(string? v)
|
||||
(try
|
||||
(duration v)
|
||||
(catch java.time.format.DateTimeParseException _e
|
||||
::s/invalid))
|
||||
|
||||
:else
|
||||
::s/invalid))
|
||||
(fn [v]
|
||||
(subs (str v) 2))))
|
||||
|
||||
(extend-protocol clojure.core/Inst
|
||||
java.time.Duration
|
||||
(inst-ms* [v] (.toMillis ^Duration v))
|
||||
|
||||
OffsetDateTime
|
||||
(inst-ms* [v] (.toEpochMilli (.toInstant ^OffsetDateTime v)))
|
||||
|
||||
FileTime
|
||||
(inst-ms* [v] (.toMillis ^FileTime v)))
|
||||
|
||||
(defmethod print-method Duration
|
||||
[mv ^java.io.Writer writer]
|
||||
(.write writer (str "#app/duration \"" (str/lower (subs (str mv) 2)) "\"")))
|
||||
|
||||
(defmethod print-dup Duration [o w]
|
||||
(print-method o w))
|
||||
|
||||
(extend-protocol fez/IEdn
|
||||
Duration
|
||||
(-edn [o]
|
||||
(tagged-literal 'app/duration (str o))))
|
||||
|
||||
(defn format-duration
|
||||
[o]
|
||||
(str/lower (subs (str o) 2)))
|
||||
|
||||
;; --- INSTANT
|
||||
|
||||
(defn instant?
|
||||
[v]
|
||||
(instance? Instant v))
|
||||
|
||||
(defn instant
|
||||
([s]
|
||||
(cond
|
||||
(instant? s) s
|
||||
(int? s) (Instant/ofEpochMilli s)
|
||||
:else (Instant/parse s)))
|
||||
([s fmt]
|
||||
(case fmt
|
||||
:rfc1123 (Instant/from (.parse DateTimeFormatter/RFC_1123_DATE_TIME ^String s))
|
||||
:iso (Instant/from (.parse DateTimeFormatter/ISO_INSTANT ^String s))
|
||||
:iso8601 (Instant/from (.parse DateTimeFormatter/ISO_INSTANT ^String s)))))
|
||||
|
||||
(defn is-after?
|
||||
"Analgous to: da > db"
|
||||
[da db]
|
||||
(.isAfter ^Instant da ^Instant db))
|
||||
|
||||
(defn is-before?
|
||||
[da db]
|
||||
(.isBefore ^Instant da ^Instant db))
|
||||
|
||||
(defn plus
|
||||
[d ta]
|
||||
(let [^TemporalAmount ta (duration ta)]
|
||||
(cond
|
||||
(instance? Duration d)
|
||||
(.plus ^Duration d ta)
|
||||
|
||||
(instance? Temporal d)
|
||||
(.plus ^Temporal d ta)
|
||||
|
||||
:else
|
||||
(throw (UnsupportedOperationException. "unsupported type")))))
|
||||
|
||||
(defn minus
|
||||
[d ta]
|
||||
(let [^TemporalAmount ta (duration ta)]
|
||||
(cond
|
||||
(instance? Duration d)
|
||||
(.minus ^Duration d ta)
|
||||
|
||||
(instance? Temporal d)
|
||||
(.minus ^Temporal d ta)
|
||||
|
||||
:else
|
||||
(throw (UnsupportedOperationException. "unsupported type")))))
|
||||
|
||||
(dm/export common-time/now)
|
||||
|
||||
(defn in-future
|
||||
[v]
|
||||
(plus (now) v))
|
||||
|
||||
(defn in-past
|
||||
[v]
|
||||
(minus (now) v))
|
||||
|
||||
(defn instant->zoned-date-time
|
||||
[v]
|
||||
(ZonedDateTime/ofInstant v (ZoneId/of "UTC")))
|
||||
|
||||
(defn format-instant
|
||||
([v] (.format DateTimeFormatter/ISO_INSTANT ^Instant v))
|
||||
([v fmt]
|
||||
(case fmt
|
||||
:iso
|
||||
(.format DateTimeFormatter/ISO_INSTANT ^Instant v)
|
||||
|
||||
:iso-local-time
|
||||
(.format DateTimeFormatter/ISO_LOCAL_TIME
|
||||
^ZonedDateTime (instant->zoned-date-time v))
|
||||
|
||||
:rfc1123
|
||||
(.format DateTimeFormatter/RFC_1123_DATE_TIME
|
||||
^ZonedDateTime (instant->zoned-date-time v)))))
|
||||
|
||||
(defmethod print-method Instant
|
||||
[mv ^java.io.Writer writer]
|
||||
(.write writer (str "#app/instant \"" (format-instant mv) "\"")))
|
||||
|
||||
(defmethod print-dup Instant [o w]
|
||||
(print-method o w))
|
||||
|
||||
(extend-protocol fez/IEdn
|
||||
Instant
|
||||
(-edn [o] (tagged-literal 'app/instant (format-instant o))))
|
||||
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
;; Cron Expression
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
|
||||
;; Cron expressions are comprised of 6 required fields and one
|
||||
;; optional field separated by white space. The fields respectively
|
||||
;; are described as follows:
|
||||
;;
|
||||
;; Field Name Allowed Values Allowed Special Characters
|
||||
;; Seconds 0-59 , - * /
|
||||
;; Minutes 0-59 , - * /
|
||||
;; Hours 0-23 , - * /
|
||||
;; Day-of-month 1-31 , - * ? / L W
|
||||
;; Month 0-11 or JAN-DEC , - * /
|
||||
;; Day-of-Week 1-7 or SUN-SAT , - * ? / L #
|
||||
;; Year (Optional) empty, 1970-2199 , - * /
|
||||
;;
|
||||
;; The '*' character is used to specify all values. For example, "*"
|
||||
;; in the minute field means "every minute".
|
||||
;;
|
||||
;; The '?' character is allowed for the day-of-month and day-of-week
|
||||
;; fields. It is used to specify 'no specific value'. This is useful
|
||||
;; when you need to specify something in one of the two fields, but
|
||||
;; not the other.
|
||||
;;
|
||||
;; The '-' character is used to specify ranges For example "10-12" in
|
||||
;; the hour field means "the hours 10, 11 and 12".
|
||||
;;
|
||||
;; The ',' character is used to specify additional values. For
|
||||
;; example "MON,WED,FRI" in the day-of-week field means "the days
|
||||
;; Monday, Wednesday, and Friday".
|
||||
;;
|
||||
;; The '/' character is used to specify increments. For example "0/15"
|
||||
;; in the seconds field means "the seconds 0, 15, 30, and
|
||||
;; 45". And "5/15" in the seconds field means "the seconds 5, 20, 35,
|
||||
;; and 50". Specifying '*' before the '/' is equivalent to specifying
|
||||
;; 0 is the value to start with. Essentially, for each field in the
|
||||
;; expression, there is a set of numbers that can be turned on or
|
||||
;; off. For seconds and minutes, the numbers range from 0 to 59. For
|
||||
;; hours 0 to 23, for days of the month 0 to 31, and for months 0 to
|
||||
;; 11 (JAN to DEC). The "/" character simply helps you turn on
|
||||
;; every "nth" value in the given set. Thus "7/6" in the month field
|
||||
;; only turns on month "7", it does NOT mean every 6th month, please
|
||||
;; note that subtlety.
|
||||
;;
|
||||
;; The 'L' character is allowed for the day-of-month and day-of-week
|
||||
;; fields. This character is short-hand for "last", but it has
|
||||
;; different meaning in each of the two fields. For example, the
|
||||
;; value "L" in the day-of-month field means "the last day of the
|
||||
;; month" - day 31 for January, day 28 for February on non-leap
|
||||
;; years. If used in the day-of-week field by itself, it simply
|
||||
;; means "7" or "SAT". But if used in the day-of-week field after
|
||||
;; another value, it means "the last xxx day of the month" - for
|
||||
;; example "6L" means "the last friday of the month". You can also
|
||||
;; specify an offset from the last day of the month, such as "L-3"
|
||||
;; which would mean the third-to-last day of the calendar month. When
|
||||
;; using the 'L' option, it is important not to specify lists, or
|
||||
;; ranges of values, as you'll get confusing/unexpected results.
|
||||
;;
|
||||
;; The 'W' character is allowed for the day-of-month field. This
|
||||
;; character is used to specify the weekday (Monday-Friday) nearest
|
||||
;; the given day. As an example, if you were to specify "15W" as the
|
||||
;; value for the day-of-month field, the meaning is: "the nearest
|
||||
;; weekday to the 15th of the month". So if the 15th is a Saturday,
|
||||
;; the trigger will fire on Friday the 14th. If the 15th is a Sunday,
|
||||
;; the trigger will fire on Monday the 16th. If the 15th is a Tuesday,
|
||||
;; then it will fire on Tuesday the 15th. However if you specify "1W"
|
||||
;; as the value for day-of-month, and the 1st is a Saturday, the
|
||||
;; trigger will fire on Monday the 3rd, as it will not 'jump' over the
|
||||
;; boundary of a month's days. The 'W' character can only be specified
|
||||
;; when the day-of-month is a single day, not a range or list of days.
|
||||
;;
|
||||
;; The 'L' and 'W' characters can also be combined for the
|
||||
;; day-of-month expression to yield 'LW', which translates to "last
|
||||
;; weekday of the month".
|
||||
;;
|
||||
;; The '#' character is allowed for the day-of-week field. This
|
||||
;; character is used to specify "the nth" XXX day of the month. For
|
||||
;; example, the value of "6#3" in the day-of-week field means the
|
||||
;; third Friday of the month (day 6 = Friday and "#3" = the 3rd one in
|
||||
;; the month). Other examples: "2#1" = the first Monday of the month
|
||||
;; and "4#5" = the fifth Wednesday of the month. Note that if you
|
||||
;; specify "#5" and there is not 5 of the given day-of-week in the
|
||||
;; month, then no firing will occur that month. If the '#' character
|
||||
;; is used, there can only be one expression in the day-of-week
|
||||
;; field ("3#1,6#3" is not valid, since there are two expressions).
|
||||
;;
|
||||
;; The legal characters and the names of months and days of the week
|
||||
;; are not case sensitive.
|
||||
|
||||
(defn cron
|
||||
"Creates an instance of CronExpression from string."
|
||||
[s]
|
||||
(try
|
||||
(CronExpression. s)
|
||||
(catch java.text.ParseException e
|
||||
(ex/raise :type :parse
|
||||
:code :invalid-cron-expression
|
||||
:cause e
|
||||
:context {:expr s}))))
|
||||
|
||||
(defn cron?
|
||||
[v]
|
||||
(instance? CronExpression v))
|
||||
|
||||
(defn next-valid-instant-from
|
||||
[^CronExpression cron ^Instant now]
|
||||
(s/assert cron? cron)
|
||||
(.toInstant (.getNextValidTimeAfter cron (Date/from now))))
|
||||
|
||||
(defn get-next
|
||||
[cron tnow]
|
||||
(let [nt (next-valid-instant-from cron tnow)]
|
||||
(cons nt (lazy-seq (get-next cron nt)))))
|
||||
|
||||
(defmethod print-method CronExpression
|
||||
[mv ^java.io.Writer writer]
|
||||
(.write writer (str "#app/cron \"" (.toString ^CronExpression mv) "\"")))
|
||||
|
||||
(defmethod print-dup CronExpression
|
||||
[o w]
|
||||
(print-ctor o (fn [o w] (print-dup (.toString ^CronExpression o) w)) w))
|
||||
|
||||
(extend-protocol fez/IEdn
|
||||
CronExpression
|
||||
(-edn [o] (pr-str o)))
|
||||
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
;; Measurement Helpers
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
|
||||
(defn tpoint
|
||||
"Create a measurement checkpoint for time measurement of potentially
|
||||
asynchronous flow."
|
||||
[]
|
||||
(let [p1 (System/nanoTime)]
|
||||
#(duration {:nanos (- (System/nanoTime) p1)})))
|
||||
|
||||
(sm/register!
|
||||
{:type ::instant
|
||||
:pred instant?
|
||||
:type-properties
|
||||
{:error/message "should be an instant"
|
||||
:title "instant"
|
||||
:decode/string instant
|
||||
:encode/string format-instant
|
||||
:decode/json instant
|
||||
:encode/json format-instant
|
||||
:gen/gen (tgen/fmap (fn [i] (in-past i)) tgen/pos-int)
|
||||
::oapi/type "string"
|
||||
::oapi/format "iso"}})
|
||||
|
||||
(sm/register!
|
||||
{:type ::duration
|
||||
:pred duration?
|
||||
:type-properties
|
||||
{:error/message "should be a duration"
|
||||
:gen/gen (tgen/fmap duration tgen/pos-int)
|
||||
:title "duration"
|
||||
:decode/string duration
|
||||
:encode/string format-duration
|
||||
:decode/json duration
|
||||
:encode/json format-duration
|
||||
::oapi/type "string"
|
||||
::oapi/format "duration"}})
|
||||
@@ -9,10 +9,10 @@
|
||||
(:require
|
||||
[app.common.exceptions :as ex]
|
||||
[app.common.logging :as l]
|
||||
[app.common.time :as ct]
|
||||
[app.common.transit :as t]
|
||||
[app.common.uuid :as uuid]
|
||||
[app.util.inet :as inet]
|
||||
[app.util.time :as dt]
|
||||
[promesa.exec :as px]
|
||||
[promesa.exec.csp :as sp]
|
||||
[promesa.util :as pu]
|
||||
@@ -93,7 +93,7 @@
|
||||
(assoc ::id id)
|
||||
(assoc ::state state)
|
||||
(assoc ::beats beats)
|
||||
(assoc ::created-at (dt/now))
|
||||
(assoc ::created-at (ct/now))
|
||||
(assoc ::input-ch input-ch)
|
||||
(assoc ::heartbeat-ch hbeat-ch)
|
||||
(assoc ::output-ch output-ch)
|
||||
@@ -107,7 +107,7 @@
|
||||
(let [options (-> options
|
||||
(assoc ::channel channel)
|
||||
(on-connect))
|
||||
timeout (dt/duration idle-timeout)]
|
||||
timeout (ct/duration idle-timeout)]
|
||||
|
||||
(yws/set-idle-timeout! channel timeout)
|
||||
(px/submit! :vthread (partial start-io-loop! options))))
|
||||
@@ -128,7 +128,7 @@
|
||||
(fn on-message [_channel message]
|
||||
(when (string? message)
|
||||
(sp/offer! input-ch message)
|
||||
(swap! state assoc ::last-activity-at (dt/now))))
|
||||
(swap! state assoc ::last-activity-at (ct/now))))
|
||||
|
||||
:on-pong
|
||||
(fn on-pong [_channel data]
|
||||
|
||||
@@ -10,11 +10,11 @@
|
||||
[app.common.data :as d]
|
||||
[app.common.logging :as l]
|
||||
[app.common.schema :as sm]
|
||||
[app.common.time :as ct]
|
||||
[app.common.uuid :as uuid]
|
||||
[app.config :as cf]
|
||||
[app.db :as db]
|
||||
[app.metrics :as mtx]
|
||||
[app.util.time :as dt]
|
||||
[cuerdas.core :as str]
|
||||
[integrant.core :as ig]))
|
||||
|
||||
@@ -31,7 +31,7 @@
|
||||
[f metrics tname]
|
||||
(let [labels (into-array String [tname])]
|
||||
(fn [params]
|
||||
(let [tp (dt/tpoint)]
|
||||
(let [tp (ct/tpoint)]
|
||||
(try
|
||||
(f params)
|
||||
(finally
|
||||
@@ -95,7 +95,7 @@
|
||||
[::task [:or ::sm/text :keyword]]
|
||||
[::label {:optional true} ::sm/text]
|
||||
[::delay {:optional true}
|
||||
[:or ::sm/int ::dt/duration]]
|
||||
[:or ::sm/int ::ct/duration]]
|
||||
[::queue {:optional true} [:or ::sm/text :keyword]]
|
||||
[::priority {:optional true} ::sm/int]
|
||||
[::max-retries {:optional true} ::sm/int]
|
||||
@@ -111,7 +111,7 @@
|
||||
|
||||
(check-options! options)
|
||||
|
||||
(let [duration (dt/duration delay)
|
||||
(let [duration (ct/duration delay)
|
||||
interval (db/interval duration)
|
||||
props (db/tjson params)
|
||||
id (uuid/next)
|
||||
@@ -129,7 +129,7 @@
|
||||
:queue queue
|
||||
:label label
|
||||
:dedupe (boolean dedupe)
|
||||
:delay (dt/format-duration duration)
|
||||
:delay (ct/format-duration duration)
|
||||
:replace (or deleted 0))
|
||||
|
||||
(db/exec-one! conn [sql:insert-new-task id task props queue
|
||||
|
||||
@@ -10,8 +10,9 @@
|
||||
[app.common.exceptions :as ex]
|
||||
[app.common.logging :as l]
|
||||
[app.common.schema :as sm]
|
||||
[app.common.time :as ct]
|
||||
[app.db :as db]
|
||||
[app.util.time :as dt]
|
||||
[app.util.cron :as cron]
|
||||
[app.worker :as wrk]
|
||||
[app.worker.runner :refer [get-error-context]]
|
||||
[cuerdas.core :as str]
|
||||
@@ -49,7 +50,7 @@
|
||||
[cfg {:keys [id cron] :as task}]
|
||||
(px/thread
|
||||
{:name (str "penpot/cron-task/" id)}
|
||||
(let [tpoint (dt/tpoint)]
|
||||
(let [tpoint (ct/tpoint)]
|
||||
(try
|
||||
(db/tx-run! cfg (fn [{:keys [::db/conn]}]
|
||||
(db/exec-one! conn ["SET LOCAL statement_timeout=0;"])
|
||||
@@ -57,20 +58,20 @@
|
||||
(when (lock-scheduled-task! conn id)
|
||||
(db/update! conn :scheduled-task
|
||||
{:cron-expr (str cron)
|
||||
:modified-at (dt/now)}
|
||||
:modified-at (ct/now)}
|
||||
{:id id}
|
||||
{::db/return-keys false})
|
||||
(l/dbg :hint "start" :id id)
|
||||
((:fn task) task)
|
||||
(let [elapsed (dt/format-duration (tpoint))]
|
||||
(let [elapsed (ct/format-duration (tpoint))]
|
||||
(l/dbg :hint "end" :id id :elapsed elapsed)))))
|
||||
|
||||
(catch InterruptedException _
|
||||
(let [elapsed (dt/format-duration (tpoint))]
|
||||
(let [elapsed (ct/format-duration (tpoint))]
|
||||
(l/debug :hint "task interrupted" :id id :elapsed elapsed)))
|
||||
|
||||
(catch Throwable cause
|
||||
(let [elapsed (dt/format-duration (tpoint))]
|
||||
(let [elapsed (ct/format-duration (tpoint))]
|
||||
(binding [l/*context* (get-error-context cause task)]
|
||||
(l/err :hint "unhandled exception on running task"
|
||||
:id id
|
||||
@@ -82,10 +83,10 @@
|
||||
|
||||
(defn- ms-until-valid
|
||||
[cron]
|
||||
(assert (dt/cron? cron) "expected cron instance")
|
||||
(let [now (dt/now)
|
||||
next (dt/next-valid-instant-from cron now)]
|
||||
(dt/diff now next)))
|
||||
(assert (cron/cron-expr? cron) "expected cron instance")
|
||||
(let [now (ct/now)
|
||||
next (cron/next-valid-instant-from cron now)]
|
||||
(ct/diff now next)))
|
||||
|
||||
(defn- schedule-cron-task
|
||||
[{:keys [::running] :as cfg} {:keys [cron id] :as task}]
|
||||
@@ -93,8 +94,8 @@
|
||||
ft (px/schedule! ts (partial execute-cron-task cfg task))]
|
||||
|
||||
(l/dbg :hint "schedule" :id id
|
||||
:ts (dt/format-duration ts)
|
||||
:at (dt/format-instant (dt/in-future ts)))
|
||||
:ts (ct/format-duration ts)
|
||||
:at (ct/format-inst (ct/in-future ts)))
|
||||
|
||||
(swap! running #(into #{ft} (filter p/pending?) %))))
|
||||
|
||||
@@ -104,7 +105,7 @@
|
||||
[:vector
|
||||
[:maybe
|
||||
[:map
|
||||
[:cron [:fn dt/cron?]]
|
||||
[:cron [:fn cron/cron-expr?]]
|
||||
[:task :keyword]
|
||||
[:props {:optional true} :map]
|
||||
[:id {:optional true} :keyword]]]]]
|
||||
|
||||
@@ -10,11 +10,11 @@
|
||||
[app.common.data.macros :as dm]
|
||||
[app.common.logging :as l]
|
||||
[app.common.schema :as sm]
|
||||
[app.common.time :as ct]
|
||||
[app.common.transit :as t]
|
||||
[app.db :as db]
|
||||
[app.metrics :as mtx]
|
||||
[app.redis :as rds]
|
||||
[app.util.time :as dt]
|
||||
[app.worker :as-alias wrk]
|
||||
[cuerdas.core :as str]
|
||||
[integrant.core :as ig]
|
||||
@@ -32,9 +32,9 @@
|
||||
(defmethod ig/expand-key ::wrk/dispatcher
|
||||
[k v]
|
||||
{k (-> (d/without-nils v)
|
||||
(assoc ::timeout (dt/duration "10s"))
|
||||
(assoc ::timeout (ct/duration "10s"))
|
||||
(assoc ::batch-size 100)
|
||||
(assoc ::wait-duration (dt/duration "5s")))})
|
||||
(assoc ::wait-duration (ct/duration "5s")))})
|
||||
|
||||
(defmethod ig/assert-key ::wrk/dispatcher
|
||||
[_ cfg]
|
||||
|
||||
@@ -10,8 +10,8 @@
|
||||
[app.common.data :as d]
|
||||
[app.common.logging :as l]
|
||||
[app.common.schema :as sm]
|
||||
[app.common.time :as ct]
|
||||
[app.metrics :as mtx]
|
||||
[app.util.time :as dt]
|
||||
[app.worker :as-alias wrk]
|
||||
[integrant.core :as ig]
|
||||
[promesa.exec :as px])
|
||||
@@ -55,7 +55,7 @@
|
||||
(defmethod ig/expand-key ::wrk/monitor
|
||||
[k v]
|
||||
{k (-> (d/without-nils v)
|
||||
(assoc ::interval (dt/duration "2s")))})
|
||||
(assoc ::interval (ct/duration "2s")))})
|
||||
|
||||
(defmethod ig/init-key ::wrk/monitor
|
||||
[_ {:keys [::wrk/executor ::mtx/metrics ::interval ::wrk/name]}]
|
||||
|
||||
@@ -12,11 +12,11 @@
|
||||
[app.common.exceptions :as ex]
|
||||
[app.common.logging :as l]
|
||||
[app.common.schema :as sm]
|
||||
[app.common.time :as ct]
|
||||
[app.common.transit :as t]
|
||||
[app.db :as db]
|
||||
[app.metrics :as mtx]
|
||||
[app.redis :as rds]
|
||||
[app.util.time :as dt]
|
||||
[app.worker :as wrk]
|
||||
[cuerdas.core :as str]
|
||||
[integrant.core :as ig]
|
||||
@@ -29,10 +29,10 @@
|
||||
[:id ::sm/uuid]
|
||||
[:queue :string]
|
||||
[:name :string]
|
||||
[:created-at ::sm/inst]
|
||||
[:modified-at ::sm/inst]
|
||||
[:scheduled-at {:optional true} ::sm/inst]
|
||||
[:completed-at {:optional true} ::sm/inst]
|
||||
[:created-at ::ct/inst]
|
||||
[:modified-at ::ct/inst]
|
||||
[:scheduled-at {:optional true} ::ct/inst]
|
||||
[:completed-at {:optional true} ::ct/inst]
|
||||
[:error {:optional true} :string]
|
||||
[:max-retries :int]
|
||||
[:retry-num :int]
|
||||
@@ -76,10 +76,10 @@
|
||||
:queue queue
|
||||
:runner-id id
|
||||
:retry (:retry-num task))
|
||||
(let [tpoint (dt/tpoint)
|
||||
(let [tpoint (ct/tpoint)
|
||||
task-fn (wrk/get-task registry (:name task))
|
||||
result (when task-fn (task-fn task))
|
||||
elapsed (dt/format-duration (tpoint))
|
||||
elapsed (ct/format-duration (tpoint))
|
||||
result (if (valid-task-result? result)
|
||||
result
|
||||
{:status "completed"})]
|
||||
@@ -105,7 +105,7 @@
|
||||
(:max-retries task))
|
||||
(= ::retry (:type edata)))
|
||||
(cond-> {:status "retry" :error cause}
|
||||
(dt/duration? (:delay edata))
|
||||
(ct/duration? (:delay edata))
|
||||
(assoc :delay (:delay edata))
|
||||
|
||||
(= ::noop (:strategy edata))
|
||||
@@ -156,13 +156,13 @@
|
||||
(str error))
|
||||
task (-> result meta ::task)
|
||||
nretry (+ (:retry-num task) inc-by)
|
||||
now (dt/now)
|
||||
now (ct/now)
|
||||
delay (->> (iterate #(* % 2) delay) (take nretry) (last))]
|
||||
(db/update! pool :task
|
||||
{:error explain
|
||||
:status "retry"
|
||||
:modified-at now
|
||||
:scheduled-at (dt/plus now delay)
|
||||
:scheduled-at (ct/plus now delay)
|
||||
:retry-num nretry}
|
||||
{:id (:id task)})
|
||||
nil))
|
||||
@@ -172,14 +172,14 @@
|
||||
explain (ex-message error)]
|
||||
(db/update! pool :task
|
||||
{:error explain
|
||||
:modified-at (dt/now)
|
||||
:modified-at (ct/now)
|
||||
:status "failed"}
|
||||
{:id (:id task)})
|
||||
nil))
|
||||
|
||||
(handle-task-completion [result]
|
||||
(let [task (-> result meta ::task)
|
||||
now (dt/now)]
|
||||
now (ct/now)]
|
||||
(db/update! pool :task
|
||||
{:completed-at now
|
||||
:modified-at now
|
||||
@@ -255,7 +255,7 @@
|
||||
(let [cfg (-> cfg
|
||||
(assoc ::rds/rconn rconn)
|
||||
(assoc ::queue (str/ffmt "%:%" tenant queue))
|
||||
(assoc ::timeout (dt/duration "5s")))]
|
||||
(assoc ::timeout (ct/duration "5s")))]
|
||||
(loop []
|
||||
(when (px/interrupted?)
|
||||
(throw (InterruptedException. "interrupted")))
|
||||
|
||||
@@ -1,3 +1,3 @@
|
||||
{app/instant app.util.time/instant
|
||||
app/cron app.util.time/cron
|
||||
app/duration app.util.time/duration}
|
||||
{penpot/inst app.common.time/inst
|
||||
penpot/cron app.util.cron/cron
|
||||
penpot/duration app.common.time/duration}
|
||||
|
||||
@@ -20,7 +20,6 @@
|
||||
[app.rpc :as-alias rpc]
|
||||
[app.storage :as sto]
|
||||
[app.storage.tmp :as tmp]
|
||||
[app.util.time :as dt]
|
||||
[backend-tests.helpers :as th]
|
||||
[clojure.test :as t]
|
||||
[cuerdas.core :as str]
|
||||
|
||||
@@ -6,11 +6,11 @@
|
||||
|
||||
(ns backend-tests.bounce-handling-test
|
||||
(:require
|
||||
[app.common.time :as ct]
|
||||
[app.db :as db]
|
||||
[app.email :as email]
|
||||
[app.http.awsns :as awsns]
|
||||
[app.tokens :as tokens]
|
||||
[app.util.time :as dt]
|
||||
[backend-tests.helpers :as th]
|
||||
[clojure.pprint :refer [pprint]]
|
||||
[clojure.test :as t]
|
||||
@@ -250,7 +250,7 @@
|
||||
|
||||
(let [profile (th/create-profile* 1)
|
||||
pool (:app.db/pool th/*system*)]
|
||||
(th/create-complaint-for pool {:type :bounce :id (:id profile) :created-at (dt/in-past {:days 8})})
|
||||
(th/create-complaint-for pool {:type :bounce :id (:id profile) :created-at (ct/in-past {:days 8})})
|
||||
(th/create-complaint-for pool {:type :bounce :id (:id profile)})
|
||||
(th/create-complaint-for pool {:type :bounce :id (:id profile)})
|
||||
|
||||
@@ -268,8 +268,8 @@
|
||||
:profile-complaint-threshold 2})}]
|
||||
(let [profile (th/create-profile* 1)
|
||||
pool (:app.db/pool th/*system*)]
|
||||
(th/create-complaint-for pool {:type :bounce :id (:id profile) :created-at (dt/in-past {:days 8})})
|
||||
(th/create-complaint-for pool {:type :bounce :id (:id profile) :created-at (dt/in-past {:days 8})})
|
||||
(th/create-complaint-for pool {:type :bounce :id (:id profile) :created-at (ct/in-past {:days 8})})
|
||||
(th/create-complaint-for pool {:type :bounce :id (:id profile) :created-at (ct/in-past {:days 8})})
|
||||
(th/create-complaint-for pool {:type :bounce :id (:id profile)})
|
||||
(th/create-complaint-for pool {:type :bounce :id (:id profile)})
|
||||
(th/create-complaint-for pool {:type :complaint :id (:id profile)})
|
||||
|
||||
@@ -15,6 +15,7 @@
|
||||
[app.common.pprint :as pp]
|
||||
[app.common.schema :as sm]
|
||||
[app.common.spec :as us]
|
||||
[app.common.time :as ct]
|
||||
[app.common.transit :as tr]
|
||||
[app.common.uuid :as uuid]
|
||||
[app.config :as cf]
|
||||
@@ -33,7 +34,6 @@
|
||||
[app.rpc.helpers :as rph]
|
||||
[app.util.blob :as blob]
|
||||
[app.util.services :as sv]
|
||||
[app.util.time :as dt]
|
||||
[app.worker :as wrk]
|
||||
[app.worker.runner]
|
||||
[clojure.java.io :as io]
|
||||
@@ -263,7 +263,7 @@
|
||||
(dm/with-open [conn (db/open system)]
|
||||
(db/insert! conn :profile-complaint-report
|
||||
{:profile-id id
|
||||
:created-at (or created-at (dt/now))
|
||||
:created-at (or created-at (ct/now))
|
||||
:type (name type)
|
||||
:content (db/tjson {})})))
|
||||
|
||||
@@ -273,7 +273,7 @@
|
||||
(db/insert! conn :global-complaint-report
|
||||
{:email email
|
||||
:type (name type)
|
||||
:created-at (or created-at (dt/now))
|
||||
:created-at (or created-at (ct/now))
|
||||
:content (db/tjson {})})))
|
||||
|
||||
(defn create-team-role*
|
||||
@@ -305,7 +305,7 @@
|
||||
([system {:keys [file-id changes session-id profile-id revn]
|
||||
:or {session-id (uuid/next) revn 0}}]
|
||||
(-> system
|
||||
(assoc ::files.update/timestamp (dt/now))
|
||||
(assoc ::files.update/timestamp (ct/now))
|
||||
(db/tx-run! (fn [{:keys [::db/conn] :as system}]
|
||||
(let [file (files.update/get-file conn file-id)]
|
||||
(#'files.update/update-file* system
|
||||
@@ -379,7 +379,7 @@
|
||||
;; (app.common.pprint/pprint (:app.rpc/methods *system*))
|
||||
(try-on! (method-fn (-> data
|
||||
(dissoc ::type)
|
||||
(assoc :app.rpc/request-at (dt/now)))))))
|
||||
(assoc :app.rpc/request-at (ct/now)))))))
|
||||
|
||||
(defn run-task!
|
||||
([name]
|
||||
@@ -525,7 +525,7 @@
|
||||
|
||||
(defn sleep
|
||||
[ms-or-duration]
|
||||
(Thread/sleep (inst-ms (dt/duration ms-or-duration))))
|
||||
(Thread/sleep (inst-ms (ct/duration ms-or-duration))))
|
||||
|
||||
(defn config-get-mock
|
||||
[data]
|
||||
|
||||
@@ -7,10 +7,10 @@
|
||||
(ns backend-tests.rpc-audit-test
|
||||
(:require
|
||||
[app.common.pprint :as pp]
|
||||
[app.common.time :as ct]
|
||||
[app.common.uuid :as uuid]
|
||||
[app.db :as db]
|
||||
[app.rpc :as-alias rpc]
|
||||
[app.util.time :as dt]
|
||||
[backend-tests.helpers :as th]
|
||||
[clojure.test :as t]
|
||||
[yetti.request]))
|
||||
@@ -46,7 +46,7 @@
|
||||
:route "dashboard-files"}
|
||||
:context {:engine "blink"}
|
||||
:profile-id (:id prof)
|
||||
:timestamp (dt/now)
|
||||
:timestamp (ct/now)
|
||||
:type "action"}]}
|
||||
|
||||
params (with-meta params
|
||||
@@ -79,7 +79,7 @@
|
||||
:route "dashboard-files"}
|
||||
:context {:engine "blink"}
|
||||
:profile-id uuid/zero
|
||||
:timestamp (dt/now)
|
||||
:timestamp (ct/now)
|
||||
:type "action"}]}
|
||||
params (with-meta params
|
||||
{:app.http/request http-request})
|
||||
|
||||
@@ -7,6 +7,7 @@
|
||||
(ns backend-tests.rpc-comment-test
|
||||
(:require
|
||||
[app.common.geom.point :as gpt]
|
||||
[app.common.time :as ct]
|
||||
[app.common.uuid :as uuid]
|
||||
[app.db :as db]
|
||||
[app.http :as http]
|
||||
@@ -14,7 +15,6 @@
|
||||
[app.rpc.commands.comments :as comments]
|
||||
[app.rpc.cond :as cond]
|
||||
[app.rpc.quotes :as-alias quotes]
|
||||
[app.util.time :as dt]
|
||||
[backend-tests.helpers :as th]
|
||||
[clojure.test :as t]
|
||||
[datoteka.fs :as fs]
|
||||
@@ -78,7 +78,7 @@
|
||||
|
||||
(let [{:keys [result] :as out} (th/command! data)]
|
||||
(t/is (th/success? out))
|
||||
(t/is (dt/instant? (:modified-at result))))
|
||||
(t/is (ct/inst? (:modified-at result))))
|
||||
|
||||
(let [status' (th/db-get :comment-thread-status
|
||||
{:thread-id (:id thread)
|
||||
|
||||
@@ -17,7 +17,6 @@
|
||||
[app.http :as http]
|
||||
[app.rpc :as-alias rpc]
|
||||
[app.storage :as sto]
|
||||
[app.util.time :as dt]
|
||||
[backend-tests.helpers :as th]
|
||||
[clojure.test :as t]
|
||||
[cuerdas.core :as str]))
|
||||
|
||||
@@ -9,6 +9,7 @@
|
||||
[app.common.features :as cfeat]
|
||||
[app.common.pprint :as pp]
|
||||
[app.common.thumbnails :as thc]
|
||||
[app.common.time :as ct]
|
||||
[app.common.types.shape :as cts]
|
||||
[app.common.uuid :as uuid]
|
||||
[app.config :as cf]
|
||||
@@ -18,7 +19,6 @@
|
||||
[app.rpc :as-alias rpc]
|
||||
[app.rpc.commands.files :as files]
|
||||
[app.storage :as sto]
|
||||
[app.util.time :as dt]
|
||||
[backend-tests.helpers :as th]
|
||||
[clojure.test :as t]
|
||||
[cuerdas.core :as str]))
|
||||
@@ -135,7 +135,7 @@
|
||||
(t/is (nil? (:users result))))))
|
||||
|
||||
(th/db-update! :file
|
||||
{:deleted-at (dt/now)}
|
||||
{:deleted-at (ct/now)}
|
||||
{:id file-id})
|
||||
|
||||
(t/testing "query single file after delete and wait"
|
||||
@@ -1844,7 +1844,7 @@
|
||||
|
||||
(th/run-task! :delete-object
|
||||
{:object :file
|
||||
:deleted-at (dt/now)
|
||||
:deleted-at (ct/now)
|
||||
:id (:id file-1)})
|
||||
|
||||
;; Check that file media object references are marked all for deletion
|
||||
|
||||
@@ -16,7 +16,6 @@
|
||||
[app.rpc.commands.auth :as cauth]
|
||||
[app.storage :as sto]
|
||||
[app.tokens :as tokens]
|
||||
[app.util.time :as dt]
|
||||
[backend-tests.helpers :as th]
|
||||
[clojure.java.io :as io]
|
||||
[clojure.test :as t]
|
||||
|
||||
@@ -6,11 +6,11 @@
|
||||
|
||||
(ns backend-tests.rpc-media-test
|
||||
(:require
|
||||
[app.common.time :as ct]
|
||||
[app.common.uuid :as uuid]
|
||||
[app.db :as db]
|
||||
[app.rpc :as-alias rpc]
|
||||
[app.storage :as sto]
|
||||
[app.util.time :as dt]
|
||||
[backend-tests.helpers :as th]
|
||||
[clojure.test :as t]
|
||||
[datoteka.fs :as fs]))
|
||||
@@ -257,7 +257,7 @@
|
||||
:is-shared false})
|
||||
|
||||
_ (th/db-update! :file
|
||||
{:deleted-at (dt/now)}
|
||||
{:deleted-at (ct/now)}
|
||||
{:id (:id file)})
|
||||
|
||||
mfile {:filename "sample.jpg"
|
||||
|
||||
@@ -6,6 +6,7 @@
|
||||
|
||||
(ns backend-tests.rpc-profile-test
|
||||
(:require
|
||||
[app.common.time :as ct]
|
||||
[app.common.uuid :as uuid]
|
||||
[app.config :as cf]
|
||||
[app.db :as db]
|
||||
@@ -14,7 +15,6 @@
|
||||
[app.rpc :as-alias rpc]
|
||||
[app.rpc.commands.profile :as profile]
|
||||
[app.tokens :as tokens]
|
||||
[app.util.time :as dt]
|
||||
[backend-tests.helpers :as th]
|
||||
[clojure.java.io :as io]
|
||||
[clojure.test :as t]
|
||||
@@ -158,7 +158,7 @@
|
||||
(let [row (th/db-get :team
|
||||
{:id (:default-team-id prof)}
|
||||
{::db/remove-deleted false})]
|
||||
(t/is (dt/instant? (:deleted-at row))))
|
||||
(t/is (ct/inst? (:deleted-at row))))
|
||||
|
||||
;; execute permanent deletion task
|
||||
(let [result (th/run-task! :objects-gc {:min-age 0})]
|
||||
@@ -212,7 +212,7 @@
|
||||
;; (th/print-result! out)
|
||||
|
||||
(let [team (th/db-get :team {:id (:id team1)} {::db/remove-deleted false})]
|
||||
(t/is (dt/instant? (:deleted-at team)))))
|
||||
(t/is (ct/inst? (:deleted-at team)))))
|
||||
|
||||
;; Request profile to be deleted
|
||||
(let [params {::th/type :delete-profile
|
||||
@@ -517,7 +517,7 @@
|
||||
(let [sprops (:app.setup/props th/*system*)
|
||||
itoken (tokens/generate sprops
|
||||
{:iss :team-invitation
|
||||
:exp (dt/in-future "48h")
|
||||
:exp (ct/in-future "48h")
|
||||
:role :editor
|
||||
:team-id uuid/zero
|
||||
:member-email "user@example.com"})
|
||||
@@ -546,7 +546,7 @@
|
||||
(let [sprops (:app.setup/props th/*system*)
|
||||
itoken (tokens/generate sprops
|
||||
{:iss :team-invitation
|
||||
:exp (dt/in-future "48h")
|
||||
:exp (ct/in-future "48h")
|
||||
:role :editor
|
||||
:team-id uuid/zero
|
||||
:member-email "user2@example.com"})
|
||||
@@ -568,7 +568,7 @@
|
||||
(let [sprops (:app.setup/props th/*system*)
|
||||
itoken (tokens/generate sprops
|
||||
{:iss :team-invitation
|
||||
:exp (dt/in-future "48h")
|
||||
:exp (ct/in-future "48h")
|
||||
:role :editor
|
||||
:team-id uuid/zero
|
||||
:member-email "user@example.com"})
|
||||
@@ -589,7 +589,7 @@
|
||||
(let [sprops (:app.setup/props th/*system*)
|
||||
itoken (tokens/generate sprops
|
||||
{:iss :team-invitation
|
||||
:exp (dt/in-future "48h")
|
||||
:exp (ct/in-future "48h")
|
||||
:role :editor
|
||||
:team-id uuid/zero
|
||||
:member-email "user2@example.com"})
|
||||
@@ -611,7 +611,7 @@
|
||||
(let [sprops (:app.setup/props th/*system*)
|
||||
itoken (tokens/generate sprops
|
||||
{:iss :team-invitation
|
||||
:exp (dt/in-future "48h")
|
||||
:exp (ct/in-future "48h")
|
||||
:role :editor
|
||||
:team-id uuid/zero
|
||||
:member-email "user2@example.com"})
|
||||
|
||||
@@ -11,7 +11,6 @@
|
||||
[app.db :as db]
|
||||
[app.http :as http]
|
||||
[app.rpc :as-alias rpc]
|
||||
[app.util.time :as dt]
|
||||
[backend-tests.helpers :as th]
|
||||
[clojure.test :as t]))
|
||||
|
||||
|
||||
@@ -7,6 +7,7 @@
|
||||
(ns backend-tests.rpc-team-test
|
||||
(:require
|
||||
[app.common.logging :as l]
|
||||
[app.common.time :as ct]
|
||||
[app.common.uuid :as uuid]
|
||||
[app.config :as cf]
|
||||
[app.db :as db]
|
||||
@@ -14,7 +15,6 @@
|
||||
[app.rpc :as-alias rpc]
|
||||
[app.storage :as sto]
|
||||
[app.tokens :as tokens]
|
||||
[app.util.time :as dt]
|
||||
[backend-tests.helpers :as th]
|
||||
[clojure.test :as t]
|
||||
[datoteka.fs :as fs]
|
||||
@@ -163,7 +163,7 @@
|
||||
|
||||
;; Proceed to delete the requester user
|
||||
(th/db-update! :profile
|
||||
{:deleted-at (dt/in-past "1h")}
|
||||
{:deleted-at (ct/in-past "1h")}
|
||||
{:id (:id requester)})
|
||||
|
||||
;; Create a new profile with the same email
|
||||
@@ -271,7 +271,7 @@
|
||||
|
||||
(let [token (tokens/generate sprops
|
||||
{:iss :team-invitation
|
||||
:exp (dt/in-future "1h")
|
||||
:exp (ct/in-future "1h")
|
||||
:profile-id (:id profile1)
|
||||
:role :editor
|
||||
:team-id (:id team)
|
||||
@@ -283,7 +283,7 @@
|
||||
{:team-id (:id team)
|
||||
:email-to (:email profile2)
|
||||
:role "editor"
|
||||
:valid-until (dt/in-future "48h")})
|
||||
:valid-until (ct/in-future "48h")})
|
||||
|
||||
(let [data {::th/type :verify-token :token token}
|
||||
out (th/command! data)]
|
||||
@@ -328,7 +328,7 @@
|
||||
{:team-id (:id team)
|
||||
:email-to (:email profile3)
|
||||
:role "editor"
|
||||
:valid-until (dt/in-future "48h")})
|
||||
:valid-until (ct/in-future "48h")})
|
||||
|
||||
(let [data {::th/type :verify-token
|
||||
::rpc/profile-id (:id profile1)
|
||||
@@ -381,14 +381,14 @@
|
||||
{:team-id (:team-id data)
|
||||
:email-to "test1@mail.com"
|
||||
:role "editor"
|
||||
:valid-until (dt/in-future "48h")})
|
||||
:valid-until (ct/in-future "48h")})
|
||||
|
||||
;; insert an entry on the database with an expired invitation
|
||||
(db/insert! th/*pool* :team-invitation
|
||||
{:team-id (:team-id data)
|
||||
:email-to "test2@mail.com"
|
||||
:role "editor"
|
||||
:valid-until (dt/in-past "48h")})
|
||||
:valid-until (ct/in-past "48h")})
|
||||
|
||||
(let [out (th/command! data)]
|
||||
(t/is (th/success? out))
|
||||
@@ -415,7 +415,7 @@
|
||||
{:team-id (:team-id data)
|
||||
:email-to "test1@mail.com"
|
||||
:role "editor"
|
||||
:valid-until (dt/in-future "48h")})
|
||||
:valid-until (ct/in-future "48h")})
|
||||
|
||||
(let [out (th/command! data)
|
||||
;; retrieve the value from the database and check its content
|
||||
@@ -438,7 +438,7 @@
|
||||
{:team-id (:team-id data)
|
||||
:email-to "test1@mail.com"
|
||||
:role "editor"
|
||||
:valid-until (dt/in-future "48h")})
|
||||
:valid-until (ct/in-future "48h")})
|
||||
|
||||
(let [out (th/command! data)
|
||||
;; retrieve the value from the database and check its content
|
||||
@@ -582,7 +582,7 @@
|
||||
|
||||
(let [rows (th/db-exec! ["select * from team where id = ?" (:id team)])]
|
||||
(t/is (= 1 (count rows)))
|
||||
(t/is (dt/instant? (:deleted-at (first rows)))))
|
||||
(t/is (ct/inst? (:deleted-at (first rows)))))
|
||||
|
||||
(let [result (th/run-task! :objects-gc {:deletion-threshold (cf/get-deletion-delay)})]
|
||||
(t/is (= 5 (:processed result))))))
|
||||
@@ -626,7 +626,7 @@
|
||||
(th/reset-mock! mock)
|
||||
|
||||
(th/db-update! :team-access-request
|
||||
{:valid-until (dt/in-past "1h")}
|
||||
{:valid-until (ct/in-past "1h")}
|
||||
{:team-id (:id team)
|
||||
:requester-id (:id requester)})
|
||||
|
||||
|
||||
@@ -7,11 +7,11 @@
|
||||
(ns backend-tests.storage-test
|
||||
(:require
|
||||
[app.common.exceptions :as ex]
|
||||
[app.common.time :as ct]
|
||||
[app.common.uuid :as uuid]
|
||||
[app.db :as db]
|
||||
[app.rpc :as-alias rpc]
|
||||
[app.storage :as sto]
|
||||
[app.util.time :as dt]
|
||||
[backend-tests.helpers :as th]
|
||||
[clojure.test :as t]
|
||||
[cuerdas.core :as str]
|
||||
@@ -53,12 +53,12 @@
|
||||
(configure-storage-backend))
|
||||
content (sto/content "content")
|
||||
object (sto/put-object! storage {::sto/content content
|
||||
::sto/expired-at (dt/in-future {:seconds 1})
|
||||
::sto/expired-at (ct/in-future {:seconds 1})
|
||||
:content-type "text/plain"})]
|
||||
|
||||
(t/is (sto/object? object))
|
||||
(t/is (dt/instant? (:expired-at object)))
|
||||
(t/is (dt/is-after? (:expired-at object) (dt/now)))
|
||||
(t/is (ct/inst? (:expired-at object)))
|
||||
(t/is (ct/is-after? (:expired-at object) (ct/now)))
|
||||
(t/is (= object (sto/get-object storage (:id object))))
|
||||
|
||||
(th/sleep 1000)
|
||||
@@ -73,7 +73,7 @@
|
||||
content (sto/content "content")
|
||||
object (sto/put-object! storage {::sto/content content
|
||||
:content-type "text/plain"
|
||||
:expired-at (dt/in-future {:seconds 1})})]
|
||||
:expired-at (ct/in-future {:seconds 1})})]
|
||||
(t/is (sto/object? object))
|
||||
(t/is (true? (sto/del-object! storage object)))
|
||||
|
||||
@@ -95,13 +95,13 @@
|
||||
content3 (sto/content "content3")
|
||||
|
||||
object1 (sto/put-object! storage {::sto/content content1
|
||||
::sto/expired-at (dt/now)
|
||||
::sto/expired-at (ct/now)
|
||||
:content-type "text/plain"})
|
||||
object2 (sto/put-object! storage {::sto/content content2
|
||||
::sto/expired-at (dt/in-past {:hours 2})
|
||||
::sto/expired-at (ct/in-past {:hours 2})
|
||||
:content-type "text/plain"})
|
||||
object3 (sto/put-object! storage {::sto/content content3
|
||||
::sto/expired-at (dt/in-past {:hours 1})
|
||||
::sto/expired-at (ct/in-past {:hours 1})
|
||||
:content-type "text/plain"})]
|
||||
|
||||
|
||||
@@ -154,7 +154,7 @@
|
||||
(t/is (= (:media-id result-1) (:media-id result-2)))
|
||||
|
||||
(th/db-update! :file-media-object
|
||||
{:deleted-at (dt/now)}
|
||||
{:deleted-at (ct/now)}
|
||||
{:id (:id result-1)})
|
||||
|
||||
;; run the objects gc task for permanent deletion
|
||||
@@ -239,7 +239,7 @@
|
||||
result-2 (:result out2)]
|
||||
|
||||
(th/db-update! :team-font-variant
|
||||
{:deleted-at (dt/now)}
|
||||
{:deleted-at (ct/now)}
|
||||
{:id (:id result-2)})
|
||||
|
||||
;; run the objects gc task for permanent deletion
|
||||
|
||||
@@ -7,7 +7,6 @@
|
||||
(ns backend-tests.tasks-telemetry-test
|
||||
(:require
|
||||
[app.db :as db]
|
||||
[app.util.time :as dt]
|
||||
[backend-tests.helpers :as th]
|
||||
[clojure.pprint :refer [pprint]]
|
||||
[clojure.test :as t]
|
||||
|
||||
@@ -10,15 +10,15 @@
|
||||
"type": "git",
|
||||
"url": "https://github.com/penpot/penpot"
|
||||
},
|
||||
"dependencies": {
|
||||
"luxon": "^3.6.1"
|
||||
},
|
||||
"devDependencies": {
|
||||
"concurrently": "^9.1.2",
|
||||
"nodemon": "^3.1.10",
|
||||
"source-map-support": "^0.5.21",
|
||||
"ws": "^8.18.2"
|
||||
},
|
||||
"dependencies": {
|
||||
"date-fns": "^4.1.0"
|
||||
},
|
||||
"scripts": {
|
||||
"fmt:clj:check": "cljfmt check --parallel=false src/ test/",
|
||||
"fmt:clj": "cljfmt fix --parallel=true src/ test/",
|
||||
|
||||
@@ -14,7 +14,6 @@
|
||||
[app.common.schema.generators :as sg]
|
||||
[app.common.schema.openapi :as-alias oapi]
|
||||
[app.common.schema.registry :as sr]
|
||||
[app.common.time :as tm]
|
||||
[app.common.uri :as u]
|
||||
[app.common.uuid :as uuid]
|
||||
[clojure.core :as c]
|
||||
@@ -850,38 +849,38 @@
|
||||
{:title "contains any"
|
||||
:description "contains predicate"}}))})
|
||||
|
||||
(register!
|
||||
{:type ::inst
|
||||
:pred inst?
|
||||
:type-properties
|
||||
{:title "inst"
|
||||
:description "Satisfies Inst protocol"
|
||||
:error/message "should be an instant"
|
||||
:gen/gen (->> (sg/small-int :min 0 :max 100000)
|
||||
(sg/fmap (fn [v] (tm/parse-instant v))))
|
||||
;; (register!
|
||||
;; {:type ::inst
|
||||
;; :pred tm/instant?
|
||||
;; :type-properties
|
||||
;; {:title "inst"
|
||||
;; :description "Satisfies Inst protocol"
|
||||
;; :error/message "should be an instant"
|
||||
;; :gen/gen (->> (sg/small-int :min 0 :max 100000)
|
||||
;; (sg/fmap (fn [v] (tm/parse-inst v))))
|
||||
|
||||
:decode/string tm/parse-instant
|
||||
:encode/string tm/format-instant
|
||||
:decode/json tm/parse-instant
|
||||
:encode/json tm/format-instant
|
||||
::oapi/type "string"
|
||||
::oapi/format "iso"}})
|
||||
;; :decode/string tm/parse-inst
|
||||
;; :encode/string tm/format-inst
|
||||
;; :decode/json tm/parse-inst
|
||||
;; :encode/json tm/format-inst
|
||||
;; ::oapi/type "string"
|
||||
;; ::oapi/format "iso"}})
|
||||
|
||||
(register!
|
||||
{:type ::timestamp
|
||||
:pred inst?
|
||||
:type-properties
|
||||
{:title "inst"
|
||||
:description "Satisfies Inst protocol"
|
||||
:error/message "should be an instant"
|
||||
:gen/gen (->> (sg/small-int)
|
||||
(sg/fmap (fn [v] (tm/parse-instant v))))
|
||||
:decode/string tm/parse-instant
|
||||
:encode/string inst-ms
|
||||
:decode/json tm/parse-instant
|
||||
:encode/json inst-ms
|
||||
::oapi/type "string"
|
||||
::oapi/format "number"}})
|
||||
;; (register!
|
||||
;; {:type ::timestamp
|
||||
;; :pred tm/instant?
|
||||
;; :type-properties
|
||||
;; {:title "inst"
|
||||
;; :description "Satisfies Inst protocol, the same as ::inst but encodes to epoch"
|
||||
;; :error/message "should be an instant"
|
||||
;; :gen/gen (->> (sg/small-int)
|
||||
;; (sg/fmap (fn [v] (tm/parse-inst v))))
|
||||
;; :decode/string tm/parse-inst
|
||||
;; :encode/string inst-ms
|
||||
;; :decode/json tm/parse-inst
|
||||
;; :encode/json inst-ms
|
||||
;; ::oapi/type "string"
|
||||
;; ::oapi/format "number"}})
|
||||
|
||||
(register!
|
||||
{:type ::fn
|
||||
|
||||
@@ -4,28 +4,152 @@
|
||||
;;
|
||||
;; Copyright (c) KALEIDOS INC
|
||||
|
||||
#_{:clj-kondo/ignore [:unused-namespace]}
|
||||
(ns app.common.time
|
||||
"Minimal cross-platoform date time api for specific use cases on types
|
||||
definition and other common code."
|
||||
#?(:cljs
|
||||
(:require
|
||||
["luxon" :as lxn])
|
||||
:clj
|
||||
(:refer-clojure :exclude [inst?])
|
||||
(:require
|
||||
#?@(:cljs [["date-fns/format$default" :as dfn-format]
|
||||
["date-fns/formatISO$default" :as dfn-format-iso]
|
||||
["date-fns/setDefaultOptions$default" :as dfn-set-default-options]
|
||||
["date-fns/differenceInMilliseconds$default" :as dfn-diff]
|
||||
["date-fns/formatDistanceToNowStrict$default" :as dfn-distance-to-now]
|
||||
["date-fns/add$default" :as dfn-add]
|
||||
["date-fns/sub$default" :as dfn-sub]
|
||||
["date-fns/parseISO$default" :as dfn-parse-iso]
|
||||
["date-fns/locale/ar-SA$default" :as dfn-ar]
|
||||
["date-fns/locale/ca$default" :as dfn-ca]
|
||||
["date-fns/locale/cs$default" :as dfn-cs]
|
||||
["date-fns/locale/de$default" :as dfn-de]
|
||||
["date-fns/locale/el$default" :as dfn-el]
|
||||
["date-fns/locale/en-US$default" :as df-en-us]
|
||||
["date-fns/locale/es$default" :as dfn-es]
|
||||
["date-fns/locale/eu$default" :as dfn-eu]
|
||||
["date-fns/locale/fa-IR$default" :as dfn-fa-ir]
|
||||
["date-fns/locale/fr$default" :as dfn-fr]
|
||||
["date-fns/locale/gl$default" :as dfn-gl]
|
||||
["date-fns/locale/he$default" :as dfn-he]
|
||||
["date-fns/locale/hr$default" :as dfn-hr]
|
||||
["date-fns/locale/id$default" :as dfn-id]
|
||||
["date-fns/locale/it$default" :as dfn-it]
|
||||
["date-fns/locale/ja$default" :as dfn-ja]
|
||||
["date-fns/locale/ko$default" :as dfn-ko]
|
||||
["date-fns/locale/lv$default" :as dfn-lv]
|
||||
["date-fns/locale/nb$default" :as dfn-nb]
|
||||
["date-fns/locale/nl$default" :as dfn-nl]
|
||||
["date-fns/locale/pl$default" :as dfn-pl]
|
||||
["date-fns/locale/pt$default" :as dfn-pt]
|
||||
["date-fns/locale/pt-BR$default" :as dfn-pt-br]
|
||||
["date-fns/locale/ro$default" :as dfn-ro]
|
||||
["date-fns/locale/ru$default" :as dfn-ru]
|
||||
["date-fns/locale/tr$default" :as dfn-tr]
|
||||
["date-fns/locale/uk$default" :as dfn-uk]
|
||||
["date-fns/locale/zh-CN$default" :as dfn-zh-cn]])
|
||||
[app.common.schema :as sm]
|
||||
[app.common.schema.generators :as sg]
|
||||
[app.common.schema.openapi :as-alias oapi]
|
||||
[cuerdas.core :as str])
|
||||
#?(:clj
|
||||
(:import
|
||||
java.time.format.DateTimeFormatter
|
||||
java.time.Duration
|
||||
java.time.Instant
|
||||
java.time.Duration)))
|
||||
|
||||
#?(:cljs
|
||||
(def DateTime lxn/DateTime))
|
||||
|
||||
#?(:cljs
|
||||
(def Duration lxn/Duration))
|
||||
java.time.OffsetDateTime
|
||||
java.time.ZoneId
|
||||
java.time.ZonedDateTime
|
||||
java.time.format.DateTimeFormatter
|
||||
java.time.temporal.ChronoUnit
|
||||
java.time.temporal.Temporal
|
||||
java.time.temporal.TemporalAmount
|
||||
java.time.temporal.TemporalUnit)))
|
||||
|
||||
(defn now
|
||||
[]
|
||||
#?(:clj (Instant/now)
|
||||
:cljs (.local ^js DateTime)))
|
||||
:cljs (new js/Date)))
|
||||
|
||||
;; --- DURATION
|
||||
|
||||
(defn- resolve-temporal-unit
|
||||
[o]
|
||||
(case o
|
||||
(:nanos :nano)
|
||||
#?(:clj ChronoUnit/NANOS
|
||||
:cljs (throw (js/Error. "not supported nanos")))
|
||||
|
||||
(:micros :microsecond :micro)
|
||||
#?(:clj ChronoUnit/MICROS
|
||||
:cljs (throw (js/Error. "not supported nanos")))
|
||||
|
||||
(:millis :millisecond :milli)
|
||||
#?(:clj ChronoUnit/MILLIS
|
||||
:cljs "millisecond")
|
||||
|
||||
(:seconds :second)
|
||||
#?(:clj ChronoUnit/SECONDS
|
||||
:cljs "second")
|
||||
|
||||
(:minutes :minute)
|
||||
#?(:clj ChronoUnit/MINUTES
|
||||
:cljs "minute")
|
||||
|
||||
(:hours :hour)
|
||||
#?(:clj ChronoUnit/HOURS
|
||||
:cljs "hour")
|
||||
|
||||
(:days :day)
|
||||
#?(:clj ChronoUnit/DAYS
|
||||
:cljs "day")))
|
||||
|
||||
(defn temporal-unit
|
||||
[o]
|
||||
#?(:clj (if (instance? TemporalUnit o) o (resolve-temporal-unit o))
|
||||
:cljs (resolve-temporal-unit o)))
|
||||
|
||||
#?(:clj
|
||||
(defn- obj->duration
|
||||
[params]
|
||||
(reduce-kv (fn [o k v]
|
||||
(.plus ^Duration o ^long v ^TemporalUnit (temporal-unit k)))
|
||||
(Duration/ofMillis 0)
|
||||
params)))
|
||||
|
||||
#?(:clj
|
||||
(defn duration?
|
||||
[o]
|
||||
(instance? Duration o)))
|
||||
|
||||
(defn duration
|
||||
[ms-or-obj]
|
||||
#?(:clj
|
||||
(cond
|
||||
(string? ms-or-obj)
|
||||
(Duration/parse (str "PT" ms-or-obj))
|
||||
|
||||
(duration? ms-or-obj)
|
||||
ms-or-obj
|
||||
|
||||
(integer? ms-or-obj)
|
||||
|
||||
(Duration/ofMillis ms-or-obj)
|
||||
|
||||
:else
|
||||
(obj->duration ms-or-obj))
|
||||
|
||||
:cljs
|
||||
(clj->js ms-or-obj)))
|
||||
|
||||
#?(:clj
|
||||
(defn parse-duration
|
||||
[s]
|
||||
(duration s)))
|
||||
|
||||
#?(:clj
|
||||
(defn format-duration
|
||||
[o]
|
||||
(str/lower (subs (str o) 2))))
|
||||
|
||||
;; --- INSTNANT & DATETIME
|
||||
|
||||
(defn is-after?
|
||||
"Analgous to: da > db"
|
||||
@@ -44,65 +168,261 @@
|
||||
(zero? result) false
|
||||
:else false)))
|
||||
|
||||
(defn instant?
|
||||
(defn inst?
|
||||
[o]
|
||||
#?(:clj (instance? Instant o)
|
||||
:cljs (instance? DateTime o)))
|
||||
:cljs (instance? js/Date o)))
|
||||
|
||||
(defn parse-instant
|
||||
(defn seconds
|
||||
[d]
|
||||
(-> d inst-ms (/ 1000) int))
|
||||
|
||||
(defn format-inst
|
||||
([v] (format-inst v :iso))
|
||||
([v fmt]
|
||||
(case fmt
|
||||
(:iso :iso8601)
|
||||
#?(:clj (.format DateTimeFormatter/ISO_INSTANT ^Instant v)
|
||||
:cljs (dfn-format-iso v))
|
||||
|
||||
:iso-date
|
||||
#?(:clj (.format DateTimeFormatter/ISO_LOCAL_DATE
|
||||
^ZonedDateTime (ZonedDateTime/ofInstant v (ZoneId/of "UTC")))
|
||||
:cljs (dfn-format-iso v #js {:representation "date"}))
|
||||
|
||||
(:rfc1123 :http)
|
||||
#?(:clj (.format DateTimeFormatter/RFC_1123_DATE_TIME
|
||||
^ZonedDateTime (ZonedDateTime/ofInstant v (ZoneId/of "UTC")))
|
||||
:cljs (dfn-format v "EEE, dd LLL yyyy HH:mm:ss 'GMT'"))
|
||||
|
||||
#?@(:cljs [:time-24-simple
|
||||
(dfn-format v "HH:mm")
|
||||
|
||||
;; DEPRECATED
|
||||
:date-full
|
||||
(dfn-format v "PPP")
|
||||
|
||||
:localized-date
|
||||
(dfn-format v "PPP")
|
||||
|
||||
:localized-time
|
||||
(dfn-format v "p")
|
||||
|
||||
:localized-date-time
|
||||
(dfn-format v "PPPp")
|
||||
|
||||
(if (string? fmt)
|
||||
(dfn-format v fmt)
|
||||
(throw (js/Error. "unpexted format")))]))))
|
||||
|
||||
#?(:cljs
|
||||
(def locales
|
||||
#js {:ar dfn-ar
|
||||
:ca dfn-ca
|
||||
:de dfn-de
|
||||
:el dfn-el
|
||||
:en df-en-us
|
||||
:en_us df-en-us
|
||||
:es dfn-es
|
||||
:es_es dfn-es
|
||||
:fa dfn-fa-ir
|
||||
:fa_ir dfn-fa-ir
|
||||
:fr dfn-fr
|
||||
:he dfn-he
|
||||
:pt dfn-pt
|
||||
:pt_pt dfn-pt
|
||||
:pt_br dfn-pt-br
|
||||
:ro dfn-ro
|
||||
:ru dfn-ru
|
||||
:tr dfn-tr
|
||||
:zh-cn dfn-zh-cn
|
||||
:nl dfn-nl
|
||||
:eu dfn-eu
|
||||
:gl dfn-gl
|
||||
:hr dfn-hr
|
||||
:it dfn-it
|
||||
:nb dfn-nb
|
||||
:nb_no dfn-nb
|
||||
:pl dfn-pl
|
||||
:id dfn-id
|
||||
:uk dfn-uk
|
||||
:cs dfn-cs
|
||||
:lv dfn-lv
|
||||
:ko dfn-ko
|
||||
:ja dfn-ja
|
||||
:ja_jp dfn-ja}))
|
||||
|
||||
#?(:cljs
|
||||
(defn timeago
|
||||
[v]
|
||||
(when v
|
||||
(dfn-distance-to-now v #js {:includeSeconds true
|
||||
:addSuffix true}))))
|
||||
|
||||
(defn inst
|
||||
[s]
|
||||
(cond
|
||||
(instant? s)
|
||||
(inst? s)
|
||||
s
|
||||
|
||||
(int? s)
|
||||
#?(:clj (Instant/ofEpochMilli s)
|
||||
:cljs (.fromMillis ^js DateTime s #js {:zone "local" :setZone false}))
|
||||
#?(:clj (Instant/ofEpochMilli s)
|
||||
:cljs (new js/Date s))
|
||||
|
||||
(string? s)
|
||||
#?(:clj (Instant/parse s)
|
||||
:cljs (.fromISO ^js DateTime s))))
|
||||
#?(:clj (Instant/from (.parse DateTimeFormatter/ISO_DATE_TIME ^String s))
|
||||
:cljs (dfn-parse-iso s))
|
||||
|
||||
(defn format-instant
|
||||
:else
|
||||
(throw (ex-info "invalid parameters" {}))))
|
||||
|
||||
#?(:clj
|
||||
(defn truncate
|
||||
[o unit]
|
||||
(let [unit (temporal-unit unit)]
|
||||
(cond
|
||||
(inst? o)
|
||||
(.truncatedTo ^Instant o ^TemporalUnit unit)
|
||||
|
||||
(instance? Duration o)
|
||||
(.truncatedTo ^Duration o ^TemporalUnit unit)
|
||||
|
||||
:else
|
||||
(throw (IllegalArgumentException. "only instant and duration allowed"))))))
|
||||
|
||||
(defn plus
|
||||
[d ta]
|
||||
(let [ta (duration ta)]
|
||||
(cond
|
||||
#?@(:clj [(duration? d) (.plus ^Duration d ^TemporalAmount ta)])
|
||||
|
||||
#?(:cljs (inst? d)
|
||||
:clj (instance? Temporal d))
|
||||
#?(:cljs (dfn-add d ta)
|
||||
:clj (.plus ^Temporal d ^Duration ta))
|
||||
|
||||
:else
|
||||
(throw #?(:clj (UnsupportedOperationException. "unsupported type")
|
||||
:cljs (js/Error. "unsupported type"))))))
|
||||
|
||||
(defn minus
|
||||
[d ta]
|
||||
(let [^TemporalAmount ta (duration ta)]
|
||||
(cond
|
||||
#?@(:clj [(duration? d) (.minus ^Duration d ^TemporalAmount ta)])
|
||||
|
||||
#?(:cljs (inst? d) :clj (instance? Temporal d))
|
||||
#?(:cljs (dfn-sub d ta)
|
||||
:clj (.minus ^Temporal d ^Duration ta))
|
||||
|
||||
:else
|
||||
(throw #?(:clj (UnsupportedOperationException. "unsupported type")
|
||||
:cljs (js/Error. "unsupported type"))))))
|
||||
|
||||
(defn in-future
|
||||
[v]
|
||||
#?(:clj (.format DateTimeFormatter/ISO_INSTANT ^Instant v)
|
||||
:cljs (.toISO ^js v)))
|
||||
(plus (now) v))
|
||||
|
||||
;; To check for valid date time we can just use the core inst? function
|
||||
(defn in-past
|
||||
[v]
|
||||
(minus (now) v))
|
||||
|
||||
#?(:clj
|
||||
(defn diff
|
||||
[t1 t2]
|
||||
(Duration/between t1 t2)))
|
||||
|
||||
#?(:cljs
|
||||
(extend-protocol IComparable
|
||||
DateTime
|
||||
(-compare [it other]
|
||||
(if ^boolean (.equals it other)
|
||||
0
|
||||
(if (< (inst-ms it) (inst-ms other)) -1 1)))
|
||||
|
||||
Duration
|
||||
(-compare [it other]
|
||||
(if ^boolean (.equals it other)
|
||||
0
|
||||
(if (< (inst-ms it) (inst-ms other)) -1 1)))))
|
||||
(defn diff-ms
|
||||
[t1 t2]
|
||||
(dfn-diff t2 t1)))
|
||||
|
||||
#?(:cljs
|
||||
(extend-type DateTime
|
||||
cljs.core/IEquiv
|
||||
(-equiv [o other]
|
||||
(and (instance? DateTime other)
|
||||
(== (.valueOf o) (.valueOf other))))))
|
||||
(defn set-default-locale!
|
||||
[locale]
|
||||
(when-let [locale (unchecked-get locales locale)]
|
||||
(dfn-set-default-options #js {:locale locale}))))
|
||||
|
||||
;; --- HELPERS
|
||||
|
||||
#?(:clj
|
||||
(defn tpoint
|
||||
"Create a measurement checkpoint for time measurement of potentially
|
||||
asynchronous flow."
|
||||
[]
|
||||
(let [p1 (System/nanoTime)]
|
||||
#(duration {:nanos (- (System/nanoTime) p1)}))))
|
||||
|
||||
#?(:cljs
|
||||
(extend-protocol cljs.core/Inst
|
||||
DateTime
|
||||
(inst-ms* [inst] (.toMillis ^js inst))
|
||||
(defn tpoint-ms
|
||||
"Create a measurement checkpoint for time measurement of potentially
|
||||
asynchronous flow."
|
||||
[]
|
||||
(let [p1 (.now js/performance)]
|
||||
#(- (.now js/performance) p1))))
|
||||
|
||||
Duration
|
||||
(inst-ms* [inst] (.toMillis ^js inst)))
|
||||
;; --- EXTENSIONS
|
||||
|
||||
:clj
|
||||
#?(:clj
|
||||
(extend-protocol clojure.core/Inst
|
||||
Duration
|
||||
(inst-ms* [v] (.toMillis ^Duration v))
|
||||
|
||||
OffsetDateTime
|
||||
(inst-ms* [v] (.toEpochMilli (.toInstant ^OffsetDateTime v)))
|
||||
|
||||
Instant
|
||||
(inst-ms* [v] (.toEpochMilli ^Instant v))))
|
||||
|
||||
#?(:clj
|
||||
(defmethod print-method Duration
|
||||
[o w]
|
||||
(print-dup o w)))
|
||||
|
||||
#?(:clj
|
||||
(defmethod print-dup Duration
|
||||
[mv ^java.io.Writer writer]
|
||||
(.write writer (str "#penpot/duration \"" (str/lower (subs (str mv) 2)) "\""))))
|
||||
|
||||
#?(:clj
|
||||
(defmethod print-method Instant
|
||||
[o w]
|
||||
(print-dup o w)))
|
||||
|
||||
#?(:clj
|
||||
(defmethod print-dup Instant
|
||||
[mv ^java.io.Writer writer]
|
||||
(.write writer (str "#penpot/inst \"" (format-inst mv) "\""))))
|
||||
|
||||
(def schema:inst
|
||||
(sm/register!
|
||||
{:type ::inst
|
||||
:pred inst?
|
||||
:type-properties
|
||||
{:error/message "should be an instant"
|
||||
:title "instant"
|
||||
:decode/string inst
|
||||
:encode/string format-inst
|
||||
:decode/json inst
|
||||
:encode/json format-inst
|
||||
:gen/gen (->> (sg/small-int :min 0)
|
||||
(sg/fmap (fn [i] (in-past i))))
|
||||
::oapi/type "string"
|
||||
::oapi/format "iso"}}))
|
||||
|
||||
#?(:clj
|
||||
(def schema:duration
|
||||
(sm/register!
|
||||
{:type ::duration
|
||||
:pred duration?
|
||||
:type-properties
|
||||
{:error/message "should be a duration"
|
||||
:gen/gen (->> (sg/small-int :min 0)
|
||||
(sg/fmap duration))
|
||||
:title "duration"
|
||||
:decode/string parse-duration
|
||||
:encode/string format-duration
|
||||
:decode/json parse-duration
|
||||
:encode/json format-duration
|
||||
::oapi/type "string"
|
||||
::oapi/format "duration"}})))
|
||||
|
||||
@@ -7,7 +7,6 @@
|
||||
(ns app.common.transit
|
||||
(:require
|
||||
#?(:clj [datoteka.fs :as fs])
|
||||
#?(:cljs ["luxon" :as lxn])
|
||||
[app.common.data :as d]
|
||||
[app.common.uri :as uri]
|
||||
[cognitect.transit :as t]
|
||||
@@ -130,20 +129,18 @@
|
||||
:wfn vec
|
||||
:rfn #(into lks/empty-linked-set %)}
|
||||
|
||||
{:id "duration"
|
||||
:class #?(:clj Duration :cljs lxn/Duration)
|
||||
:rfn (fn [v]
|
||||
#?(:clj (Duration/ofMillis v)
|
||||
:cljs (.fromMillis ^js lxn/Duration v)))
|
||||
:wfn inst-ms}
|
||||
#?(:clj
|
||||
{:id "duration"
|
||||
:class Duration
|
||||
:rfn (fn [v] (Duration/ofMillis v))
|
||||
:wfn inst-ms})
|
||||
|
||||
{:id "m"
|
||||
:class #?(:clj Instant :cljs lxn/DateTime)
|
||||
:class #?(:clj Instant :cljs js/Date)
|
||||
:rfn (fn [v]
|
||||
#?(:clj (-> (Long/parseLong v)
|
||||
(Instant/ofEpochMilli))
|
||||
:cljs (let [ms (js/parseInt v 10)]
|
||||
(.fromMillis ^js lxn/DateTime ms))))
|
||||
#?(:clj (-> (Long/parseLong v)
|
||||
(Instant/ofEpochMilli))
|
||||
:cljs (new js/Date (js/parseInt v 10))))
|
||||
:wfn (comp str inst-ms)}
|
||||
|
||||
{:id "penpot/pointer"
|
||||
@@ -204,12 +201,30 @@
|
||||
(with-open [input (ByteArrayInputStream. ^bytes data)]
|
||||
(t/read (reader input opts))))))
|
||||
|
||||
#?(:cljs
|
||||
(defn- is-date-like?
|
||||
[obj]
|
||||
(and ^boolean (some? obj)
|
||||
^boolean (fn? (.-getTime obj))
|
||||
^boolean (some? (.getTime obj)))))
|
||||
|
||||
#_:clj-kondo/ignore
|
||||
(def ^:private date-write-handler
|
||||
(t/write-handler (constantly "m")
|
||||
(comp str inst-ms)))
|
||||
|
||||
(defn encode-str
|
||||
([data] (encode-str data nil))
|
||||
([data opts]
|
||||
#?(:cljs
|
||||
(let [type (:type opts :json)
|
||||
params {:handlers @write-handler-map}
|
||||
params {:handlers @write-handler-map
|
||||
;; NOTE: this is necessary because the plugin
|
||||
;; secure context alters the js/Date constructor
|
||||
:handlerForForeign (fn [x _]
|
||||
(if (is-date-like? x)
|
||||
date-write-handler
|
||||
nil))}
|
||||
params (if (:with-meta opts)
|
||||
(assoc params :transform t/write-meta)
|
||||
params)
|
||||
|
||||
@@ -14,6 +14,7 @@
|
||||
[app.common.schema :as sm]
|
||||
[app.common.schema.generators :as sg]
|
||||
[app.common.schema.openapi :as-alias oapi]
|
||||
[app.common.time :as ct]
|
||||
[app.common.types.plugins :as ctpg]
|
||||
[clojure.set :as set]
|
||||
[cuerdas.core :as str]))
|
||||
@@ -136,7 +137,7 @@
|
||||
[:name ::sm/text]
|
||||
[:path {:optional true} :string]
|
||||
[:opacity {:optional true} [::sm/number {:min 0 :max 1}]]
|
||||
[:modified-at {:optional true} ::sm/inst]
|
||||
[:modified-at {:optional true} ::ct/inst]
|
||||
[:plugin-data {:optional true} ::ctpg/plugin-data]])
|
||||
|
||||
(def schema:library-color
|
||||
|
||||
@@ -8,6 +8,7 @@
|
||||
(:require
|
||||
[app.common.data :as d]
|
||||
[app.common.schema :as sm]
|
||||
[app.common.time :as-alias ct]
|
||||
[app.common.types.page :as ctp]
|
||||
[app.common.types.plugins :as ctpg]
|
||||
[app.common.types.variant :as ctv]
|
||||
@@ -25,7 +26,7 @@
|
||||
[:id ::sm/uuid]
|
||||
[:name :string]
|
||||
[:path {:optional true} [:maybe :string]]
|
||||
[:modified-at {:optional true} ::sm/inst]
|
||||
[:modified-at {:optional true} ::ct/inst]
|
||||
[:objects {:gen/max 10 :optional true} ctp/schema:objects]
|
||||
[:main-instance-id ::sm/uuid]
|
||||
[:main-instance-page ::sm/uuid]
|
||||
|
||||
@@ -12,6 +12,7 @@
|
||||
[app.common.geom.point :as gpt]
|
||||
[app.common.geom.shapes :as gsh]
|
||||
[app.common.schema :as sm]
|
||||
[app.common.time :as-alias ct]
|
||||
[app.common.types.component :as ctk]
|
||||
[app.common.types.components-list :as ctkl]
|
||||
[app.common.types.pages-list :as ctpl]
|
||||
@@ -39,7 +40,7 @@
|
||||
[::sm/one-of valid-container-types]]
|
||||
[:name :string]
|
||||
[:path {:optional true} [:maybe :string]]
|
||||
[:modified-at {:optional true} ::sm/inst]
|
||||
[:modified-at {:optional true} ::ct/inst]
|
||||
[:objects {:optional true}
|
||||
[:map-of {:gen/max 10} ::sm/uuid :map]]
|
||||
[:plugin-data {:optional true} schema:plugin-data]]))
|
||||
|
||||
@@ -16,7 +16,7 @@
|
||||
[app.common.geom.shapes.tree-seq :as gsts]
|
||||
[app.common.logging :as l]
|
||||
[app.common.schema :as sm]
|
||||
[app.common.time :as dt]
|
||||
[app.common.time :as ct]
|
||||
[app.common.types.color :as ctc]
|
||||
[app.common.types.component :as ctk]
|
||||
[app.common.types.components-list :as ctkl]
|
||||
@@ -34,7 +34,6 @@
|
||||
[app.common.uuid :as uuid]
|
||||
[cuerdas.core :as str]))
|
||||
|
||||
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
;; CONSTANTS
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
@@ -49,8 +48,8 @@
|
||||
"A schema that represents the file media object"
|
||||
[:map {:title "FileMedia"}
|
||||
[:id ::sm/uuid]
|
||||
[:created-at {:optional true} ::sm/inst]
|
||||
[:deleted-at {:optional true} ::sm/inst]
|
||||
[:created-at {:optional true} ::ct/inst]
|
||||
[:deleted-at {:optional true} ::ct/inst]
|
||||
[:name :string]
|
||||
[:width ::sm/safe-int]
|
||||
[:height ::sm/safe-int]
|
||||
@@ -96,9 +95,9 @@
|
||||
[:name :string]
|
||||
[:revn :int]
|
||||
[:vern {:optional true} :int]
|
||||
[:created-at ::sm/inst]
|
||||
[:modified-at ::sm/inst]
|
||||
[:deleted-at {:optional true} ::sm/inst]
|
||||
[:created-at ::ct/inst]
|
||||
[:modified-at ::ct/inst]
|
||||
[:deleted-at {:optional true} ::ct/inst]
|
||||
[:project-id {:optional true} ::sm/uuid]
|
||||
[:team-id {:optional true} ::sm/uuid]
|
||||
[:is-shared {:optional true} ::sm/boolean]
|
||||
@@ -164,7 +163,7 @@
|
||||
:or {create-page true with-data true}}]
|
||||
|
||||
(let [id (or id (uuid/next))
|
||||
created-at (or created-at (dt/now))
|
||||
created-at (or created-at (ct/now))
|
||||
modified-at (or modified-at created-at)
|
||||
features (d/nilv features #{})
|
||||
|
||||
|
||||
@@ -13,7 +13,7 @@
|
||||
[app.common.files.helpers :as cfh]
|
||||
[app.common.schema :as sm]
|
||||
[app.common.schema.generators :as sg]
|
||||
[app.common.time :as dt]
|
||||
[app.common.time :as ct]
|
||||
[app.common.transit :as t]
|
||||
[app.common.types.token :as cto]
|
||||
[app.common.uuid :as uuid]
|
||||
@@ -98,7 +98,7 @@
|
||||
[:type [::sm/one-of cto/token-types]]
|
||||
[:value ::sm/any]
|
||||
[:description {:optional true} :string]
|
||||
[:modified-at {:optional true} ::sm/inst]])
|
||||
[:modified-at {:optional true} ::ct/inst]])
|
||||
|
||||
(declare make-token)
|
||||
|
||||
@@ -118,7 +118,7 @@
|
||||
[& {:as attrs}]
|
||||
(-> attrs
|
||||
(update :id #(or % (uuid/next)))
|
||||
(update :modified-at #(or % (dt/now)))
|
||||
(update :modified-at #(or % (ct/now)))
|
||||
(update :description d/nilv "")
|
||||
(check-token-attrs)
|
||||
(map->Token)))
|
||||
@@ -208,14 +208,14 @@
|
||||
(TokenSet. id
|
||||
new-name
|
||||
description
|
||||
(dt/now)
|
||||
(ct/now)
|
||||
tokens))
|
||||
|
||||
(set-description [_ new-description]
|
||||
(TokenSet. id
|
||||
name
|
||||
(d/nilv new-description "")
|
||||
(dt/now)
|
||||
(ct/now)
|
||||
tokens))
|
||||
|
||||
ITokenSet
|
||||
@@ -231,17 +231,17 @@
|
||||
(TokenSet. id
|
||||
name
|
||||
description
|
||||
(dt/now)
|
||||
(ct/now)
|
||||
(assoc tokens (:name token) token))))
|
||||
|
||||
(update-token [this id f]
|
||||
(if-let [token (token-by-id this id)]
|
||||
(let [token' (-> (make-token (f token))
|
||||
(assoc :modified-at (dt/now)))]
|
||||
(assoc :modified-at (ct/now)))]
|
||||
(TokenSet. id
|
||||
name
|
||||
description
|
||||
(dt/now)
|
||||
(ct/now)
|
||||
(if (= (:name token) (:name token'))
|
||||
(assoc tokens (:name token') token')
|
||||
(-> tokens
|
||||
@@ -254,7 +254,7 @@
|
||||
(TokenSet. id
|
||||
name
|
||||
description
|
||||
(dt/now)
|
||||
(ct/now)
|
||||
(dissoc tokens (:name token)))))
|
||||
|
||||
(get-token [this id]
|
||||
@@ -279,7 +279,7 @@
|
||||
[:id ::sm/uuid]
|
||||
[:name :string]
|
||||
[:description {:optional true} :string]
|
||||
[:modified-at {:optional true} ::sm/inst]
|
||||
[:modified-at {:optional true} ::ct/inst]
|
||||
[:tokens {:optional true
|
||||
:gen/gen (->> (sg/map-of (sg/generator ::sm/text)
|
||||
(sg/generator schema:token))
|
||||
@@ -316,7 +316,7 @@
|
||||
[& {:as attrs}]
|
||||
(let [attrs (-> attrs
|
||||
(update :id #(or % (uuid/next)))
|
||||
(update :modified-at #(or % (dt/now)))
|
||||
(update :modified-at #(or % (ct/now)))
|
||||
(update :tokens #(into (d/ordered-map) %))
|
||||
(update :description d/nilv "")
|
||||
(check-token-set-attrs))]
|
||||
@@ -552,7 +552,7 @@
|
||||
description
|
||||
is-source
|
||||
external-id
|
||||
(dt/now)
|
||||
(ct/now)
|
||||
set-names))
|
||||
|
||||
(enable-set [this set-name]
|
||||
@@ -580,7 +580,7 @@
|
||||
description
|
||||
is-source
|
||||
external-id
|
||||
(dt/now)
|
||||
(ct/now)
|
||||
(conj (disj sets prev-set-name) set-name))
|
||||
this))
|
||||
|
||||
@@ -606,7 +606,7 @@
|
||||
[:description {:optional true} :string]
|
||||
[:is-source {:optional true} :boolean]
|
||||
[:external-id {:optional true} :string]
|
||||
[:modified-at {:optional true} ::sm/inst]
|
||||
[:modified-at {:optional true} ::ct/inst]
|
||||
[:sets {:optional true} [:set {:gen/max 5} :string]]])
|
||||
|
||||
(def schema:token-theme
|
||||
@@ -640,7 +640,7 @@
|
||||
(update :description d/nilv "")
|
||||
(update :is-source d/nilv false)
|
||||
(update :external-id #(or % (str new-id)))
|
||||
(update :modified-at #(or % (dt/now)))
|
||||
(update :modified-at #(or % (ct/now)))
|
||||
(update :sets set)
|
||||
(check-token-theme-attrs)
|
||||
(map->TokenTheme))))
|
||||
@@ -1070,7 +1070,7 @@ Will return a value that matches this schema:
|
||||
(let [theme (dm/get-in themes [group name])]
|
||||
(if theme
|
||||
(let [theme' (-> (make-token-theme (f theme))
|
||||
(assoc :modified-at (dt/now)))
|
||||
(assoc :modified-at (ct/now)))
|
||||
group' (:group theme')
|
||||
name' (:name theme')
|
||||
same-group? (= group group')
|
||||
@@ -1490,7 +1490,7 @@ Will return a value that matches this schema:
|
||||
:is-source (get theme "is-source")
|
||||
:external-id (get theme "id")
|
||||
:modified-at (some-> (get theme "modified-at")
|
||||
(dt/parse-instant))
|
||||
(ct/inst))
|
||||
:sets (into #{}
|
||||
(comp (map key)
|
||||
xf-normalize-set-name
|
||||
|
||||
@@ -8,6 +8,7 @@
|
||||
(:require
|
||||
[app.common.data :as d]
|
||||
[app.common.schema :as sm]
|
||||
[app.common.time :as-alias ct]
|
||||
[app.common.types.plugins :as ctpg]
|
||||
[app.common.types.text :as txt]
|
||||
[app.common.uuid :as uuid]))
|
||||
@@ -31,7 +32,7 @@
|
||||
[:line-height :string]
|
||||
[:letter-spacing :string]
|
||||
[:text-transform :string]
|
||||
[:modified-at {:optional true} ::sm/inst]
|
||||
[:modified-at {:optional true} ::ct/inst]
|
||||
[:path {:optional true} [:maybe :string]]
|
||||
[:plugin-data {:optional true} ::ctpg/plugin-data]]))
|
||||
|
||||
|
||||
@@ -10,7 +10,7 @@
|
||||
[clojure.test :as t]))
|
||||
|
||||
(t/deftest compare-time
|
||||
(let [dta (dt/parse-instant 10000)
|
||||
dtb (dt/parse-instant 20000)]
|
||||
(let [dta (dt/inst 10000)
|
||||
dtb (dt/inst 20000)]
|
||||
(t/is (false? (dt/is-after? dta dtb)))
|
||||
(t/is (true? (dt/is-before? dta dtb)))))
|
||||
|
||||
@@ -12,7 +12,7 @@
|
||||
#?(:clj [clojure.datafy :refer [datafy]])
|
||||
[app.common.data :as d]
|
||||
[app.common.test-helpers.ids-map :as thi]
|
||||
[app.common.time :as dt]
|
||||
[app.common.time :as ct]
|
||||
[app.common.transit :as tr]
|
||||
[app.common.types.tokens-lib :as ctob]
|
||||
[app.common.uuid :as uuid]
|
||||
@@ -20,14 +20,14 @@
|
||||
|
||||
(defn setup-virtual-time
|
||||
[next]
|
||||
(let [current (volatile! (inst-ms (dt/now)))]
|
||||
(with-redefs [dt/now #(dt/parse-instant (vswap! current inc))]
|
||||
(let [current (volatile! (inst-ms (ct/now)))]
|
||||
(with-redefs [ct/now #(ct/inst (vswap! current inc))]
|
||||
(next))))
|
||||
|
||||
(t/use-fixtures :once setup-virtual-time)
|
||||
|
||||
(t/deftest make-token
|
||||
(let [now (dt/now)
|
||||
(let [now (ct/now)
|
||||
token1 (ctob/make-token :id (thi/new-id! :token1)
|
||||
:name "test-token-1"
|
||||
:type :boolean
|
||||
@@ -71,7 +71,7 @@
|
||||
(t/is (= #{"foo" "bar"} (ctob/find-token-value-references "{foo}} + {bar}")))))
|
||||
|
||||
(t/deftest make-token-set
|
||||
(let [now (dt/now)
|
||||
(let [now (ct/now)
|
||||
token-set1 (ctob/make-token-set :name "test-token-set-1")
|
||||
token-set2 (ctob/make-token-set :name "test-token-set-2"
|
||||
:description "test description"
|
||||
@@ -196,7 +196,7 @@
|
||||
(t/is (= (get-in expected ["baz" "boo" :name]) "baz.boo"))))
|
||||
|
||||
(t/deftest make-token-theme
|
||||
(let [now (dt/now)
|
||||
(let [now (ct/now)
|
||||
token-theme1 (ctob/make-token-theme :name "test-token-theme-1")
|
||||
token-theme2 (ctob/make-token-theme :name "test-token-theme-2"
|
||||
:group "group-1"
|
||||
@@ -266,7 +266,7 @@
|
||||
(t/is (= (ctob/set-count tokens-lib') 1))
|
||||
(t/is (= (ctob/get-name token-set') "test-token-set"))
|
||||
(t/is (= (ctob/get-description token-set') "some description"))
|
||||
(t/is (dt/is-after? (ctob/get-modified-at token-set') (ctob/get-modified-at token-set)))))
|
||||
(t/is (ct/is-after? (ctob/get-modified-at token-set') (ctob/get-modified-at token-set)))))
|
||||
|
||||
(t/deftest rename-token-set
|
||||
(let [tokens-lib (-> (ctob/make-tokens-lib)
|
||||
@@ -282,7 +282,7 @@
|
||||
|
||||
(t/is (= (ctob/set-count tokens-lib') 1))
|
||||
(t/is (= (ctob/get-name token-set') "updated-name"))
|
||||
(t/is (dt/is-after? (ctob/get-modified-at token-set') (ctob/get-modified-at token-set)))))
|
||||
(t/is (ct/is-after? (ctob/get-modified-at token-set') (ctob/get-modified-at token-set)))))
|
||||
|
||||
(t/deftest rename-token-set-group
|
||||
(let [tokens-lib (-> (ctob/make-tokens-lib)
|
||||
@@ -403,7 +403,7 @@
|
||||
(t/is (= (ctob/set-count tokens-lib') 1))
|
||||
(t/is (= (count (ctob/get-tokens-map token-set')) 1))
|
||||
(t/is (= (:name token') "test-token"))
|
||||
(t/is (dt/is-after? (ctob/get-modified-at token-set') (ctob/get-modified-at token-set)))))
|
||||
(t/is (ct/is-after? (ctob/get-modified-at token-set') (ctob/get-modified-at token-set)))))
|
||||
|
||||
(t/deftest update-token
|
||||
(let [tokens-lib (-> (ctob/make-tokens-lib)
|
||||
@@ -445,8 +445,8 @@
|
||||
(t/is (= (:name token') "test-token-1"))
|
||||
(t/is (= (:description token') "some description"))
|
||||
(t/is (= (:value token') false))
|
||||
(t/is (dt/is-after? (ctob/get-modified-at token-set') (ctob/get-modified-at token-set)))
|
||||
(t/is (dt/is-after? (:modified-at token') (:modified-at token)))))
|
||||
(t/is (ct/is-after? (ctob/get-modified-at token-set') (ctob/get-modified-at token-set)))
|
||||
(t/is (ct/is-after? (:modified-at token') (:modified-at token)))))
|
||||
|
||||
(t/deftest rename-token
|
||||
(let [tokens-lib (-> (ctob/make-tokens-lib)
|
||||
@@ -479,8 +479,8 @@
|
||||
(t/is (= (:name token') "updated-name"))
|
||||
(t/is (= (:description token') ""))
|
||||
(t/is (= (:value token') true))
|
||||
(t/is (dt/is-after? (ctob/get-modified-at token-set') (ctob/get-modified-at token-set)))
|
||||
(t/is (dt/is-after? (:modified-at token') (:modified-at token)))))
|
||||
(t/is (ct/is-after? (ctob/get-modified-at token-set') (ctob/get-modified-at token-set)))
|
||||
(t/is (ct/is-after? (:modified-at token') (:modified-at token)))))
|
||||
|
||||
(t/deftest delete-token
|
||||
(let [tokens-lib (-> (ctob/make-tokens-lib)
|
||||
@@ -502,7 +502,7 @@
|
||||
(t/is (= (ctob/set-count tokens-lib') 1))
|
||||
(t/is (= (count (ctob/get-tokens-map token-set')) 0))
|
||||
(t/is (nil? token'))
|
||||
(t/is (dt/is-after? (ctob/get-modified-at token-set') (ctob/get-modified-at token-set)))))
|
||||
(t/is (ct/is-after? (ctob/get-modified-at token-set') (ctob/get-modified-at token-set)))))
|
||||
|
||||
(t/deftest get-ordered-sets
|
||||
(let [tokens-lib (-> (ctob/make-tokens-lib)
|
||||
@@ -788,7 +788,7 @@
|
||||
(t/is (= (ctob/theme-count tokens-lib') 2))
|
||||
(t/is (= (:name token-theme') "test-token-theme"))
|
||||
(t/is (= (:description token-theme') "some description"))
|
||||
(t/is (dt/is-after? (:modified-at token-theme') (:modified-at token-theme)))))
|
||||
(t/is (ct/is-after? (:modified-at token-theme') (:modified-at token-theme)))))
|
||||
|
||||
(t/deftest rename-token-theme
|
||||
(let [tokens-lib (-> (ctob/make-tokens-lib)
|
||||
@@ -805,7 +805,7 @@
|
||||
|
||||
(t/is (= (ctob/theme-count tokens-lib') 2))
|
||||
(t/is (= (:name token-theme') "updated-name"))
|
||||
(t/is (dt/is-after? (:modified-at token-theme') (:modified-at token-theme)))))
|
||||
(t/is (ct/is-after? (:modified-at token-theme') (:modified-at token-theme)))))
|
||||
|
||||
(t/deftest delete-token-theme
|
||||
(let [tokens-lib (-> (ctob/make-tokens-lib)
|
||||
@@ -834,7 +834,7 @@
|
||||
token-theme (ctob/get-theme tokens-lib "" "test-token-theme")
|
||||
token-theme' (ctob/get-theme tokens-lib' "" "test-token-theme")]
|
||||
|
||||
(t/is (dt/is-after? (:modified-at token-theme') (:modified-at token-theme)))))
|
||||
(t/is (ct/is-after? (:modified-at token-theme') (:modified-at token-theme)))))
|
||||
|
||||
(t/deftest transit-serialization
|
||||
(let [tokens-lib (-> (ctob/make-tokens-lib)
|
||||
@@ -952,8 +952,8 @@
|
||||
(t/is (= (:name token') "group1.test-token-2"))
|
||||
(t/is (= (:description token') "some description"))
|
||||
(t/is (= (:value token') false))
|
||||
(t/is (dt/is-after? (ctob/get-modified-at token-set') (ctob/get-modified-at token-set)))
|
||||
(t/is (dt/is-after? (:modified-at token') (:modified-at token)))))
|
||||
(t/is (ct/is-after? (ctob/get-modified-at token-set') (ctob/get-modified-at token-set)))
|
||||
(t/is (ct/is-after? (:modified-at token') (:modified-at token)))))
|
||||
|
||||
(t/deftest update-token-in-sets-rename
|
||||
(let [tokens-lib (-> (ctob/make-tokens-lib)
|
||||
@@ -989,8 +989,8 @@
|
||||
(t/is (= (:name token') "group1.updated-name"))
|
||||
(t/is (= (:description token') ""))
|
||||
(t/is (= (:value token') true))
|
||||
(t/is (dt/is-after? (ctob/get-modified-at token-set') (:ctob/get-modified-at token-set)))
|
||||
(t/is (dt/is-after? (:modified-at token') (:modified-at token)))))
|
||||
(t/is (ct/is-after? (ctob/get-modified-at token-set') (:ctob/get-modified-at token-set)))
|
||||
(t/is (ct/is-after? (:modified-at token') (:modified-at token)))))
|
||||
|
||||
(t/deftest move-token-of-group
|
||||
(let [tokens-lib (-> (ctob/make-tokens-lib)
|
||||
@@ -1027,8 +1027,8 @@
|
||||
(t/is (= (:name token') "group2.updated-name"))
|
||||
(t/is (= (:description token') ""))
|
||||
(t/is (= (:value token') true))
|
||||
(t/is (dt/is-after? (ctob/get-modified-at token-set') (ctob/get-modified-at token-set)))
|
||||
(t/is (dt/is-after? (:modified-at token') (:modified-at token)))))
|
||||
(t/is (ct/is-after? (ctob/get-modified-at token-set') (ctob/get-modified-at token-set)))
|
||||
(t/is (ct/is-after? (:modified-at token') (:modified-at token)))))
|
||||
|
||||
(t/deftest delete-token-in-group
|
||||
(let [tokens-lib (-> (ctob/make-tokens-lib)
|
||||
@@ -1053,7 +1053,7 @@
|
||||
(t/is (= (ctob/set-count tokens-lib') 1))
|
||||
(t/is (= (count (ctob/get-tokens-map token-set')) 1))
|
||||
(t/is (nil? token'))
|
||||
(t/is (dt/is-after? (ctob/get-modified-at token-set') (ctob/get-modified-at token-set)))))
|
||||
(t/is (ct/is-after? (ctob/get-modified-at token-set') (ctob/get-modified-at token-set)))))
|
||||
|
||||
(t/deftest update-token-set-in-groups
|
||||
(let [tokens-lib (-> (ctob/make-tokens-lib)
|
||||
@@ -1079,7 +1079,7 @@
|
||||
(t/is (= (d/index-of (keys group1') "S-token-set-2") 0))
|
||||
(t/is (= (ctob/get-name token-set') "group1/token-set-2"))
|
||||
(t/is (= (ctob/get-description token-set') "some description"))
|
||||
(t/is (dt/is-after? (ctob/get-modified-at token-set') (ctob/get-modified-at token-set)))))
|
||||
(t/is (ct/is-after? (ctob/get-modified-at token-set') (ctob/get-modified-at token-set)))))
|
||||
|
||||
(t/deftest rename-token-set-in-groups
|
||||
(let [tokens-lib (-> (ctob/make-tokens-lib)
|
||||
@@ -1105,7 +1105,7 @@
|
||||
(t/is (= (d/index-of (keys group1') "S-updated-name") 0))
|
||||
(t/is (= (ctob/get-name token-set') "group1/updated-name"))
|
||||
(t/is (= (ctob/get-description token-set') ""))
|
||||
(t/is (dt/is-after? (ctob/get-modified-at token-set') (ctob/get-modified-at token-set)))))
|
||||
(t/is (ct/is-after? (ctob/get-modified-at token-set') (ctob/get-modified-at token-set)))))
|
||||
|
||||
(t/deftest move-token-set-of-group
|
||||
(let [tokens-lib (-> (ctob/make-tokens-lib)
|
||||
@@ -1133,7 +1133,7 @@
|
||||
(t/is (nil? (get group1' "S-updated-name")))
|
||||
(t/is (= (ctob/get-name token-set') "group2/updated-name"))
|
||||
(t/is (= (ctob/get-description token-set') ""))
|
||||
(t/is (dt/is-after? (ctob/get-modified-at token-set') (ctob/get-modified-at token-set)))))
|
||||
(t/is (ct/is-after? (ctob/get-modified-at token-set') (ctob/get-modified-at token-set)))))
|
||||
|
||||
(t/deftest delete-token-set-in-group
|
||||
(let [tokens-lib (-> (ctob/make-tokens-lib)
|
||||
@@ -1174,7 +1174,7 @@
|
||||
(t/is (= (:name token-theme') "token-theme-2"))
|
||||
(t/is (= (:group token-theme') "group1"))
|
||||
(t/is (= (:description token-theme') "some description"))
|
||||
(t/is (dt/is-after? (:modified-at token-theme') (:modified-at token-theme)))))
|
||||
(t/is (ct/is-after? (:modified-at token-theme') (:modified-at token-theme)))))
|
||||
|
||||
(t/deftest get-token-theme-groups
|
||||
(let [token-lib (-> (ctob/make-tokens-lib)
|
||||
@@ -1211,7 +1211,7 @@
|
||||
(t/is (= (:name token-theme') "updated-name"))
|
||||
(t/is (= (:group token-theme') "group1"))
|
||||
(t/is (= (:description token-theme') ""))
|
||||
(t/is (dt/is-after? (:modified-at token-theme') (:modified-at token-theme)))))
|
||||
(t/is (ct/is-after? (:modified-at token-theme') (:modified-at token-theme)))))
|
||||
|
||||
(t/deftest move-token-theme-of-group
|
||||
(let [tokens-lib (-> (ctob/make-tokens-lib)
|
||||
@@ -1241,7 +1241,7 @@
|
||||
(t/is (= (:name token-theme') "updated-name"))
|
||||
(t/is (= (:group token-theme') "group2"))
|
||||
(t/is (= (:description token-theme') ""))
|
||||
(t/is (dt/is-after? (:modified-at token-theme') (:modified-at token-theme)))))
|
||||
(t/is (ct/is-after? (:modified-at token-theme') (:modified-at token-theme)))))
|
||||
|
||||
(t/deftest delete-token-theme-in-group
|
||||
(let [tokens-lib (-> (ctob/make-tokens-lib)
|
||||
@@ -1357,7 +1357,7 @@
|
||||
|
||||
#?(:clj
|
||||
(t/deftest export-dtcg-json
|
||||
(let [now (dt/now)
|
||||
(let [now (ct/now)
|
||||
tokens-lib (-> (ctob/make-tokens-lib)
|
||||
(ctob/add-set (ctob/make-token-set :name "core"
|
||||
:tokens {"colors.red.600"
|
||||
@@ -1408,7 +1408,7 @@
|
||||
|
||||
#?(:clj
|
||||
(t/deftest export-parse-dtcg-json
|
||||
(with-redefs [dt/now (constantly #inst "2024-10-16T12:01:20.257840055-00:00")
|
||||
(with-redefs [ct/now (constantly #inst "2024-10-16T12:01:20.257840055-00:00")
|
||||
uuid/next (constantly uuid/zero)]
|
||||
(let [tokens-lib (-> (ctob/make-tokens-lib)
|
||||
(ctob/add-set (ctob/make-token-set :name "core"
|
||||
@@ -1477,7 +1477,7 @@
|
||||
|
||||
#?(:clj
|
||||
(t/deftest export-dtcg-json-with-active-theme-and-set
|
||||
(let [now (dt/now)
|
||||
(let [now (ct/now)
|
||||
tokens-lib (-> (ctob/make-tokens-lib)
|
||||
(ctob/add-set (ctob/make-token-set :name "core"
|
||||
:tokens {"colors.red.600"
|
||||
@@ -1530,7 +1530,7 @@
|
||||
|
||||
#?(:clj
|
||||
(t/deftest export-dtcg-multi-file
|
||||
(let [now (dt/now)
|
||||
(let [now (ct/now)
|
||||
tokens-lib (-> (ctob/make-tokens-lib)
|
||||
(ctob/add-set (ctob/make-token-set :name "some/set"
|
||||
:tokens {"colors.red.600"
|
||||
|
||||
@@ -248,7 +248,7 @@ __metadata:
|
||||
resolution: "common@workspace:."
|
||||
dependencies:
|
||||
concurrently: "npm:^9.1.2"
|
||||
luxon: "npm:^3.6.1"
|
||||
date-fns: "npm:^4.1.0"
|
||||
nodemon: "npm:^3.1.10"
|
||||
source-map-support: "npm:^0.5.21"
|
||||
ws: "npm:^8.18.2"
|
||||
@@ -291,6 +291,13 @@ __metadata:
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"date-fns@npm:^4.1.0":
|
||||
version: 4.1.0
|
||||
resolution: "date-fns@npm:4.1.0"
|
||||
checksum: 10c0/b79ff32830e6b7faa009590af6ae0fb8c3fd9ffad46d930548fbb5acf473773b4712ae887e156ba91a7b3dc30591ce0f517d69fd83bd9c38650fdc03b4e0bac8
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"debug@npm:4, debug@npm:^4, debug@npm:^4.3.4":
|
||||
version: 4.4.1
|
||||
resolution: "debug@npm:4.4.1"
|
||||
@@ -620,13 +627,6 @@ __metadata:
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"luxon@npm:^3.6.1":
|
||||
version: 3.6.1
|
||||
resolution: "luxon@npm:3.6.1"
|
||||
checksum: 10c0/906d57a9dc4d1de9383f2e9223e378c298607c1b4d17b6657b836a3cd120feb1c1de3b5d06d846a3417e1ca764de8476e8c23b3cd4083b5cdb870adcb06a99d5
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"make-fetch-happen@npm:^14.0.3":
|
||||
version: 14.0.3
|
||||
resolution: "make-fetch-happen@npm:14.0.3"
|
||||
|
||||
@@ -114,7 +114,6 @@
|
||||
"js-beautify": "^1.15.4",
|
||||
"lodash": "^4.17.21",
|
||||
"lodash.debounce": "^4.0.8",
|
||||
"luxon": "^3.6.1",
|
||||
"opentype.js": "^1.3.4",
|
||||
"postcss-modules": "^6.0.1",
|
||||
"randomcolor": "^0.6.2",
|
||||
|
||||
@@ -10,11 +10,11 @@
|
||||
[app.common.data.macros :as dm]
|
||||
[app.common.files.changes :as cpc]
|
||||
[app.common.logging :as log]
|
||||
[app.common.time :as ct]
|
||||
[app.common.types.shape-tree :as ctst]
|
||||
[app.common.uuid :as uuid]
|
||||
[app.main.data.helpers :as dsh]
|
||||
[app.main.worker :as mw]
|
||||
[app.util.time :as dt]
|
||||
[beicon.v2.core :as rx]
|
||||
[potok.v2.core :as ptk]))
|
||||
|
||||
@@ -118,7 +118,7 @@
|
||||
source (d/nilv source :local)
|
||||
local? (= source :local)
|
||||
commit {:id commit-id
|
||||
:created-at (dt/now)
|
||||
:created-at (ct/now)
|
||||
:source source
|
||||
:origin (ptk/type origin)
|
||||
:features features
|
||||
|
||||
@@ -10,6 +10,7 @@
|
||||
[app.common.data.macros :as dm]
|
||||
[app.common.geom.point :as gpt]
|
||||
[app.common.schema :as sm]
|
||||
[app.common.time :as ct]
|
||||
[app.common.types.shape-tree :as ctst]
|
||||
[app.common.uuid :as uuid]
|
||||
[app.main.data.event :as ev]
|
||||
@@ -35,8 +36,8 @@
|
||||
[:seqn :int]
|
||||
[:content :string]
|
||||
[:participants ::sm/set-of-uuid]
|
||||
[:created-at ::sm/inst]
|
||||
[:modified-at ::sm/inst]
|
||||
[:created-at ::ct/inst]
|
||||
[:modified-at ::ct/inst]
|
||||
[:position ::gpt/point]
|
||||
[:count-unread-comments {:optional true} :int]
|
||||
[:count-comments {:optional true} :int]])
|
||||
@@ -49,8 +50,8 @@
|
||||
[:owner-id ::sm/uuid]
|
||||
[:owner-fullname {:optional true} ::sm/text]
|
||||
[:owner-email {:optional true} ::sm/email]
|
||||
[:created-at ::sm/inst]
|
||||
[:modified-at ::sm/inst]
|
||||
[:created-at ::ct/inst]
|
||||
[:modified-at ::ct/inst]
|
||||
[:content :string]])
|
||||
|
||||
(def check-comment-thread!
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user