What He Saw Before His Wings Melted
Long before he flew too high, before the wax gave way and the world remembered only his fall, Icarus flew low. They often leave out this part of his misadventures, when curiosity, not hubris, guided his wings. He flew not to ascend to Olympus, but rather to get a good view of the lesser known Asynctopolis.
A city pulsing with signals, stitched together by invisible threads. From above, its patterns unfolded like a diagram. Flows of information, agents in silent collaboration, each unaware of the others, yet perfectly aligned.
This is what he saw.
Asynctopolis from the Clouds
def asynctopolis (flow/create-flow asynctopolis/config)) (
nil {:show-chans false
(show/flow-svg asynctopolis :with-content false})
He circled the skyline. He watched the channels breathe. And slowly, he spiraled down, drawn not by ambition, but fascination— closer to each process, each transformation, each role in the great asynchronous allegiance.
As he flew lower he saw that processes are connected via channels.
nil {:chans-as-ports true
(show/flow-svg asynctopolis :with-content false})
Are channels attached to a process, or are they part of it? You can choose to visualize them as distinct connectors, or as embedded roles within each process. Both perspectives reveal useful insights.
nil {:chans-as-ports false
(show/flow-svg asynctopolis :with-content false})
Wanting to see more, Icarus swooped even lower to survey the processes.
(show/proc-table asynctopolis)
process | start params | in chans | out chans |
---|---|---|---|
Tallystrix |
min: 1
Min value, alert if lower
max: 10
Max value, alert if higher
|
stat: Channel to receive stat values
poke: Channel to poke when it is time to report a window of data to the log
|
alert: Notify of value out of range {:val value, :error :high|:low
|
Chronon |
wait: 3000
Time to wait between pokes
|
out: Poke channel, will send true when the alarm goes off
|
|
Claxxus |
prefix: Alert:
Log message prefix
|
in: Channel to receive messages
|
|
Randomius |
min: 0
Min value to generate
max: 12
Max value to generate
wait: 500
Time in ms to wait between generating
|
out: Output channel for stats
|
With a clearer understanding of the processes, he pondered how these processes are connected.
(show/conn-table asynctopolis)
source | target |
---|---|
Randomius_out | Tallystrix_stat |
Chronon_out | Tallystrix_poke |
Tallystrix_alert | Claxxus_in |
In doing so he realized there are also 2 global channels, report
and error
:
nil {:chans-as-ports false
(show/flow-svg asynctopolis :with-content false
:show-global-chans true})
Any process can put messages on report
and error
.
Street Level
Reaching street level, he called out start
! The flow responded, handing him report and error channels in a map.
def chs (flow/start asynctopolis)) (
Randomius initialing
Tallystrix initializing
Chronon initializing
Claxxus initializing
But still, nothing stirred. So he yelled resume
!
(flow/resume asynctopolis)
true
def report-chan (:report-chan chs)) (
(async/poll! report-chan)
nil
:Tallystrix :poke] [true]) (flow/inject asynctopolis [
#object [FutureTask]
:Tallystrix :stat] ["abc1000"]) (flow/inject asynctopolis [
Claxxus transitioning :clojure.core.async.flow/resume
Tallystrix transitioning :clojure.core.async.flow/resume
Chronon transitioning :clojure.core.async.flow/resume
Chronon running
Randomius transitioning :clojure.core.async.flow/resume
Talon, set flight!
#object [FutureTask]
:chans-as-ports false
(show/flow-svg asynctopolis chs {:with-content false})
Chronon transforms :alarm true to :out
SQUARK: 9
Tallystrix transforming :poke true
Randomius transform 9 from :stat to :out
Tallystrix transforming :stat abc1000
Tallystrix transforming :stat 9
Tallystrix transforming :poke true
Tallystrix takes only numbers, "abc1000"
was not acceptable.
Conclusion
(flow/stop asynctopolis)
Tallystrix transitioning :clojure.core.async.flow/stop
Randomius transitioning :clojure.core.async.flow/stop
Talon, rest!
true
1) (Thread/sleep
Claxxus transitioning :clojure.core.async.flow/stop
Chronon transitioning :clojure.core.async.flow/stop
Chronon rests.
nil
Icarus realized that Flow is a library for building concurrent, event-driven systems out of simple, communication-free functions. Processes connect through channels. You define the structure as a directed graph. Flow takes care of orchestration. Flows are data-driven, easy to inspect, reason about and visualize. Then he wondered just how high could he fly?
Happy flowing, and keep your feathers waxed!