🎉 Add simple telemetry server module.

This commit is contained in:
Andrey Antukh 2020-12-27 22:47:31 +01:00 committed by Alonso Torres
parent 4d9418e620
commit 707fa160e8
12 changed files with 433 additions and 309 deletions

View file

@ -31,6 +31,8 @@
info.sunng/ring-jetty9-adapter {:mvn/version "0.14.1"} info.sunng/ring-jetty9-adapter {:mvn/version "0.14.1"}
seancorfield/next.jdbc {:mvn/version "1.1.613"} seancorfield/next.jdbc {:mvn/version "1.1.613"}
metosin/reitit-ring {:mvn/version "0.5.10"} metosin/reitit-ring {:mvn/version "0.5.10"}
metosin/jsonista {:mvn/version "0.3.0"}
org.postgresql/postgresql {:mvn/version "42.2.18"} org.postgresql/postgresql {:mvn/version "42.2.18"}
com.zaxxer/HikariCP {:mvn/version "3.4.5"} com.zaxxer/HikariCP {:mvn/version "3.4.5"}
@ -76,10 +78,6 @@
mockery/mockery {:mvn/version "0.1.4"}} mockery/mockery {:mvn/version "0.1.4"}}
:extra-paths ["tests"]} :extra-paths ["tests"]}
;; :fn-media-loader
;; {:exec-fn app.cli.media-loader/run
;; :args {}}
:fn-fixtures :fn-fixtures
{:exec-fn app.cli.fixtures/run {:exec-fn app.cli.fixtures/run
:args {}} :args {}}

View file

@ -20,6 +20,7 @@
[clojure.pprint :refer [pprint]] [clojure.pprint :refer [pprint]]
[clojure.repl :refer :all] [clojure.repl :refer :all]
[clojure.spec.alpha :as s] [clojure.spec.alpha :as s]
[clojure.spec.gen.alpha :as sgen]
[clojure.test :as test] [clojure.test :as test]
[clojure.tools.namespace.repl :as repl] [clojure.tools.namespace.repl :as repl]
[clojure.walk :refer [macroexpand-all]] [clojure.walk :refer [macroexpand-all]]
@ -30,6 +31,7 @@
(defonce system nil) (defonce system nil)
;; --- Benchmarking Tools ;; --- Benchmarking Tools
(defmacro run-quick-bench (defmacro run-quick-bench
@ -68,7 +70,7 @@
[] []
(alter-var-root #'system (fn [sys] (alter-var-root #'system (fn [sys]
(when sys (ig/halt! sys)) (when sys (ig/halt! sys))
(-> (main/build-system-config @cfg/config) (-> (main/build-system-config cfg/config)
(ig/prep) (ig/prep)
(ig/init)))) (ig/init))))
:started) :started)

View file

