elsa-core/doc/adr/0003-direct-bookmark-management-in-workflowexecutioncontext.md
Sipke Schoorstra 4266421a4c
Refactor Fault Propagation and Simplify Bookmark Management (#6545)
* Refactor bookmark management and add new features

Streamlined bookmark handling by eliminating temporary storage in `ActivityExecutionContext` and directly managing bookmarks in `WorkflowExecutionContext`. Documented architectural decisions using ADRs.

* Regenerate EF Core migrations

* Refactor fault tracking to use AggregatedFaultCount property.

Replaces FaultCount with AggregatedFaultCount across the codebase to improve clarity and consistency in fault tracking. Updates related methods, properties, and data mappings to align with the new terminology. Fixes initialization issue with nullable inputs in Fault class.

* Add migration to track fault counts in runtime (V3.5)

This migration adds a new column, "AggregatedFaultCount," to the "ActivityExecutionRecords" table. The column is an integer, non-nullable, with a default value of 0, and enables tracking aggregated fault occurrences. The migration also includes a rollback to remove this column if needed.

* Fix typo in ADR 0004 regarding bookmark management convention

Corrected a spelling mistake in the ADR documentation by changing "determins" to "determines." This ensures clarity and maintains the professionalism of the document. No functional changes were made.

* Refine fault propagation logic for child-parent activities

Replace automatic fault transitions of parent activities with an aggregate fault count for descendant activities. This avoids premature state changes while still indicating child activity faults, improving workflow resilience and accuracy.

* Remove signal-driven fault propagation ADR and renumber bookmarks ADR

The ADR for signal-driven fault propagation was deleted, and the direct bookmark management ADR was renamed and renumbered accordingly. Related references in the table of contents, graph, and solution file were updated to reflect these changes.

* Refactor DeleteBookmarks to improve readability.

Reformatted the BookmarkFilter initialization for better clarity and maintainability. This change ensures the code is more aligned with modern C# conventions and improves overall readability. No behavior or functionality has been altered.

* Refactor naming for "AggregatedFaultCount" to "AggregateFaultCount"

Standardized the terminology across the codebase and migrations by renaming all references of "AggregatedFaultCount" to "AggregateFaultCount" for improved consistency and readability. Updated relevant logic, models, migrations, and database contexts accordingly.
2025-04-10 15:01:49 +02:00

2.6 KiB

3. Direct Bookmark Management in WorkflowExecutionContext

Date: 2025-04-01

Status

Accepted

Context

Currently, ActivityExecutionContext maintains a temporary list of bookmarks created by the activity during its execution. After the activity completes, a middleware is responsible for copying these bookmarks into the WorkflowExecutionContext.Bookmarks list, which is then persisted to the database.

This architecture leads to a subtle issue upon resumption:

  • When a workflow is resumed from a persisted state, only the WorkflowExecutionContext and its Bookmarks are restored from the database.
  • The ActivityExecutionContext's temporary Bookmarks list remains empty.
  • As a result, if the resumed activity attempts to cancel (or modify) its previously created bookmarks, it cannot, because it has no access to them—changes are not tracked.

However, there is an existing convention that determines that if an activity created a bookmark during its execution, the activity will not automatically complete. Specifically, this is implemented in the AutoCompleteBehavior, which is installed by the CodeActivity and possibly by custom activities. To keep this behavior in tact, we will still maintain a private list of bookmarks, one that is explicitly purposed for maintaining new* bookmarks, temporarily for the lifetime of the ActivityExecutionContext in memory.

Decision

Eliminate the temporary Bookmarks list in ActivityExecutionContext. Instead, have activities add bookmarks directly to the WorkflowExecutionContext.Bookmarks list.

This is possible and safe because each Bookmark already contains:

  • A reference to the originating ActivityId
  • A reference to the originating ActivityInstanceId

These references allow accurate tracking and filtering of bookmarks, even when multiple activities are active.

Additionally, maintain a new temporary bookmarks list that explicitly stores newly created bookmarks. This list does not have to be copied into the WorkflowExecutionContext's Bookmarks property, given that this property will now be updated directly.

Consequences

  • Simplifies the architecture by removing the need for middleware to copy bookmarks post-execution.
  • Fixes a bug where resumed activities could not cancel their previously created bookmarks.
  • Reduces the chance of inconsistencies between temporary and persisted bookmark state.
  • Ensures bookmark changes are always applied to the persisted, canonical source of truth.

Alternatives Considered

  • Keep the existing temporary list and enhance the system to hydrate the ActivityExecutionContext.Bookmarks list on resume. Rejected due to added complexity and duplication of state.