Crux modules are (currently) vanilla 1-arg Clojure functions with some optional metadata to specify dependencies and arguments.
By convention, these are named ->your-component
, to signify that it’s returning an instance of your component.
If the value returned implements AutoCloseable
/Closeable
, the module will be closed when the Crux node is stopped.
The most basic component would be just a Clojure function, returning the started module:
(defn ->server [opts]
;; start your server
)
You can specify arguments using the :crux.system/args
metadata key - this example declares a required :port
option, checked against the given spec, defaulting to 3000:
(require '[crux.system :as sys])
(defn ->server {::sys/args {:port {:spec ::sys/int
:doc "Port to start the server on"
:required? true
:default 3000}}}
[{:keys [port] :as options}]
;; start your server
)
You can specify dependencies using :crux.system/deps
- a map of the dependency key to its options.
The options takes the same form as the end-user options - you can specify :crux/module
for the default implementation, as well as any parameters.
The started dependencies are passed to you as part of the function’s parameter, with the args
.
Bear in mind that any options you do specify can be overridden by end-users!
(defn ->server {::sys/deps {:other-module {:crux/module `->other-module
:param "value"}
...}}
[{:keys [other-module]}]
;; start your server
)
You can also use refs - for example, to depend on the Crux node:
(defn ->server {::sys/deps {:crux-node :crux/node}
::sys/args {:spec ::sys/int
:doc "Port to start the server on"
:required? true
:default 3000}}
[{:keys [crux-node] :as options}]
;; start your server
)