@ -120,6 +120,12 @@
(s/def ::ldap-auth-fullname-attribute ::us/string) (s/def ::ldap-auth-fullname-attribute ::us/string)
(s/def ::ldap-auth-avatar-attribute ::us/string) (s/def ::ldap-auth-avatar-attribute ::us/string)
(s/def ::telemetry-enabled ::us/boolean)
(s/def ::telemetry-url ::us/string)
(s/def ::telemetry-server-enabled ::us/boolean)
(s/def ::telemetry-server-port ::us/integer)
(s/def ::config (s/def ::config
(s/keys :opt-un [::http-server-cors (s/keys :opt-un [::http-server-cors
::http-server-debug ::http-server-debug
@ -150,6 +156,10 @@
::smtp-ssl ::smtp-ssl
::host ::host
::file-trimming-threshold ::file-trimming-threshold
::telemetry-enabled
::telemetry-server-enabled
::telemetry-url
::telemetry-server-port
::debug ::debug
::allow-demo-users ::allow-demo-users
::registration-enabled ::registration-enabled
@ -168,7 +178,7 @@
::ldap-auth-fullname-attribute ::ldap-auth-fullname-attribute
::ldap-auth-avatar-attribute])) ::ldap-auth-avatar-attribute]))
(defn env->config (defn- env->config
[env] [env]
(reduce-kv (reduce-kv
(fn [acc k v] (fn [acc k v]
@ -181,13 +191,13 @@
{} {}
env)) env))
(defn read-config (defn- read-config
[env] [env]
(->> (env->config env) (->> (env->config env)
(merge defaults) (merge defaults)
(us/conform ::config))) (us/conform ::config)))
(defn read-test-config (defn- read-test-config
[env] [env]
(assoc (read-config env) (assoc (read-config env)
:redis-uri "redis://redis/1" :redis-uri "redis://redis/1"
@ -196,31 +206,13 @@
:assets-directory "/tmp/app/static" :assets-directory "/tmp/app/static"
:migrations-verbose false)) :migrations-verbose false))
(def config (def version (v/parse "%version%"))
(delay (read-config env))) (def config (read-config env))
(def test-config (read-test-config env))
(def test-config
(delay (read-test-config env)))
(def default-deletion-delay (def default-deletion-delay
(dt/duration {:hours 48})) (dt/duration {:hours 48}))
(def version
(delay (v/parse "%version%")))
;; (defmethod ig/init-key ::secrets
;; [type {:keys [key] :as opts}]
;; (when (= key "default")
;; (log/warn "Using default SECRET-KEY, system will generate insecure tokens."))
;; {:key key
;; :factory
;; (fn [salt length]
;; (let [engine (bk/engine {:key key
;; :salt (name salt)
;; :alg :hkdf
;; :digest :blake2b-512})]
;; (bk/get-bytes engine length)))})
(prefer-method print-method (prefer-method print-method
clojure.lang.IRecord clojure.lang.IRecord
clojure.lang.IDeref) clojure.lang.IDeref)

View file

@ -9,13 +9,14 @@
(ns app.db (ns app.db
(:require (:require
[app.common.spec :as us]
[app.common.exceptions :as ex] [app.common.exceptions :as ex]
[app.common.geom.point :as gpt] [app.common.geom.point :as gpt]
[app.common.spec :as us]
[app.config :as cfg] [app.config :as cfg]
[app.util.json :as json]
[app.util.migrations :as mg]
[app.util.time :as dt] [app.util.time :as dt]
[app.util.transit :as t] [app.util.transit :as t]
[clojure.data.json :as json]
[clojure.spec.alpha :as s] [clojure.spec.alpha :as s]
[clojure.string :as str] [clojure.string :as str]
[integrant.core :as ig] [integrant.core :as ig]
@ -46,7 +47,7 @@
(s/def ::name ::us/not-empty-string) (s/def ::name ::us/not-empty-string)
(s/def ::min-pool-size ::us/integer) (s/def ::min-pool-size ::us/integer)
(s/def ::max-pool-size ::us/integer) (s/def ::max-pool-size ::us/integer)
(s/def ::migrations fn?) (s/def ::migrations map?)
(s/def ::metrics map?) (s/def ::metrics map?)
(defmethod ig/pre-init-spec ::pool [_] (defmethod ig/pre-init-spec ::pool [_]
@ -55,14 +56,16 @@
(defmethod ig/init-key ::pool (defmethod ig/init-key ::pool
[_ {:keys [migrations] :as cfg}] [_ {:keys [migrations] :as cfg}]
(let [pool (create-pool cfg)] (let [pool (create-pool cfg)]
(when migrations (when (seq migrations)
(with-open [conn (open pool)] (with-open [conn (open pool)]
(migrations conn))) (mg/setup! conn)
(doseq [[mname steps] migrations]
(mg/migrate! conn {:name (name mname) :steps steps}))))
pool)) pool))
(defmethod ig/halt-key! ::pool (defmethod ig/halt-key! ::pool
[_ pool] [_ pool]
(.close ^com.zaxxer.hikari.HikariDataSource pool)) (.close ^HikariDataSource pool))
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; API & Impl ;; API & Impl
@ -72,7 +75,6 @@
(str "SET statement_timeout = 10000;\n" (str "SET statement_timeout = 10000;\n"
"SET idle_in_transaction_session_timeout = 30000;")) "SET idle_in_transaction_session_timeout = 30000;"))
(defn- create-datasource-config (defn- create-datasource-config
[{:keys [metrics] :as cfg}] [{:keys [metrics] :as cfg}]
(let [dburi (:uri cfg) (let [dburi (:uri cfg)
@ -106,7 +108,7 @@
(defn pool-closed? (defn pool-closed?
[pool] [pool]
(.isClosed ^com.zaxxer.hikari.HikariDataSource pool)) (.isClosed ^HikariDataSource pool))
(defn- create-pool (defn- create-pool
[cfg] [cfg]
@ -254,7 +256,7 @@
val (.getValue o)] val (.getValue o)]
(if (or (= typ "json") (if (or (= typ "json")
(= typ "jsonb")) (= typ "jsonb"))
(json/read-str val :key-fn keyword) (json/decode-str val)
val))) val)))
(defn decode-transit-pgobject (defn decode-transit-pgobject
@ -278,7 +280,7 @@
[data] [data]
(doto (org.postgresql.util.PGobject.) (doto (org.postgresql.util.PGobject.)
(.setType "jsonb") (.setType "jsonb")
(.setValue (json/write-str data)))) (.setValue (json/encode-str data))))
(defn pgarray->set (defn pgarray->set
[v] [v]

View file

@ -9,15 +9,11 @@
(ns app.http (ns app.http
(:require (:require
[clojure.pprint] [app.common.spec :as us]
[app.config :as cfg] [app.config :as cfg]
[app.http.auth :as auth] [app.http.auth :as auth]
;; [app.http.auth.gitlab :as gitlab]
[app.http.auth.google :as google]
;; [app.http.auth.ldap :as ldap]
[app.http.errors :as errors] [app.http.errors :as errors]
[app.http.middleware :as middleware] [app.http.middleware :as middleware]
;; [app.http.ws :as ws]
[app.metrics :as mtx] [app.metrics :as mtx]
[clojure.tools.logging :as log] [clojure.tools.logging :as log]
[integrant.core :as ig] [integrant.core :as ig]
@ -27,15 +23,25 @@
(:import (:import
org.eclipse.jetty.server.handler.ErrorHandler)) org.eclipse.jetty.server.handler.ErrorHandler))
(s/def ::handler fn?)
(s/def ::ws (s/map-of ::us/string fn?))
(s/def ::port ::cfg/http-server-port)
(defmethod ig/pre-init-spec ::server [_]
(s/keys :req-un [::handler ::port]
:opt-un [::ws]))
(defmethod ig/init-key ::server (defmethod ig/init-key ::server
[_ {:keys [router ws port] :as opts}] [_ {:keys [handler ws port] :as opts}]
(log/info "Starting http server.") (log/infof "Starting http server on port %s." port)
(let [options {:port port (let [options (merge
{:port port
:h2c? true :h2c? true
:join? false :join? false
:allow-null-path-info true :allow-null-path-info true}
:websockets ws} (when (seq ws)
server (jetty/run-jetty router options) {:websockets ws}))
server (jetty/run-jetty handler options)
handler (doto (ErrorHandler.) handler (doto (ErrorHandler.)
(.setShowStacks true) (.setShowStacks true)
(.setServer server))] (.setServer server))]
@ -45,7 +51,7 @@
(defmethod ig/halt-key! ::server (defmethod ig/halt-key! ::server
[_ server] [_ server]
(log/info "Stoping http server." server) (log/info "Stoping http server.")
(.stop server)) (.stop server))
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

View file

@ -13,7 +13,8 @@
[app.config :as cfg] [app.config :as cfg]
[app.metrics :as mtx] [app.metrics :as mtx]
[app.util.transit :as t] [app.util.transit :as t]
[clojure.data.json :as json] [app.util.json :as json]
;; [clojure.data.json :as json]
[clojure.java.io :as io] [clojure.java.io :as io]
[ring.middleware.cookies :refer [wrap-cookies]] [ring.middleware.cookies :refer [wrap-cookies]]
[ring.middleware.keyword-params :refer [wrap-keyword-params]] [ring.middleware.keyword-params :refer [wrap-keyword-params]]
@ -21,7 +22,7 @@
[ring.middleware.params :refer [wrap-params]] [ring.middleware.params :refer [wrap-params]]
[ring.middleware.resource :refer [wrap-resource]])) [ring.middleware.resource :refer [wrap-resource]]))
(defn- wrap-parse-request-body (defn wrap-parse-request-body
[handler] [handler]
(letfn [(parse-transit [body] (letfn [(parse-transit [body]
(let [reader (t/reader body)] (let [reader (t/reader body)]
@ -70,7 +71,7 @@
(defn- impl-format-response-body (defn- impl-format-response-body
[response] [response]
(let [body (:body response) (let [body (:body response)
type (if (:debug @cfg/config) :json-verbose :json)] type (if (:debug cfg/config) :json-verbose :json)]
(cond (cond
(coll? body) (coll? body)
(-> response (-> response
@ -96,12 +97,12 @@
{:name ::format-response-body {:name ::format-response-body
:compile (constantly wrap-format-response-body)}) :compile (constantly wrap-format-response-body)})
(defn- wrap-errors (defn wrap-errors
[handler on-error] [handler on-error]
(fn [request] (fn [request]
(try (try
(handler request) (handler request)
(catch Throwable e (catch Exception e
(on-error e request))))) (on-error e request)))))
(def errors (def errors
@ -114,6 +115,7 @@
(mtx/wrap-counter handler {:id "http__requests_counter" (mtx/wrap-counter handler {:id "http__requests_counter"
:help "Absolute http requests counter."}))}) :help "Absolute http requests counter."}))})
(def cookies (def cookies
{:name ::cookies {:name ::cookies
:compile (constantly wrap-cookies)}) :compile (constantly wrap-cookies)})
@ -129,34 +131,3 @@
(def keyword-params (def keyword-params
{:name ::keyword-params {:name ::keyword-params
:compile (constantly wrap-keyword-params)}) :compile (constantly wrap-keyword-params)})
(defn- wrap-development-cors
[handler]
(letfn [(add-cors-headers [response]
(update response :headers
(fn [headers]
(-> headers
(assoc "access-control-allow-origin" "http://localhost:3449")
(assoc "access-control-allow-methods" "GET,POST,DELETE,OPTIONS,PUT,HEAD,PATCH")
(assoc "access-control-allow-credentials" "true")
(assoc "access-control-expose-headers" "x-requested-with, content-type, cookie")
(assoc "access-control-allow-headers" "content-type")))))]
(fn [request]
(if (= (:request-method request) :options)
(-> {:status 200 :body ""}
(add-cors-headers))
(let [response (handler request)]
(add-cors-headers response))))))
(def development-cors
{:name ::development-cors
:compile (fn [& _args]
(when *assert*
wrap-development-cors))})
(def development-resources
{:name ::development-resources
:compile (fn [& _args]
(when *assert*
#(wrap-resource % "public")))})

View file

@ -16,18 +16,21 @@
[integrant.core :as ig])) [integrant.core :as ig]))
;; Set value for all new threads bindings. ;; Set value for all new threads bindings.
(alter-var-root #'*assert* (constantly (:enable-asserts @cfg/config))) (alter-var-root #'*assert* (constantly (:enable-asserts cfg/config)))
(derive :app.telemetry/server :app.http/server)
;; --- Entry point ;; --- Entry point
(defn build-system-config (defn build-system-config
[config] [config]
(merge
{:app.db/pool {:app.db/pool
{:uri (:database-uri config) {:uri (:database-uri config)
:username (:database-username config) :username (:database-username config)
:password (:database-password config) :password (:database-password config)
:metrics (ig/ref :app.metrics/metrics) :metrics (ig/ref :app.metrics/metrics)
:migrations (ig/ref :app.migrations/migrations) :migrations (ig/ref :app.migrations/all)
:name "main" :name "main"
:min-pool-size 0 :min-pool-size 0
:max-pool-size 10} :max-pool-size 10}
@ -35,9 +38,16 @@
:app.metrics/metrics :app.metrics/metrics
{} {}
:app.migrations/all
{:uxbox-main (ig/ref :app.migrations/migrations)
:telemetry (ig/ref :app.telemetry/migrations)}
:app.migrations/migrations :app.migrations/migrations
{} {}
:app.telemetry/migrations
{}
:app.redis/redis :app.redis/redis
{:uri (:redis-uri config)} {:uri (:redis-uri config)}
@ -54,7 +64,7 @@
:app.http/server :app.http/server
{:port (:http-server-port config) {:port (:http-server-port config)
:router (ig/ref :app.http/router) :handler (ig/ref :app.http/router)
:ws {"/ws/notifications" (ig/ref :app.notifications/handler)}} :ws {"/ws/notifications" (ig/ref :app.notifications/handler)}}
:app.http/router :app.http/router
@ -175,10 +185,21 @@
:max-age (dt/duration {:hours 12}) :max-age (dt/duration {:hours 12})
:metrics (ig/ref :app.metrics/metrics)} :metrics (ig/ref :app.metrics/metrics)}
:app.srepl/server ;; :app.tasks.telemetry/handler
{:port 6062} ;; {:pool (ig/ref :app.db/pool)}
:app.srepl/server
{:port 6062}}
(when (:telemetry-server-enabled cfg/config true)
{:app.telemetry/handler
{:pool (ig/ref :app.db/pool)
:executor (ig/ref :app.worker/executor)}
:app.telemetry/server
{:port (:telemetry-server-port config 6063)
:handler (ig/ref :app.telemetry/handler)}})))
})
(defmethod ig/init-key :default [_ data] data) (defmethod ig/init-key :default [_ data] data)
(defmethod ig/prep-key :default [_ data] (d/without-nils data)) (defmethod ig/prep-key :default [_ data] (d/without-nils data))
@ -187,7 +208,7 @@
(defn start (defn start
[] []
(let [system-config (build-system-config @cfg/config)] (let [system-config (build-system-config cfg/config)]
(ig/load-namespaces system-config) (ig/load-namespaces system-config)
(alter-var-root #'system (fn [sys] (alter-var-root #'system (fn [sys]
(when sys (ig/halt! sys)) (when sys (ig/halt! sys))
@ -195,7 +216,7 @@
(ig/prep) (ig/prep)
(ig/init)))) (ig/init))))
(log/infof "Welcome to penpot! Version: '%s'." (log/infof "Welcome to penpot! Version: '%s'."
(:full @cfg/version)))) (:full cfg/version))))
(defn stop (defn stop
[] []

View file

@ -11,12 +11,10 @@
(:require (:require
[integrant.core :as ig] [integrant.core :as ig]
[app.db :as db] [app.db :as db]
[app.migrations.migration-0023 :as mg0023] [app.util.migrations :as mg]
[app.util.migrations :as mg])) [app.migrations.migration-0023 :as mg0023]))
(def main-migrations (def migrations
{:name "uxbox-main"
:steps
[{:name "0001-add-extensions" [{:name "0001-add-extensions"
:fn (mg/resource "app/migrations/sql/0001-add-extensions.sql")} :fn (mg/resource "app/migrations/sql/0001-add-extensions.sql")}
@ -118,16 +116,7 @@
{:name "0034-mod-profile-table-add-props-field" {:name "0034-mod-profile-table-add-props-field"
:fn (mg/resource "app/migrations/sql/0034-mod-profile-table-add-props-field.sql")} :fn (mg/resource "app/migrations/sql/0034-mod-profile-table-add-props-field.sql")}
]}) ])
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; (defmethod ig/init-key ::migrations [_ _] migrations)
;; Entry point
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
(defmethod ig/init-key ::migrations
[_ _]
(fn [conn]
(mg/setup! conn)
(mg/migrate! conn main-migrations)))

View file

@ -0,0 +1,116 @@
;; 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/.
;;
;; This Source Code Form is "Incompatible With Secondary Licenses", as
;; defined by the Mozilla Public License, v. 2.0.
;;
;; Copyright (c) 2020 UXBOX Labs SL
(ns app.telemetry
(:require
[clojure.tools.logging :as log]
[app.common.spec :as us]
[app.db :as db]
[app.http.middleware :refer [wrap-parse-request-body wrap-errors]]
[promesa.exec :as px]
[clojure.spec.alpha :as s]
[integrant.core :as ig]
[ring.middleware.keyword-params :refer [wrap-keyword-params]]
[ring.middleware.params :refer [wrap-params]]))
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; Migrations
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
(def sql:create-info-table
"CREATE TABLE telemetry.info (
instance_id uuid,
created_at timestamptz NOT NULL DEFAULT clock_timestamp(),
data jsonb NOT NULL,
PRIMARY KEY (instance_id, created_at)
) PARTITION BY RANGE(created_at);
CREATE TABLE telemetry.info_default (LIKE telemetry.info INCLUDING ALL);
ALTER TABLE telemetry.info
ATTACH PARTITION telemetry.info_default DEFAULT;")
;; Research on this
;; ALTER TABLE telemetry.instance_info
;; SET (autovacuum_freeze_min_age = 0,
;; autovacuum_freeze_max_age = 100000);")
(def sql:create-instance-table
"CREATE TABLE IF NOT EXISTS telemetry.instance (
id uuid PRIMARY KEY,
created_at timestamptz NOT NULL DEFAULT now()
);")
(def migrations
[{:name "0001-add-telemetry-schema"
:fn #(db/exec! % ["CREATE SCHEMA IF NOT EXISTS telemetry;"])}
{:name "0002-add-instance-table"
:fn #(db/exec! % [sql:create-instance-table])}
{:name "0003-add-info-table"
:fn #(db/exec! % [sql:create-info-table])}])
(defmethod ig/init-key ::migrations [_ _] migrations)
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; Router Handler
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
(declare handler)
(declare process-request)
(defmethod ig/init-key ::handler
[_ cfg]
(-> (partial handler cfg)
(wrap-keyword-params)
(wrap-params)
(wrap-parse-request-body)))
(s/def ::instance-id ::us/uuid)
(s/def ::params (s/keys :req-un [::instance-id]))
(defn handler
[{:keys [executor] :as cfg} {:keys [params] :as request}]
(try
(let [params (us/conform ::params params)
cfg (assoc cfg
:instance-id (:instance-id params)
:data (dissoc params :instance-id))]
(px/run! executor (partial process-request cfg)))
(catch Exception e
(log/errorf e "Unexpected error.")))
{:status 200
:body "OK\n"})
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; Request Processing
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
(def sql:insert-instance-info
"insert into telemetry.instance_info (instance_id, data, created_at)
values (?, ?, date_trunc('day', now()))
on conflict (instance_id, created_at)
do update set data = ?")
(defn- process-request
[{:keys [pool instance-id data]}]
(try
(db/with-atomic [conn pool]
(let [data (db/json data)]
(db/exec! conn [sql:insert-instance-info
instance-id
data
data])))
(catch Exception e
(log/errorf e "Error on procesing request."))))

View file

@ -0,0 +1,25 @@
;; 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/.
;;
;; This Source Code Form is "Incompatible With Secondary Licenses", as
;; defined by the Mozilla Public License, v. 2.0.
;;
;; Copyright (c) 2020 UXBOX Labs SL
(ns app.util.json
(:refer-clojure :exclude [read])
(:require
[jsonista.core :as j]))
(defn encode-str
[v]
(j/write-value-as-string v j/keyword-keys-object-mapper))
(defn decode-str
[v]
(j/read-value v j/keyword-keys-object-mapper))
(defn read
[v]
(j/read-value v j/keyword-keys-object-mapper))

View file

@ -293,11 +293,12 @@
(s/def ::cron dt/cron?) (s/def ::cron dt/cron?)
(s/def ::props (s/nilable map?)) (s/def ::props (s/nilable map?))
(s/def ::scheduled-task (s/def ::scheduled-task-spec
(s/keys :req-un [::id ::cron ::fn] (s/keys :req-un [::id ::cron ::fn]
:opt-un [::props])) :opt-un [::props]))
(s/def ::schedule (s/coll-of ::scheduled-task)) (s/def ::schedule
(s/coll-of (s/nilable ::scheduled-task-spec)))
(defmethod ig/pre-init-spec ::scheduler [_] (defmethod ig/pre-init-spec ::scheduler [_]
(s/keys :req-un [::executor ::db/pool ::schedule])) (s/keys :req-un [::executor ::db/pool ::schedule]))
@ -307,7 +308,8 @@
(let [scheduler (Executors/newScheduledThreadPool (int 1)) (let [scheduler (Executors/newScheduledThreadPool (int 1))
cfg (assoc cfg :scheduler scheduler)] cfg (assoc cfg :scheduler scheduler)]
(synchronize-schedule cfg) (synchronize-schedule cfg)
(run! (partial schedule-task cfg) schedule) (run! (partial schedule-task cfg)
(filter some? schedule))
(reify (reify
java.lang.AutoCloseable java.lang.AutoCloseable
(close [_] (close [_]

View file

@ -38,7 +38,7 @@
(defn state-init (defn state-init
[next] [next]
(let [config (-> (main/build-system-config @cfg/test-config) (let [config (-> (main/build-system-config cfg/test-config)
(dissoc :app.srepl/server (dissoc :app.srepl/server
:app.http/server :app.http/server
:app.http/router :app.http/router