Skip to content

Commit

Permalink
fix: pre-commit
Browse files Browse the repository at this point in the history
  • Loading branch information
michael-0acf4 committed Jan 24, 2025
1 parent 3cb9371 commit dbb8443
Showing 1 changed file with 108 additions and 120 deletions.
228 changes: 108 additions & 120 deletions docs/metatype.dev/docs/reference/runtimes/substantial/index.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ Why use it?

- **Long-running "processes"**: Durable tasks that need to run over extended periods (days, weeks or months), handling **retries** and **restarts** seamlessly.
- **Fault-tolerant execution**: Ensure reliable execution of tasks, even upon failures, by maintaining a durable state of the latest run.
- **Task orchestration**: Coordinate complex sequences of workflows (analogous to microservices interactions).
- **Task orchestration**: Coordinate complex sequences of workflows (analogous to microservice interactions).

For example, the workflow below will continue running until a `confirmation` event is sent to the **associated run**.

Expand All @@ -37,7 +37,6 @@ Additionally, if we were to shut down the Typegate node executing it and then re

## Key Concepts


### Backend

This abstraction implements a set of atomic operations that allows Typegate to persist and recover the workflow state. Currently, we have the **Redis** backend available, along with others like **fs** and **memory**, which are primarily intended for development or testing purposes.
Expand All @@ -48,13 +47,13 @@ A special type of function with **durable state** and an execution mechanism dir

#### Persistence and Lifecycle

* **Context**
- **Context**

The context object contains the workflow input (namely `kwargs` as seen in the example above), but it can also be thought as a namespace that contains all of the core functions used for durableness.

It is recreated at every replay.

* **Interrupts**
- **Interrupts**

A special state of the program that is produced by any function that can trigger a workflow **replay**.

