Skip to content
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 8 additions & 8 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -17,10 +17,10 @@ There are two problems to address here.
The first problem exists within the context of platforms that provide "Durable Execution".

Most of these platforms force the usage of a "workflow" function and "step" / "activity" functions.
The reason is that the "workflow" function is paired with an event history, qeuue, or journal which is used during a replay of the execution to know where to resume the execution without repeating side-effects.
This is because the 'workflow' function is paired with an event history, queue, or journal that is used during replay of the execution to know where to resume the execution without repeating side-effects.

This separation makes for a messy and expensive process for a Workflow function to directly call itself.
It is messy in that the code is usually overly complicated, and it is expensive in that there multiple events per invocation entered into the history, each of them often requiring a network call.
It is messy in that the code is usually overly complicated, and it is expensive in that there are multiple events per invocation entered into the history, each of them often requiring a network call.
So, how do you have simple, clean, but also durable code?

The second problem is more general, which is how do you cache results for expensive operations and not repeat them?
Expand All @@ -44,19 +44,19 @@ This means that there is no distinction between "workflow" functions and "step"/
And this means it is relatively trivial for a function to call itself recursively without the code looking messy, and without that operation being expensive in terms of bloating an event history and unnecessary network calls.

The second thing to know is that a Durable Promise is a write once register.
A Durable Promise is permanent and once it has a value, it will never change.
A Durable Promise is permanent and once it has a value, its value will never change.

To be a permanent write once register, each Durable Promise must have a unique ID in the system. Therefore the results of Durable Promise become perfectly cacheable, with no cache invalidation required.

Again, consider calculating factorials.
If you ever have to calculate the factorial of 5, you can attach the "factorial-5" promise ID to that invocation.
Once that has been calculated the promise is resolve permanently storing the value inside of it.
Once that has been calculated the promise is resolved, permanently storing the value inside of it.

If any other operation needs the value of factorial 5, it can use the promise ID "factorial-5" and immediately receive the result.

## About this example

This example has a single `factorial()` funtion that calls itself recursively:
This example has a single `factorial()` function that calls itself recursively:

```typescript
function* factorial(ctx: Context, n: number): Generator<any, number, any> {
Expand Down Expand Up @@ -86,13 +86,13 @@ You will see the factorial calculations spread out across the workers, each awai

If you use a large enough number (anything 8 or above), you will see a delay while the final result is calculated.

After, try running the same factorial calculation, or any number less than that, and you will see the calculation complete almost instantly.
Afterward, try running the same factorial calculation, or any number less than that, and you will see the calculation complete almost instantly.

This is because the result of each of the previously calculated factorials has been permanently "cached" in respective Durable Promises.
This is because the result of each of the previously calculated factorials has been permanently "cached" in the corresponding Durable Promises.

You can see from the previous code sample that each invocation corresponds to the id "factorial-n" where n is the number.

So, moving forward, if any other operation in the application needs the result of a factorial, it need only call `factorial()` with the promise ID of `factorial-n` — and any factorial that has already been calculated will provide the result directly from the cached promise ID().
So, moving forward, if any other operation in the application needs the result of a factorial, it only needs to call `factorial()` with the promise ID of `factorial-n` — and any factorial that has already been calculated will provide the result directly from the cached promise ID.

## How to run this example

Expand Down