<story><title>The Workflow Pattern</title><url>https://blog.bittacklr.be/the-workflow-pattern.html</url></story><parent_chain><item><author>jiggawatts</author><text>The existence of workflow DSLs seems like a symptom of a systemic weakness in common programming languages.&lt;p&gt;We use languages best suited to writing Windows GUIs or Linux kernels to implement business rules — and then we act surprised when we have to invent an entire language and runtime to solve simple business problems.&lt;p&gt;One missing feature in typical languages is the native ability to have a computation frozen in the middle of a function call and then defrosted and continue as if nothing had happened. The low-level mechanisms are often available already — such as object serialisation — but these primitives never support the serialisation of a call stack or an in-flight computation.&lt;p&gt;We even have compilers that can split up and restructure an async function into a heap object and an associated state machine!&lt;p&gt;What’s the difference between an async function that is &lt;i&gt;awaiting&lt;/i&gt; a slow HTTP call and an async function &lt;i&gt;awaiting&lt;/i&gt; a long-running workflow step? Only that the state machine of the latter is persisted to storage instead of the heap!&lt;p&gt;I always thought it was a bit silly that the async mechanism in modern languages is so myopic and single-purpose. These kinds of high level language transformations ought to be extensible and pluggable so that we could write workflows in a proper programming language and have it look like normal code except for the occasional “await” keyword.&lt;p&gt;PS: The same philosophy could be applied to Java Loom style async programming where threads could be marked as eligible for hibernation, in which case they would be restricted to using data types that can be safely round-tripped by the serialiser.</text></item></parent_chain><comment><author>kodablah</author><text>&amp;gt; I always thought it was a bit silly that the async mechanism in modern languages is so myopic and single-purpose. These kinds of high level language transformations ought to be extensible and pluggable so that we could write workflows in a proper programming language and have it look like normal code except for the occasional “await” keyword.&lt;p&gt;This is how Temporal works. For example, in Python the async event loop is replaced by a durable event loop [0], the JS promises become durable promises, .NET tasks become durable via a custom scheduler, etc. Granted it doesn&amp;#x27;t serialize the stack, it uses event sourcing almost exactly like the article describes, and therefore requires deterministic code for replaying. From the dev POV, it looks like any code can just be frozen in the middle of a function and magically resumed elsewhere.&lt;p&gt;0 - &lt;a href=&quot;https:&amp;#x2F;&amp;#x2F;temporal.io&amp;#x2F;blog&amp;#x2F;durable-distributed-asyncio-event-loop&quot; rel=&quot;nofollow noreferrer&quot;&gt;https:&amp;#x2F;&amp;#x2F;temporal.io&amp;#x2F;blog&amp;#x2F;durable-distributed-asyncio-event-l...&lt;/a&gt;&lt;p&gt;(disclaimer, I work at Temporal and have written some of these distributed coroutine impls)</text></comment>
<story><title>The Workflow Pattern</title><url>https://blog.bittacklr.be/the-workflow-pattern.html</url></story><parent_chain><item><author>jiggawatts</author><text>The existence of workflow DSLs seems like a symptom of a systemic weakness in common programming languages.&lt;p&gt;We use languages best suited to writing Windows GUIs or Linux kernels to implement business rules — and then we act surprised when we have to invent an entire language and runtime to solve simple business problems.&lt;p&gt;One missing feature in typical languages is the native ability to have a computation frozen in the middle of a function call and then defrosted and continue as if nothing had happened. The low-level mechanisms are often available already — such as object serialisation — but these primitives never support the serialisation of a call stack or an in-flight computation.&lt;p&gt;We even have compilers that can split up and restructure an async function into a heap object and an associated state machine!&lt;p&gt;What’s the difference between an async function that is &lt;i&gt;awaiting&lt;/i&gt; a slow HTTP call and an async function &lt;i&gt;awaiting&lt;/i&gt; a long-running workflow step? Only that the state machine of the latter is persisted to storage instead of the heap!&lt;p&gt;I always thought it was a bit silly that the async mechanism in modern languages is so myopic and single-purpose. These kinds of high level language transformations ought to be extensible and pluggable so that we could write workflows in a proper programming language and have it look like normal code except for the occasional “await” keyword.&lt;p&gt;PS: The same philosophy could be applied to Java Loom style async programming where threads could be marked as eligible for hibernation, in which case they would be restricted to using data types that can be safely round-tripped by the serialiser.</text></item></parent_chain><comment><author>wavemode</author><text>The missing feature you&amp;#x27;re describing is monads. They can essentially be a first-class abstraction for computation (among other things). They can represent synchronous computations, computations that can be suspended&amp;#x2F;resumed, computations that might fail with a particular type of exception, or anything in between.</text></comment>