diff --git a/docs/meta/backlog.md b/docs/meta/backlog.md index b8ec1a2..a510fdc 100644 --- a/docs/meta/backlog.md +++ b/docs/meta/backlog.md @@ -4,7 +4,7 @@ This backlog is prioritized by user impact and frequency of complaints based on gap analysis from 161 issues across elsa-studio and elsa-gitbook. -## Slice Inventory (2026-06-19) +## Slice Inventory (2026-06-20) This inventory reflects the current GitBook contents before selecting the next automation slice. "Covered" means the repository now includes a @@ -35,7 +35,7 @@ acceptance criterion below is already complete. - `DOC-022` Scaling and performance - `DOC-024` MassTransit communication - `DOC-040` Timer and scheduled workflows -- `DOC-042` Bulk dispatch workflows activity +- `DOC-053` Alterations operational guide hardening - `DOC-028` Studio customization - `DOC-029` Custom UI hints - `DOC-030` Custom UI components @@ -52,25 +52,25 @@ acceptance criterion below is already complete. - `DOC-027` Execution model - `DOC-038` Distributed tracing - `DOC-039` Performance tuning +- `DOC-042` Bulk dispatch workflows activity - `DOC-043` Hangfire integration - `DOC-047` API reference - `DOC-048` Activity reference -- `DOC-053` Alterations operational guide hardening ### Current run selection -- `DOC-042` Bulk dispatch workflows activity: add a release-backed guide that - explains fan-out child workflow dispatch, item-to-input mapping, - `WaitForCompletion`, per-child ports, and how the activity differs from the - REST bulk-dispatch endpoint. +- `DOC-053` Alterations operational guide hardening: rewrite the alterations + pages around the actual `release/3.8.0` execution modes, built-in alteration + types, plan lifecycle, Studio surfaces, persistence options, and shipped HTTP + endpoints including bulk retry. ### Recommended next slice -- `DOC-025` Long-running workflows: the new scheduling guide now explains - timers and durable resumes, but the docs still lack one release-backed guide - that connects bookmarks, timers, incidents, cancellation, persistence, - background execution, and operator troubleshooting into a full workflow - lifecycle narrative. +- `DOC-019` HTTP endpoint security: the HTTP workflow guides now explain how + to build endpoints, but the auth surface is still spread across multiple + pages. A single release-backed guide should connect `Authorize`, + `HttpEndpoint`, API permissions, public vs authenticated endpoints, and + Studio-facing troubleshooting. ### Newly discovered follow-on topics @@ -84,35 +84,27 @@ acceptance criterion below is already complete. - `DOC-052` Workflow state and journal API cookbook: add an operations-facing guide for inspecting workflow state, filtered journal entries, activity executions, and variable mutation endpoints when diagnosing live instances. -- `DOC-054` Messaging transport decision guide: document when to use - MassTransit message-type activities, the Azure Service Bus activity module, - or MassTransit-backed workflow dispatching so teams do not conflate three - different messaging integration paths. +- `DOC-054` Messaging transport selection and topology guide: add a focused + cross-cutting guide that helps architects choose between MassTransit, + Azure Service Bus, and Kafka extensions, and explains when to use + workflow-trigger activities vs runtime dispatchers vs custom consumers. ### Current run result -- `DOC-040` Timer and scheduled workflows: completed in this run by adding a - dedicated guide for `Delay`, `StartAt`, `Timer`, and `Cron`, and grounding - the scheduling model in `DefaultBookmarkScheduler`, `ResumeWorkflowTask`, - `LocalScheduler`, and Quartz-backed scheduler configuration from - `release/3.8.0`. -- `DOC-042` Bulk dispatch workflows activity: completed in this run by adding - a dedicated guide for `BulkDispatchWorkflows`, clarifying item input mapping, - wait-vs-fire-and-forget behavior, per-child completion and fault ports, - channel dispatch, and the difference between in-workflow bulk dispatch and - the `/workflow-definitions/{definitionId}/bulk-dispatch` API endpoint. +- `DOC-053` Alterations operational guide hardening: completed in this run by + aligning the overview, alteration plans, and immediate execution guides with + `release/3.8.0` behavior, including Studio's alterations module, the + built-in `Cancel` alteration, persistence and dispatcher configuration, the + `run:alterations` permission surface, and the shipped `/alterations/run`, + `/alterations/submit`, `/alterations/dry-run`, and + `/alterations/workflows/retry` endpoints. ## Critical Priority (Must Have - Block Users) ### Current slice note - `DOC-053` Alterations operational guide hardening: - `features/alterations` is present, but the current pages are not fully - release-backed. Examples still use pre-filter plan payloads, omit the built-in - `Cancel` alteration, describe `/alterations/run` as requiring manual resume - dispatch even though the endpoint already dispatches successful instances with - scheduled work, and do not explain the Studio alterations surface or the - persistence/dispatcher options available in `release/3.8.0`. + completed on 2026-06-20. ### DOC-001: V2 to V3 Migration Guide - **Persona**: Backend Integrator, Architect diff --git a/features/alterations/README.md b/features/alterations/README.md index 41e8f0e..030fd52 100644 --- a/features/alterations/README.md +++ b/features/alterations/README.md @@ -4,6 +4,17 @@ An [alteration](../../getting-started/concepts/#alteration) represents a change Using alterations, you can change the state of a running workflow instance without republishing the workflow definition. In `release/3.8.0`, Elsa exposes alterations through server APIs and Elsa Studio. +## What Elsa ships in `release/3.8.0` + +Enabling `UseAlterations()` adds: + +* the built-in `Elsa.Alterations.ExecuteAlterationPlan` system workflow used to execute submitted plans +* REST endpoints under `/alterations` +* in-memory alteration plan and job stores by default +* an in-memory background dispatcher for alteration jobs by default + +All alteration APIs shown on this page require the `run:alterations` permission. + ## When to use alterations Use alterations when you need to correct or steer existing workflow instances. Typical examples include: @@ -35,15 +46,34 @@ Use these pages for each mode: * [Alteration Plans](alteration-plans/README.md) * [Applying Alterations](applying-alterations/README.md) +### Which mode fits which job + +| Situation | Use | +| --- | --- | +| You already know the exact workflow instance IDs and need the response now | `POST /alterations/run` or `IAlterationRunner` | +| You need Elsa to find matching workflow instances from filters and process them in the background | alteration plans | +| You need to retry faulted activities across one or more instances | `POST /alterations/workflows/retry` | +| You want designers or operators to stage a bulk plan visually in Studio | Elsa Studio alterations module | + ## Elsa Studio Elsa Studio in `release/3.8.0` includes an alterations module. When the backend Alterations feature is enabled, Studio shows an **Alterable instances** page and adds **Alter** actions for running workflow instances. -Studio currently focuses on altering individual running instances. For bulk operations across many instances, use alteration plans and their filter-based API. +Studio exposes: + +* an **Alterations** top-level menu with plan and instance views +* an **Alterable instances** page that lists non-system running workflow instances +* an alteration designer for staging the five built-in alteration types against an instance +* plan details pages that show plan status, generated jobs, and per-job logs +* quick **Alter** actions from workflow-instance screens + +Studio currently focuses on staging or inspecting plans around individual running instances. For cross-instance bulk operations, use alteration plans and their filter-based API. ## Persistence and dispatch options -By default, Alterations uses in-memory stores and an in-memory background dispatcher. For durable or multi-node deployments, configure persistence for alteration plans and jobs: +By default, Alterations uses in-memory stores and an in-memory background dispatcher. That is fine for local development, but plans and jobs are not durable across process restarts. + +For durable or multi-node deployments, configure persistence for alteration plans and jobs: ```csharp services.AddElsa(elsa => elsa.UseAlterations(alterations => @@ -69,3 +99,13 @@ services.AddElsa(elsa => elsa.UseAlterations(alterations => alterations.UseMassTransitDispatcher(); })); ``` + +Use the MassTransit dispatcher when alteration jobs should survive node boundaries or be processed by worker nodes connected through MassTransit. The dispatcher replaces the default in-memory background queue for alteration jobs only; it does not change how the immediate `/alterations/run` endpoint executes. + +## Operational notes + +* Submitted plans create one alteration job per matched workflow instance. +* If a submitted plan matches no instances, Elsa still stores the plan but generates no jobs. +* `/alterations/run` dispatches successful workflow instances that still have scheduled work after the alterations finish. +* `IAlterationRunner` by itself does not dispatch scheduled work; pair it with `IAlteredWorkflowDispatcher` when you call the service directly. +* The built-in bulk retry endpoint schedules faulted activities by creating `ScheduleActivity` alterations and then dispatching the affected instances. diff --git a/features/alterations/alteration-plans/README.md b/features/alterations/alteration-plans/README.md index 3cc8bbd..7f00902 100644 --- a/features/alterations/alteration-plans/README.md +++ b/features/alterations/alteration-plans/README.md @@ -15,6 +15,19 @@ In `release/3.8.0`, `IAlterationPlanScheduler` accepts `AlterationPlanParams`, w * `filter`: an `AlterationWorkflowInstanceFilter` describing which workflow instances to target * `id`: an optional plan ID; Elsa generates one when omitted +## What happens when you submit a plan + +Submitting a plan does not run the alterations inline with the request. Elsa instead: + +1. stores or generates the plan ID +2. dispatches the built-in `Elsa.Alterations.ExecuteAlterationPlan` system workflow +3. stores the plan +4. finds matching workflow instances from the filter +5. creates one alteration job per matching instance +6. dispatches those jobs through the configured alteration job dispatcher + +This is why alteration plans are the right fit for bulk operational work, scheduled worker processing, and cases where you need job-level inspection later. + ### Creating Alteration Plans To create an alteration plan in code, create an `AlterationPlanParams` instance: @@ -39,6 +52,19 @@ var plan = new AlterationPlanParams The workflow-instance filter supports more than explicit instance IDs. In `release/3.8.0`, you can also filter by correlation IDs, names, search term, definition IDs, definition version IDs, statuses, sub-statuses, incidents, system-workflow flag, activity filters, and timestamp filters. +### Filter guidance + +Use explicit `workflowInstanceIds` when you already know the exact targets but still want background execution and plan tracking. + +Use broader filters when you are operating on a live slice of runtime state, for example: + +* all running instances of a specific workflow definition +* instances with incidents +* instances waiting in a specific sub-status +* instances created, updated, or finished in a specific time range + +Use `POST /alterations/dry-run` before submitting a broad filter so you can confirm which instance IDs Elsa would target. + ### Submitting Alteration Plans To submit an alteration plan, use the `IAlterationPlanScheduler` service. For example: @@ -65,3 +91,30 @@ var jobs = (await store.FindManyAsync(new AlterationJobFilter { PlanId = planId ``` If the filter matches no workflow instances, Elsa still stores the plan, but it does not create jobs. + +## Plan status and job status + +The plan and job records are separate on purpose: + +* the plan tells you whether Elsa accepted and processed the bulk request +* the jobs tell you what happened for each targeted workflow instance + +Use plan timestamps plus per-job logs to answer operational questions such as: + +* did Elsa find any matching instances +* which instances failed +* which alteration inside the plan failed for a specific instance +* whether a plan has finished creating and dispatching its jobs + +## Elsa Studio workflow + +In Studio, the alterations designer submits the same `AlterationPlanParams` payload used by the server API. + +After submission, Studio navigates to a plan details page that shows: + +* the stored plan payload +* current plan status +* generated jobs +* per-job log entries + +This is the fastest path for operators who want plan visibility without scripting the REST API directly. diff --git a/features/alterations/alteration-plans/rest-api.md b/features/alterations/alteration-plans/rest-api.md index ec8884f..e541c4e 100644 --- a/features/alterations/alteration-plans/rest-api.md +++ b/features/alterations/alteration-plans/rest-api.md @@ -2,6 +2,8 @@ The Alterations module exposes a REST API for submitting, inspecting, and dry-running alteration plans. +All endpoints on this page require the `run:alterations` permission. + ## Submit a plan Send `POST /alterations/submit` with `alterations` plus a `filter`: @@ -68,6 +70,21 @@ Example response: } ``` +The dry-run endpoint accepts the same `AlterationWorkflowInstanceFilter` model that `POST /alterations/submit` uses inside `filter`. In `release/3.8.0`, that includes: + +* `workflowInstanceIds` +* `correlationIds` +* `names` +* `searchTerm` +* `definitionIds` +* `definitionVersionIds` +* `statuses` +* `subStatuses` +* `hasIncidents` +* `isSystem` +* `activityFilters` +* `timestampFilters` + ## Get plan and job status Use the plan ID to query the current plan and its jobs: @@ -132,3 +149,5 @@ The response includes the stored plan and any generated jobs: ``` `status` values are serialized from Elsa's plan and job status enums. Use the plan timestamps and per-job logs to understand whether Elsa found matching instances, whether jobs have started, and which alterations succeeded or failed. + +If a plan matches no workflow instances, the response still returns the stored plan, but `jobs` remains empty. diff --git a/features/alterations/applying-alterations/README.md b/features/alterations/applying-alterations/README.md index af6f2fa..cc8088e 100644 --- a/features/alterations/applying-alterations/README.md +++ b/features/alterations/applying-alterations/README.md @@ -2,6 +2,8 @@ Use immediate execution when you already know which workflow instance IDs you want to alter and you want the results in the current request. +This execution mode is synchronous from the caller's point of view: Elsa runs the requested alterations against the specified workflow instances and returns one result per instance. + At the service level, immediate execution uses `IAlterationRunner`: ```csharp @@ -21,6 +23,17 @@ var results = await runner.RunAsync(workflowInstanceIds, alterations, cancellati This updates the specified workflow instances synchronously and returns one `RunAlterationsResult` per instance. +## What the result tells you + +Each `RunAlterationsResult` contains: + +* `workflowInstanceId` +* `log` +* `workflowHasScheduledWork` +* `isSuccessful` + +Use the log entries to see which alteration succeeded or failed for each targeted instance. + ## Resuming scheduled work When you use `IAlterationRunner` directly, successful alterations may leave workflow instances with scheduled work waiting to be dispatched. In that case, resume them with `IAlteredWorkflowDispatcher`: @@ -40,3 +53,21 @@ This distinction matters: * `POST /alterations/run` runs the alterations and then automatically dispatches successful instances that have scheduled work. If you are using the HTTP API, you do not need a separate resume step after a successful `/alterations/run` request. + +## When to use immediate execution + +Use immediate execution when: + +* an operator already has one or more concrete workflow instance IDs +* you want the alteration log in the same request +* you do not need durable plan and job records + +Use alteration plans instead when Elsa should discover the target instances for you or when you need persistent plan and job tracking. + +## Retrying faulted workflow instances + +`release/3.8.0` also ships a bulk retry endpoint for faulted instances: `POST /alterations/workflows/retry`. + +That endpoint builds `ScheduleActivity` alterations for the specified activity IDs, or for all incident activity IDs when you omit `activityIds`, then dispatches the updated workflow instances. + +Use the retry endpoint when your operational goal is specifically "retry the faulted work" rather than "apply an arbitrary alteration set". diff --git a/features/alterations/applying-alterations/rest-api.md b/features/alterations/applying-alterations/rest-api.md index 7c5a3e3..208e528 100644 --- a/features/alterations/applying-alterations/rest-api.md +++ b/features/alterations/applying-alterations/rest-api.md @@ -4,6 +4,8 @@ The Alterations module exposes `POST /alterations/run` for immediate execution a Use this endpoint when you already know the target instance IDs and want the results immediately. If you want Elsa to select instances from a filter and process them in the background, use [alteration plans](../alteration-plans/rest-api.md) instead. +All endpoints on this page require the `run:alterations` permission. + For example, to apply an alteration that modifies a variable, migrates the workflow instance to a new version, and schedules an activity, use the following request: ```http @@ -68,3 +70,39 @@ The response includes one result per targeted workflow instance: ``` After the runner finishes, the endpoint automatically dispatches any successful workflow instance that still has scheduled work. + +## Retry faulted activities + +`release/3.8.0` also exposes `POST /alterations/workflows/retry` for retrying faulted activities across one or more workflow instances. + +If you omit `activityIds`, Elsa retries all incident activity IDs recorded on each specified workflow instance. + +```http +POST /alterations/workflows/retry HTTP/1.1 +Host: localhost:5001 + +{ + "workflowInstanceIds": [ + "88ce68d00e824c78a53af04f16d276ea" + ] +} +``` + +To retry only specific activities, include `activityIds`: + +```http +POST /alterations/workflows/retry HTTP/1.1 +Host: localhost:5001 + +{ + "workflowInstanceIds": [ + "88ce68d00e824c78a53af04f16d276ea" + ], + "activityIds": [ + "ShipOrder", + "CapturePayment" + ] +} +``` + +The response shape matches `/alterations/run` by returning one result per targeted workflow instance.