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
)