This commit is contained in:
Reid D McKenzie 2020-05-24 01:22:43 -06:00 committed by GitHub
parent a1880d1516
commit eb0ca097aa

View file

@ -1,6 +1,8 @@
# Flowmetal
> That of which servitors are made
> A shining mercurial metal laden with sensors and almost infinitely reconfigurable.
>
> The stuff of which robots and servitors are made.
Flowmetal is a substrate for automation.
It attempts to provide a programming environment wherein programs are durable, evented and asynchronous aimed at what would traditionally be described as scripting or coordination.
@ -68,19 +70,64 @@ In this setup, the Flowmetal interpreters are able to interact with an external
For instance this program would use the external connector stubs to build up interaction(s) with an external system.
```lisp
(defpackage flowmetal.time
(defenum time-unit
"Calendar-independent durations."
+milliseconds+
+seconds+
+hours+
+days+)
(defrecord duration [num : int?, scale : time-unit?]
"A type for representing scalar durations.")
(defn as-milliseconds [d : duration?]
: duration?
"Normalize a duration to a number of milliseconds."
(match d
[(duration x +days+) (duration (* x 24) +hours+)]
[(duration x +hours+) (duration (* x 60) +minutes+)]
[(duration x +minutes+) (duration (* x 60) +seconds+)]
[(duration x +seconds+) (duration (* x 1000) +milliseconds+)]
[(duration x +milliseconds+) d]))
;; A type of one value used to represent an error
(defenum timeout
+timeout+)
(defendpoint with-timeout!
[d : duration?
f : (fn? [] : a)]
: a
)
)
(defpackage com.twitter.wilson
(require
;; The log lets you record status information into a program's trace
[flowmetal.log :refer [log]]
[flowmetal.log
:refer [log!]]
;; The time system lets you put bounds on the implicit awaiting Flowmetal does
[flowmetal.time :refer [with-timeout, timeout?, duration, duration?, sleep]]
[flowmetal.time
:refer [with-timeout!, timeout?, make-duration, duration?, +seconds+, +hours+, sleep!]]
;; JSON. Simple enough
[flowmetal.json :refer [loads, dumps, json?]]
[flowmetal.json
:refer [loads, dumps, json?]]
;; Extensions! Provided by other systems.
;; These two allow for HTTP requests to be made and callbacks to be received.
[http.callback :refer [make-callback, get-callback, callback?]]
[http.request :refer [post, error?, dns-error?, connection-error?, response-error?]])
;;
;; This one allows for an external service to receive HTTP callbacks on Flowmetal's behalf.
[http.callback
:refer [make-callback!, get-callback!, callback?]]
;; This one allows for an external service to make HTTP requests on Flowmetal's behalf.
[http.request
:refer [post!, error?, dns-error?, connection-error?, response-error?]])
(defenum stage
+reboot+
+bios-update+
+reinstall+)
;; FIXME: how to do table optimization?
(defn fib [x]
@ -89,11 +136,18 @@ For instance this program would use the external connector stubs to build up int
[1 1]
[_ (+ (fib (- x 1) (- x 2)))]))
(defn retry-http [f :- (fn [] :- a)
backoff-fn :- (fn [int?] :- duration?) :default (fn [x] (duration (fib x) :seconds))
backoff-count :- int? :default 0]
:- a
"""The implementation of HTTP retrying."""
(defn retry-http [f
: (fn? [] a?)
backoff-fn
: (fn? [int?] duration?)
:default (fn [x : int?]
: duration?
(make-duration (fib x) +seconds+))
backoff-count
: int?
:default 0]
: a
"""The implementation of HTTP with retrying."""
(let [response (f)]
(if (not (error? response))
response
@ -104,16 +158,20 @@ For instance this program would use the external connector stubs to build up int
(do (sleep (backoff-fn backoff-count))
(retry-http* f backoff-fn (+ backoff-count 1)))))))
(defn job [hostname :- str,
stages :- (list? str?),
job-timeout :- duration? :default (duration 3 :hours)]
:- (union timeout? json?)
(defn job [hostname
: str?
stages
: (list? stage?)
job-timeout
: duration?
:default (duration 3 :hours)]
: (union? [timeout? json?])
"""Run a wilson job, wait for the callback and process the result.
By default the job is only waited for three hours.
"""
(let [callback :- callback? (make-callback)
(let [callback : callback? (make-callback!)
job (retry-http
(fn []
(post "http://wilson.local.twitter.com"
@ -123,8 +181,9 @@ For instance this program would use the external connector stubs to build up int
:stages [stages]
:callbacks [{:type :http, :url callback}]}))))]
(let [result (with-timeout (duration 3 :hours)
(get-callback callback))]
(let [result (with-timeout! (duration 3 :hours)
(fn []
(get-callback callback)))]
(if-not (timeout? result)
(loads result)
result))))