Liking cljdoc? Tell your friends :D

fancoil

What's the frontend of duct?

You say air conditioning? Oh! Fan Coil Unit.

A clojurescript framework, which uses multi-methods to define and implement system unit, uses integrant to inject configuration and stateful dependencies to unit at system startup.

It is highly inspired by the structure of re-frame and duct.

Installation

[com.github.itarck/fancoil "0.0.3-SNAPSHOT"]    ;  Leiningen/Boot
com.github.itarck/fancoil {:mvn/version "0.0.3-SNAPSHOT"}    ; Clojure CLI/deps.edn

How to use

  • Read the source code: not much, ~100 loc
  • Try some examples here: includes simple clock, todomvc-ratom, todomvc-datascript, cat chat (with backend via http and ws)
  • Read fancoil.module

System structure

Concept

  • System
    • The system has several machines working together, and it is stateful.
    • The system needs to follow a certain order when starting the machines.
  • Machine (unit)
    • Machines have three period: definition, implementation and runtime.
    • When a machine is running, it depends on other machines, and it is stateful.
    • If a machine is not running, it has no state. It is formal function that implements runtime functionality.
  • Plugin
    • Plugin can extend functionality of a machine
  • Module
    • Module can extend the system. Module is a package of a new machine and plugins for its related machines

Types of machine

NameDescSpecDetail
dbstored staterefratom,datascript
chanflow statechannelcore.async.chan
subscribesubscribe reactionref-> reactiontree of reactions
viewview modelmodel -> reactions -> react componentreagent, rum
dispatchdispatch eventevent -> request
taptap modelvalue->valueuser-defined, for handle, pure function
handle!handle! requestrequest -> effectdefault to db-handler
- injectinject co-effectrequest -> requestsupport for multiple co-fx
- handlehandle requestrequest -> responsedb-handler, pure function
- do!do! effectresponse -> effectsupport for multiple fx
servicelong-run for requestgo-loopsupport for sync and async
taskonce/periodic e.g. init process

Life cycle of machine

  • Definition period: in fancoil.base, the type and interface of a machine is defined by defmulti

    (defmulti handle!
        "stateful function
        request in -> effects out
        config: inject, handle, doall!, other resources"
        (fn [config signal & rest] signal))
    
  • Implementation period: in fancoil.plugin, some methods of base are implemented, you can include them. Or you can use defmethod to implement them in your project. Method may call other methods of same multi-fn, as is common in handle and subscribe.

    (defmethod base/handle! :default
      [{:keys [doall! handle inject]} signal req]
      (let [req (inject :ratom/db req)
            resp (handle signal req)]
        (doall! resp)))
    
  • Runtime period: in fancoil.unit, some integrant init-key method is implemented, and integrant will inject the configuration into the machine when it initializes the system

    (defmethod ig/init-key ::handle!
       [_ config]
       (partial base/handle! config))        
    
    (def config 
      {::handle! {:handle (ig/ref ::handle)
                  :inject (ig/ref ::inject)
                 :doall! (ig/ref ::doall!)}
     ;; other config })
    

Features

  • Separation of state: stateful dependencies are injected until last minute
  • More functions: more pure or formal functions
  • Highly configurable: flexibility to change the system structure via integrant config
  • Highly extensible: extend for existing machines via plugins. Or write new integrant unit.
  • Easy to test: use integrant to init parts of the system to do unit tests on the machine

Credits and Thanks

Other notes

  • Request is hash-map, open. when injecting cofx, it will add namespaced key of the injector.
  • Response is hash-map, open. doall! can execute all effects, no guarantee of order. If you need to guarantee the order, use a vector of key-value pairs, or just use fx/doseq

Can you improve this documentation?Edit on GitHub

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

× close