Тема
Когда нужна оркестрация
Оркестрация нужна, когда одна пользовательская операция состоит из нескольких асинхронных шагов с зависимостями.
Пример оформления заказа:
- получить актуальную корзину;
- параллельно получить адрес и способы оплаты;
- зарезервировать товар;
- провести платёж;
- если платёж упал — снять резерв.
WorkflowStore управляет порядком, прогрессом, отменой, checkpoint и компенсацией.
Что WorkflowStore не делает
WorkflowStore не должен выполнять Axios напрямую. Каждый node вызывает уже готовый domain store:
ts
const workflow = new WorkflowStore({
nodes: [
{
id: "profile",
execute: async () => profileStore.fetch(),
},
],
})Так loading, error normalization, cache и cancellation HTTP-операции остаются в Query Layer stores.
Когда workflow не нужен
Не создавайте workflow для одного запроса:
ts
await profileStore.fetch()Обычный async method также понятнее для двух строго последовательных операций без progress, retry recovery и compensation.
Workflow оправдан, если нужны несколько пунктов:
- граф зависимостей;
- параллельные независимые шаги;
- условные nodes;
- общий observable progress;
- отмена всей операции;
- compensation уже выполненных шагов;
- восстановление после reload.
Основные понятия
| Термин | Значение |
|---|---|
| Workflow | Вся составная операция. |
| Node | Один именованный шаг. |
| Dependency | Node, который должен завершиться раньше. |
| Execution level | Независимые nodes, которые можно запустить параллельно. |
| Result | Значение, возвращённое node. |
| Condition | Условие, может ли node выполняться. |
| Compensation | Обратное действие после ошибки следующего шага. |
| Checkpoint | Сохранённые completed node ids и serializable results. |
Простейший workflow
ts
import { WorkflowStore } from "@dubium/query-layer/orchestration"
const bootstrapWorkflow = new WorkflowStore({
nodes: [
{
// Уникальное имя результата.
id: "profile",
// Node вызывает domain store, а не Axios.
execute: async () => profileStore.fetch(),
},
{
id: "permissions",
execute: async () => permissionsStore.fetch(),
},
],
// Одновременно работает не больше двух nodes.
concurrency: 2,
})
const results = await bootstrapWorkflow.execute()
const profile = results.get("profile")
const permissions = results.get("permissions")У nodes нет dependencies, поэтому они находятся на одном execution level и могут выполняться параллельно.
Observable state
ts
workflow.status
// idle | running | success | error | cancelled
workflow.progress
// { nodeId, status, completed, total } | null
workflow.results
// ReadonlyMap<string, unknown>
workflow.error
// unknownWorkflowStore сам является MobX-store. React-компонент оборачивается в observer и читает эти поля.
Порядок изучения
- WorkflowStore — полный пример и API.
- Узлы и зависимости — DAG, conditions, results.
- Ошибки и компенсация — rollback составной операции.
- Checkpoint — восстановление после reload.
- React и тестирование — UI progress и tests.