-
Notifications
You must be signed in to change notification settings - Fork 160
/
cli.clj
93 lines (76 loc) · 3.53 KB
/
cli.clj
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
(ns crux.cli
(:require [clojure.edn :as edn]
[clojure.pprint :as pp]
[clojure.tools.cli :as cli]
[clojure.tools.logging :as log]
[crux.node :as n]
[crux.config :as cc]
[crux.io :as cio]
[clojure.java.io :as io])
(:import (java.io Closeable File)))
(def default-options
{:crux.node/topology '[crux.standalone/topology crux.http-server/module]
:crux.kv/db-dir "db-dir"})
(defn- if-it-exists [^File f]
(when (.exists f)
f))
(def cli-options
[["-e" "--edn-file EDN_FILE" "EDN file to load Crux options from"
:parse-fn io/file
:validate [if-it-exists "EDN file doesn't exist"]]
["-p" "--properties-file PROPERTIES_FILE" "Properties file to load Crux options from"
:parse-fn io/file
:validate [if-it-exists "Properties file doesn't exist"]]
["-x" "--extra-edn-options EDN_OPTIONS" "Extra options as an quoted EDN map."
:default nil
:parse-fn edn/read-string]
["-h" "--help"]])
(defn parse-args [args]
(let [{:keys [options errors summary] :as parsed-opts} (cli/parse-opts args cli-options)]
(cond
(seq errors) {::errors errors}
(:help options) {::help summary}
:else (let [{:keys [edn-file properties-file extra-edn-options]} options]
{::node-opts (merge default-options
(or (some-> edn-file (cc/load-edn))
(some-> properties-file (cc/load-properties))
(some-> (io/file "crux.edn") if-it-exists (cc/load-edn))
(some-> (io/file "crux.properties") if-it-exists (cc/load-properties))
(some-> (io/resource "crux.edn") (cc/load-edn))
(some-> (io/resource "crux.properties") (cc/load-properties)))
extra-edn-options)}))))
(defn- options->table [options]
(with-out-str
(pp/print-table (for [[k v] options]
{:key k :value v}))))
(defn- shutdown-hook-promise []
;; NOTE: This isn't registered until the node manages to start up
;; cleanly, so ctrl-c keeps working as expected in case the node
;; fails to start.
(let [main-thread (Thread/currentThread)
shutdown? (promise)]
(.addShutdownHook (Runtime/getRuntime)
(Thread. (fn []
(let [shutdown-ms 10000]
(deliver shutdown? true)
(shutdown-agents)
(.join main-thread shutdown-ms)
(when (.isAlive main-thread)
(log/warn "could not stop node cleanly after" shutdown-ms "ms, forcing exit")
(.halt (Runtime/getRuntime) 1))))
"crux.shutdown-hook-thread"))
shutdown?))
(defn start-node-from-command-line [args]
(cio/install-uncaught-exception-handler!)
(let [{::keys [errors help node-opts]} (parse-args args)]
(cond
errors (binding [*out* *err*]
(doseq [error errors]
(println error))
(System/exit 1))
help (println help)
:else (let [{:keys [version revision]} n/crux-version]
(log/infof "Crux version: %s revision: %s" version revision)
(log/info "options:" (options->table node-opts))
(with-open [node (n/start node-opts)]
@(shutdown-hook-promise))))))