Liking cljdoc? Tell your friends :D

amalgam

Lint and test clojars badge cljdoc badge

Useful utilities and mixtures for com.stuartsierra/component.

There are two categories: functions for configuring and running a system (including stopping it with the JVM), and implementations that turn JVM objects (like a thread pool) into components.

Baseline versions

  • JVM: 21
  • Clojure: 1.12.0

Configure and run systems

It is pretty simple to configure an run a system. The configuration will recursively merge a configuration map into a system map. Any maps are recursively merged. Lists, sets, and vector are non-recursively concatenated. You can specify merge functions to modify this behavior.

Example:

user> (require '[com.stuartsierra.component :as component])
nil

user> (require '[systems.thoughtfull.amalgam :as amalgam])
nil

user> (defrecord Foo
  [actual default]
  component/Lifecycle
  (start [this] (println "value is:" (or actual default)) this)
  (stop [this] this))
user.Foo

user> (defn make-system []
  (component/system-map :foo (map->Foo {:default 5})))
#'user/make-system

user> (amalgam/start-system make-system (constantly {:foo {:actual 10}}))
value is: 10
{:foo {:actual 10, :default 5}}

user> (amalgam/start-system make-system (constantly {}))
value is: 5
{:foo {:actual nil, :default 5}}

There is also run-system which starts the system, installs a JVM shutdown hook, and blocks waiting for the JVM to shutdown, then it stops the system.

Thread pool executors

There are defrecords that implement both component/Lifecycle and JVM executor interfaces. You can use the components in your system and when started they will start an execuctor and when stopped they will stop the executor, meanwhile they are executors because the implement the appropriate Java interfaces.

There are implementations for java.util.concurrent.ThreadPoolExecutor and java.util.concurrent.ScheduledThreadPoolExecutor.

Data source

data-source will create a component that when started creates a javax.sql.DataSource that can be injected as a dependency and if the wrapped DataSource is AutoCloseable it is closed when the component stops.

Other fun stuff

Vector

vector creates a vector component that collects its dependencies into a vector.

Example:

user> (-> (component/system-map :v (amalgam/vector :a :b) :a 1 :b 2) component/start :v)
[1 2]

Function

function creates a component that collects its dependencies and when started gives them as the first argument to a function.

Example:

user> (def f (component/using (amalgam/function [deps c] (assoc deps :c c)) [:a :b]))
#'user/f
user> (def system (-> (component/system-map :f f :a 1 :b 2) component/start))
#'user/system
user> ((:f system) 3)
{:a 1, :b 2, :c 3}

function* does the same, but will wrap an existing function.

License

Copyright © technosophist

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.

Can you improve this documentation?Edit on GitHub

cljdoc is a website building & hosting documentation for Clojure/Script libraries

× close