Expand All @@ -68,9 +67,9 @@ Any agent (Typegate node) that picks the workflow, will **replay** it, the cycle
await ctx.sleep(24 * 3600 * 1000); // 1 day
```

* **Save**
- **Save**

A save is one of the main building blocks of a workflow, many functions available on the context object relies on it.
A save is one of the main building blocks of a workflow, many functions available on the context object rely on it.

This is mainly because a save call converts any function into a **durable** one: the function output is saved.
This ensures that when a workflow is resumed (after a Typegate reboot for example) or replayed (after interrupts), the saved function will not be executed again.
Expand All @@ -90,11 +89,12 @@ const result = await ctx.save(() => sendEmail());

:::info Notes

* Only JSON-compliant values can be persisted. The execution will throw otherwise.
* Make sure to not rely on changing outside references inside a save call, best is to always expect a replay.
- Only JSON-compliant values can be persisted. The execution will throw otherwise.
- Make sure to not rely on changing outside references inside a save call, best is to always expect a replay.

```typescript
let value = 5;
const afterSave = await save(() => {
const afterSave = await save(() => {
value *= 2;
return save; // 10 will be stored on the Backend
});
Expand All @@ -109,13 +109,11 @@ if (afterSave == 10) {
} else {
throw new Error("Unreachable code");
}

```

:::


* **Send/Receive**
- **Send/Receive**

You can send events to a workflow through GraphQL, any receive call on the workflow will await for it and will **interrupt** the workflow if it hasn't been received yet.

Expand All @@ -133,12 +131,10 @@ g.expose(
<TabItem value="typescript">

```typescript
g.expose(
{
// ..
send: sub.send(t.integer())
}
);
g.expose({
// ..
send: sub.send(t.integer()),
});
```

</TabItem>
Expand All @@ -148,10 +144,7 @@ g.expose(
```graphql
# Client
query {
send(
run_id: "<workflow_run_id>",
event: { name: "myEvent", payload: 1234 }
)
send(run_id: "<workflow_run_id>", event: { name: "myEvent", payload: 1234 })
}
```

Expand All @@ -160,7 +153,7 @@ query {
const value = await ctx.receive<number>("myEvent"); // 1234
```

* **Ensure**
- **Ensure**

It's a function that takes a predicate, and will **interrupt** the workflow so that it will be replayed later if the returned value is false.

Expand All @@ -177,6 +170,98 @@ When a workflow is started, a run is created and Substantial will provide you a

You can send an event or abort an ongoing run from its `run_id`.

### Advanced Filters

In practice, you will have many workflows that have been executed, each run can be in different states. Substantial provides a way to filter the runs.

<SDKTabs>
<TabItem value="python">

```python
g.expose(
# ..
search=sub.advanced_filters()
)
```

</TabItem>
<TabItem value="typescript">

```typescript
g.expose({
// ..
search: sub.advancedFilters(),
});
```

</TabItem>

</SDKTabs>

```graphql
# Client
query {
search(
name: "sendEmail"
filter: {
and: [
{ status: { contains: "\"COMPLETED\"" } }
{ not: { started_at: { lt: "\"2025-01-15T00:00:00Z\"" } } }
{ not: { eq: "null" } }
]
}
) {
run_id
started_at
ended_at
status
value
}
}
```

- **Specification and syntax**

The specification itself is very close to Prisma queries.
You can also refer to your GraphQL playground for guiding you into expressing your query.

Base specification:

```
val ::= json_string
term ::= { eq: val }
| { lt: val } | { lte: val }
| { gt: val } | { gte: val }
| { in: val } | { contains: val }
special_term ::= { started_at: term }
| { ended_at: term }
| { status: term }
expr ::= not | or | and | term | special_term
not ::= { not: expr }
or ::= { or: [expr] }
and ::= { and: [expr] }
```

:::info Notes

- **contains**: Check if the workflow output is a list that contains the given value or if the given value is a substring of it.
- **in**: Check if the workflow output is within a list or is a substring of the given value.
- **status**
- Can be one of `"COMPLETED"`, `"COMPLETED_WITH_ERROR"`, `"ONGOING"` or `"UNKNOWN"`.

For example, the term

```graphql
{ status: { contains: "\"COMPLETED\"" } }
```

..should cover `"COMPLETED"` and `"COMPLETED_WITH_ERROR"`.

::::

## Child workflows

Child workflows are like any other workflows, they are just run by another workflow (parent).
Expand Down Expand Up @@ -358,100 +443,3 @@ typegraph(
</TabItem>

</SDKTabs>



### Advanced Filters

In practice, you will have a lot of workflows that has been executed in different states. Substantial provides a way to filter the runs.

<SDKTabs>
<TabItem value="python">

```python
g.expose(
# ..
search=sub.advanced_filters()
)
```

</TabItem>
<TabItem value="typescript">

```typescript
g.expose(
{
// ..
search: sub.advancedFilters()
}
);
```

</TabItem>

</SDKTabs>

```graphql
# Client
query {
search(
name: "sendEmail",
filter: {
and: [
{ status: { contains: "\"COMPLETED\"" } },
{ not: { started_at: { lt: "\"2025-01-15T00:00:00Z\"" } } },
{ not: { eq: "null" } }
]
}
) {
run_id
started_at
ended_at
status
value
}
}
```

#### Filter spec
The specification itself is very close to Prisma queries.
You can also refer to your GraphQL playground for guiding you into expressing your query.

Base specification:

```
val ::= json_string
term ::= { eq: val }
| { lt: val } | { lte: val }
| { gt: val } | { gte: val }
| { in: val } | { contains: val }
special_term ::= { started_at: term }
| { ended_at: term }
| { status: term }
expr ::= not | or | and | term | special_term
not ::= { not: expr }
or ::= { or: [expr] }
and ::= { and: [expr] }
```

:::info Notes

* `contains`
- Check if the workflow output is a list that contains the given value or if the given value is a substring of it.
* `in`
- Check if the workflow output is within a list or is a substring of the given value.

* `status`
- Can be one of `"COMPLETED"`, `"COMPLETED_WITH_ERROR"`, `"ONGOING"` or `"UNKNOWN"`.

For example, the term
```graphql
{ status: { contains: "\"COMPLETED\"" } }
```

..should cover `"COMPLETED"` and `"COMPLETED_WITH_ERROR"`.

::::

0 comments on commit dbb8443

Please sign in to comment.