A Clojure library in the spirit of temporal.io or uber cadence. Lets you define a function with side effects, and persist/resume the state of the function.
⚠️ use at your own peril, NOT production ready
Two concepts apply:
- Activities: Either a protocol+impl, or a function. Handles side-effects
- Workflows: Functions that orchestrate activities, and are resillient.
If a process crashes, the workflow should be able to safely resume with
at-least-once
semantics
Examples:
Note that when the runtime is javascript, all activities will return a promise. Thus, the use of
promesa.core/let
and/orintemporal.macros/env-let
is advised
(ns intemporal.demo-workflow
(:require [intemporal.store :as store]
[intemporal.workflow :as w]
[intemporal.macros :refer [stub-function stub-protocol defn-workflow]]))
;;;;
;; demo
(defn nested-fn [a]
[a :nested])
(defn activity-fn [a]
(let [f (stub-function nested-fn)]
(conj a :activity (f :sub))))
(defprotocol MyActivities
(foo [this a]))
(defrecord MyActivitiesImpl []
MyActivities
(foo [this a] (println "record was called:" ) [a :child]))
(defn-workflow my-workflow [i]
(let [sf (stub-function activity-fn)
pr (stub-protocol MyActivities {})]
(conj [:root]
(sf [1])
(foo pr :X))))
(def mstore (store/make-memstore))
(def worker (w/start-worker! mstore {`MyActivities (->MyActivitiesImpl)}))
;; note that in cljs, this returns a promise
(def res (w/with-env {:store mstore}
(my-workflow 1)))
(defn pprint-table [table]
(clojure.pprint/print-table table))
(defn print-tables []
(let [tasks (store/list-tasks mstore)
events (->> (store/list-events mstore)
(sort-by :id))]
(pprint-table tasks)
(pprint-table events)))
(print-tables)
- Activites + Workflows
- Pass stub options
- Discard
ActivityOptions
- Protocol options
- Regular fn options
- Discard
- Convert to
.cljc
- workers + queues
- saga
- retries
- signals