"If Edison had a needle to find in a haystack, he would proceed at once with the diligence of the bee to examine straw after straw until he found the object of his search." - Nikola Tesla
This is the common basis for some of otto.de's microservices. It is written in clojure using the component framework.
tesla-microservice is used for a number of different services now. Still it is a work in progress. See CHANGES.md for instructions on breaking changes.
The scheduler wraps a thread-pool which can be used for scheduling tasks. It is based on overtones at-at project.
To actually use it you have to pass the :scheduler
as a dependency to the component in which it should be used.
Afterwards you can schedule tasks using the overtone api like this:
(overtone.at-at/every 100 #(println "Hello world") (de.otto.tesla.stateful.scheduler/pool scheduler) :desc "HelloWord Task")
The overtone-pool wrapped by the scheduler can be configured by the config-entry :scheduler
. (See overtone.at-at/mk-pool
)
By default the pool holds no threads.
The app-status indicates the current status of your microservice. To use it you can register a status function to it.
Here is a simple example for a function that checks if an atom is empty or not.
(de.otto.tesla.stateful.app-status/register-status-fun app-status #(status atom))
The app-status
is injected under the keyword :app-status from the base system.
(defn status [atom]
(let [status (if @atom :error :ok)
message (if @atom "Atom is empty" "Atom is not empty")]
(de.otto.status/status-detail :status-id status message)))
For further information and usages take a look at the: status library
As of version 0.1.15
there is no server included any more directly in tesla-microservice.
This gives you the freedom to a) not use any server at all (e.g. for embedded use) b) choose another server e.g. a non-blocking one like httpkit or immutant. The available options are:
Applications build with tesla-microservices
can be configured via
edn
-files, that have to be located in the class path.
For backwards compatibility, it is also possible to load config from properties
-files.
See below for noteworthy differences.
default.edn
is loaded as a resource from classpath if present.application.edn
or overridden by the ENV-variable $CONFIG_FILE
is loaded as a resource or, if that is not possible, from the filesystem.local.edn
is loaded from classpath if present.The configuration hash-map in those files is loaded and merged in the specified order. Which mean configurations for the same key is overridden by the latter occurrence.
In contrast to former versions of tesla-microservice
ENV-variables are not
merged into the configuration.
But you can easily specify ENV-variables, that should be accessible in your configuration:
{
:my-app-secret #ts/env [:my-env-dep-app-secret "default"]
}
ENV-variables are read with environ. To see which keyword represents which ENV-var have a look in their docs.
For backwards compatibility, it is also possible to load config from properties
-files.
You'll have to pass {:property-file-preferred true}
as a runtime config to the base-system.
It is not possible to load individual environment variables when using properties config.
Adding :merge-env-to-properties-config true
to the runtime config will add all system properties
and environment variables, overiding any config from files.
Applications utilizing Tesla-Microservice can use iapetos prometheus client for monitoring.
Metrics are send by reporters which can be configured using the :metrics
keyword.
Each configured reporter will start at system startup automatically.
See example configuration below for all supported reporters.
:metrics {:graphite {:host "localhost"
:port "2003"
:prefix "my.prefix"
:interval-in-s 60
:include-hostname :first-part}
:prometheus {:metrics-path "/metrics"}}
The Tesla-Microservice comes with endpoints that hold information about the internal state of your application. Those endpoints can be the app-status or even metrics (Prometheus, see above). To secure those endpoints you can register the app-status or metrics component in the main system map with an authentication function.
E.g.:
(defn authenticated? [config user password]
(and (= user (:username config)) ; get username from config map -> config map looks like this {:username "username" :password "password"}
(= password (:password config)))) ; get password from config map
(defn example-system [runtime-config]
(-> (de.otto.tesla.system/base-system runtime-config)
(assoc
:app-status (com.stuartsierra.component/using (de.otto.tesla.stateful.app-status/new-app-status authenticated?) [:config ...])
:metering (com.stuartsierra.component/using (de.otto.tesla.stateful.metering/new-metering authenticated?) [:config ...]))
...))
The basis included is stripped to the very minimum. Additional functionality is available as addons:
More features will be released at a later time as separate addons.
Q: Is it any good? A: Yes.
Q: Why tesla? A: It's a reference to the ingenious scientist and inventor.
Q: Are there alternatives? A: Yes. You might want to look at modularity.org, system and duct.
Christian Stamm, Felix Bechstein, Ralf Sigmund, Kai Brandes, Florian Weyandt
Released under Apache License 2.0 license.
Can you improve this documentation?Edit on GitHub
cljdoc is a website building & hosting documentation for Clojure/Script libraries
× close