funcool/recycle

Name: recycle

Owner: funcool

Description: Clojure library designed to manage application state heavily inspired by stuartsierra's component.

Created: 2017-11-21 16:48:39.0

Updated: 2017-11-21 16:48:58.0

Pushed: 2017-11-23 09:57:57.0

Homepage: null

Size: 23

Language: Clojure

GitHub Committers

UserMost Recent Commit# Commits

Other Committers

UserEmailMost Recent Commit# Commits

README

recycle

WARNING: Project in WIP. Not ready for real world usage.

A tiny (200LOC) Clojure library designed to manage application state heavily inspired by stuartsierra/component.

Api Reference

You can find more in the Api Reference

Why?

Recycle tries to encourage an algebra-interpreter style when designing our programs. The defined application services perform the role of interpreters and the parts of the application consuming those services communicate with then using algebras.

Differences from Component

The main differences from component are:

Usage
uire '[recycle.core :as r])
Services

Services are the main and only entity of the library.

Creating services

Function: service.

A service is created from a specification which is just a map of keywords to values. The whole list of accepted values is described in Options when creating a service.

> (require '[recycle.core :as r])


> (def my-service (r/service {}))
er/my-service
Starting/stopping services

Functions: start, stop, started?, stopped?.

A service can be started/stopped. When starting a service you need to provide a config value (can be anything), this value is supplied to the :start handler of a service which must return the value representing the instance of the service (the default handler does nothing and returns nil as the value for the instance).

> (require '[recycle.core :as r])


> (def my-service (r/service {}))
er/my-service

> (r/start my-service :some-config)


> (r/started? my-service)


> (r/stop my-service)


> (r/started? my-service)
e

> (r/stopped? my-service)

Sending messages to services

Functions: ask, ?.

Services can receive messages, but only if they are running and they were created with a :receive implementation:

> (require '[recycle.core :as r])


> (def my-service (r/service {}))
er/my-service

> (r/ask my-service "World")
ptionInfo called a service that isn't running  clojure.core/ex-info (core.clj:4617)

> (r/start my-service {})


> (r/ask my-service "World")
ptionInfo service do not implement :receive  clojure.core/ex-info (core.clj:4617)

> (def my-service (r/service {:start   (fn [config]
                                         (partial format (:template config)))
                              :receive (fn [this arg]
                                         (this arg))}))
er/my-service

> (r/start my-service {:template "Hello, %s!"})


> (r/ask my-service "World")
lo, World!"
Composing services

Function: service-map

Services can be trivially composed by just wrapping them in other services, but recycle provides a simple combinator service-map to combine several services into one that starts/stops all services concurrenctly and routes messages to those using the key they have in the map. The best feature of using service-map is that the result itself is another service, so all the functions that work with a normal service can be used with combined/nested services.

> (def hello-service (r/service ))
er/hello-service

> (def adder-service (r/service {:start   (fn [config]
                                            +)
                                 :receive (fn [this & args]
                                            (apply this args))}))
er/adder-service

> (def my-service (r/service-map {:hello {:start   (fn [config]
                                                     (partial format (:template config)))
                                          :receive (fn [this arg]
                                                     (this arg))}
                                  :adder {:start   (fn [config] +)
                                          :receive (fn [this & args]
                                                     (apply this args))}}
er/my-service

> (r/start my-service {:template "Hello, %s!"})


> (r/ask my-service :hello "World")
lo, World!"

> (r/ask my-service :adder 1 2 3)

Options when creating a service

The map passed to service may contain any of the following keys in order to perform more interesting functionalities:

Starting services in certain order

DOC TODO

Start and stop parts of the application

DOC TODO

Start the application without certain services

DOC TODO

Swapping service instances

DOC TODO

License

Copyright © 2017, Anler Hernández Peral

Distributed under the BSD 2-Clause License.


This work is supported by the National Institutes of Health's National Center for Advancing Translational Sciences, Grant Number U24TR002306. This work is solely the responsibility of the creators and does not necessarily represent the official views of the National Institutes of Health.