Skip to content

Refactor shells; add consumer graph & call stack tracking#7352

Closed
sfmskywalker wants to merge 17 commits intomainfrom
enh/shells
Closed

Refactor shells; add consumer graph & call stack tracking#7352
sfmskywalker wants to merge 17 commits intomainfrom
enh/shells

Conversation

@sfmskywalker
Copy link
Copy Markdown
Member

Purpose

Modernize shell-based features and add developer-facing graph and observability capabilities:

  • Provide a recursive workflow consumer graph and export-with-consumers
  • Track and expose activity execution call stacks across workflow boundaries
  • Streamline shell feature wiring (HTTP middleware, resilience) and configuration

Scope

Select one primary concern:

  • Bug fix (behavior change)
  • Refactor (no behavior change)
  • Documentation update
  • Formatting / code cleanup
  • Dependency / build update
  • New feature

If this PR includes multiple unrelated concerns, please split it before requesting review.


Description

Problem

  • Shell feature composition is cumbersome; HTTP feature does not plug in middleware cleanly.
  • There is no API to resolve transitive workflow consumers or export definitions with their consumers.
  • Activity execution lacks a first-class call stack, making diagnosis of nested/child executions hard.
  • Cache keys are not tenant-scoped; filter-keyed workflow graph caching is unstable.
  • Distributed deployments can duplicate refresh/reload work and exhibit trigger re-index churn.
  • CI and dependencies lag .NET 10.

Solution

  • Add workflow consumer graph:

    • Introduce IWorkflowReferenceGraphBuilder and options to compute transitive consumer relationships.
    • Add API endpoint and client method to retrieve consumers for a definition.
    • Extend export endpoints (and client) to include transitive consumers with deterministic ZIPs and filenames.
  • Add activity execution call stack:

    • Track SchedulingActivityExecutionId, SchedulingWorkflowInstanceId, and CallStackDepth.
    • Populate these fields across flowchart, sequence, parallel, while, and cross-workflow invocation points.
    • Add store pagination API and HTTP endpoint to return an activity execution’s call stack.
    • Add EF Core migrations (V3_7) to persist new fields.
  • Modernize shell features and configuration:

    • Refactor HTTP feature to an IMiddlewareShellFeature and register middleware automatically.
    • Introduce ResilienceFeature and HTTP resilience registration.
    • Add ManagementServiceCollectionExtensions and Expressions AddTypeAlias helpers to make activity/variable/type alias registration declarative.
    • Expand JavaScript feature options (CLR access, config access, script cache, wrappers/variable copying).
  • Improve multitenancy and caching:

    • Add TenantsOptions.IsEnabled to toggle multitenancy logic.
    • Scope workflow cache keys by tenant and resolve graphs via stable version-based keys.
  • Bolster runtime resilience in distributed scenarios:

    • Decorate workflow definition refresh/reload with distributed locks.
    • Emit WorkflowDefinitionsReloaded notification after registry repopulation.
  • CI and dependencies:

    • Move GitHub Actions to .NET 10, harden test discovery/targeting net10.0.
    • Bump package versions; use project references for CShells locally.
    • Update release-notes agent to write to doc/changelogs and add 3.6.0 release notes.
  • Hardening and fixes:

    • Make trigger indexing idempotent by aligning JSON serialization (case, converters) to prevent false-positive diffs.
    • Parse Content-Disposition robustly for downloaded filenames.
    • Minor HTTP and EF corrections; additional tests across new features.

Verification

Steps:

  1. Build and run with .NET 10; ensure middleware-based HTTP workflows respond as expected.
  2. Call GET /workflow-definitions/{definitionId}/consumers; verify returned IDs include transitive consumers.
  3. Export a definition with includeConsumingWorkflows=true; verify ZIP contains parent/child consumers and deterministic timestamps/file names.
  4. Execute a workflow that calls child workflows; fetch GET /activity-executions/{id}/call-stack and confirm ordered root→leaf chain with correct depths.
  5. In multi-tenant setups, confirm workflow definition/graph caches are tenant-scoped (no cross-tenant leakage).
  6. In multi-pod setups, trigger refresh/reload concurrently; verify only one instance runs via distributed lock and trigger indexing remains idempotent.

Expected outcome:

  • New APIs return correct graphs/zips; activity call stacks are accurate and paginated.
  • HTTP feature works without manual middleware wiring.
  • No trigger duplication; caches invalidate correctly per tenant.
  • CI passes on .NET 10.

Screenshots / Recordings (if applicable)


Commit Convention

We recommend using conventional commit prefixes:

  • fix: – Bug fixes (behavior change)
  • feat: – New features (e.g., consumer graph, call stack API)
  • refactor: – Code changes without behavior change (shell feature consolidation)
  • docs: – Documentation updates (release notes agent path)
  • chore: – Maintenance, tooling, or dependency updates (.NET 10, package bumps)
  • test: – Test additions or modifications (graph/export/call stack/idempotency)

Clear commit messages make reviews easier and history more meaningful.


Checklist

  • The PR is focused on a single concern
  • Commit messages follow the recommended convention
  • Tests added or updated (if applicable)
  • Documentation updated (if applicable)
  • No unrelated cleanup included
  • All tests pass

Replace CShells NuGet package references with direct project references to the local CShells source to enable developing and testing against local changes and simplify build integration across modules.
Added error handling for assembly load failures in feature discovery to improve resilience. Also updated configuration for identity token options and removed unused service bus consumer dependencies. Simplified project structure by moving and cleaning up `Directory.Build.targets` files.
Moved `ShellSettingsExtensions` and `ShellConfiguration` to `CShells.Abstractions` for better modularity. Added new `ServiceCollectionFeatureExtensions` to improve options registration. Updated appsettings and references to support these changes.
…y and variable registration

Added `ManagementServiceCollectionExtensions` for registering Elsa activity types and variable descriptors, providing a modular and shell-feature-compatible approach to configuration. Updated relevant features to utilize these new extension methods, enhancing code modularity and reducing redundancy.
Introduced `ResilienceServiceCollectionExtensions` to register resilience strategies within the `Elsa.Resilience.Core` module. Updated `HttpFeature` to incorporate resilience strategies, enhancing HTTP-related resilience configuration leveraging the new extension methods.
Implemented multiple properties in `JavaScriptFeature` to enhance JavaScript execution: `AllowClrAccess`, `AllowConfigurationAccess`, `ScriptCacheTimeout`, `DisableWrappers`, and `DisableVariableCopying`. These additions enable more flexible and secure configuration of the Jint JavaScript engine.
Resolve workflow definitions first and store graphs under stable per-version-ID cache keys so different lookup paths share entries.
Centralize cache creation and change-token registration to remove duplicated caching logic.
Skip materializer-unavailable definitions to avoid caching null graphs and simplify flow.
Introduce constants for default definition and version IDs, and materializer name. Refactor tests to use these constants, streamline graph and definition resolution, and improve cache key creation by sharing logic across tests. Extend tests to check scenarios with unavailable materializers, ensuring caching only occurs for valid cases.
Added checks for both workflow definition and version cache keys in AutoUpdateTests to ensure comprehensive cache validation, improving test reliability and coverage.
…ration

Revised project reference paths in `Elsa.ModularServer.Web.csproj` for CShells projects and updated `Elsa.sln` to include new CShells projects, streamlining project organization and build configuration.
…rename `ResilienceShellFeature` to `ResilienceFeature`.
…pWorkflowsMiddleware`, and update `HttpActivityOptions` defaults.
… service collections

- Introduced `AddTypeAlias<T>` method in `ServiceCollectionExtensions.cs` for adding type aliases.
- Added `AddVariableTypeAndAlias<T>` method in `ManagementServiceCollectionExtensions.cs` to add variable types with aliases.
@greptile-apps
Copy link
Copy Markdown
Contributor

greptile-apps bot commented Mar 8, 2026

Greptile Summary

This PR switches four elsa-core projects from NuGet PackageReference to local ProjectReference for the CShells abstraction packages, and registers the corresponding CShells source projects in Elsa.sln under a new cshells solution folder — enabling side-by-side local development against the cshells sibling repository.

Key observations:

  • The migration is incomplete: src/apps/Elsa.ModularServer.Web/Elsa.ModularServer.Web.csproj still uses NuGet PackageReference for CShells.AspNetCore and CShells.FastEndpoints (the concrete implementations), while the abstractions they depend on are now built from local source. This mixed state can cause MSBuild to resolve two different copies of the abstraction assemblies, risking type-identity mismatches at runtime.
  • All ProjectReference paths point outside the repository root to a sibling cshells/ directory. This is a local-development convenience but it will silently break for any contributor or CI agent that only clones elsa-core. The requirement to check out cshells as a sibling should be documented (README / CONTRIBUTING) and reflected in the CI checkout steps.
  • Elsa.Identity.csproj and Elsa.Workflows.Api.csproj each add a direct ProjectReference to CShells.FastEndpoints.Abstractions, but both already pull it in transitively through Elsa.Api.Common. The redundant reference is harmless but adds unnecessary noise.

Confidence Score: 3/5

  • The PR is safe for local development but carries a real risk of build breakage for fresh checkouts and CI environments that don't co-locate the cshells sibling repository, and the incomplete migration in Elsa.ModularServer.Web may cause assembly version conflicts.
  • The scope of the diff is narrow (4 csproj files + the solution), but two meaningful issues prevent a higher score: (1) the incomplete PackageReferenceProjectReference migration leaves a potential assembly-version conflict in Elsa.ModularServer.Web, and (2) the external sibling-repository requirement is undocumented and will break standard contributor and CI workflows without additional setup.
  • src/apps/Elsa.ModularServer.Web/Elsa.ModularServer.Web.csproj (not in the diff but directly affected) and all four updated .csproj files that introduce the sibling-repo ProjectReference paths.

Important Files Changed

Filename Overview
Elsa.sln Adds a cshells solution folder containing 6 CShells project references from a sibling repo path (../cshells/). All 6 projects are wired into build configurations and nested correctly. However, Elsa.ModularServer.Web.csproj (not in this diff) still references the concrete CShells.AspNetCore and CShells.FastEndpoints NuGet packages, creating a mixed NuGet/local-source state.
src/common/Elsa.Api.Common/Elsa.Api.Common.csproj Switches CShells.AspNetCore.Abstractions and CShells.FastEndpoints.Abstractions from NuGet PackageReference to local ProjectReference. Requires sibling cshells repository to be present; will break fresh checkouts of elsa-core alone.
src/common/Elsa.Features/Elsa.Features.csproj Switches CShells.Abstractions from NuGet PackageReference to local ProjectReference. Same sibling-repo dependency concern as the other updated csproj files.
src/modules/Elsa.Identity/Elsa.Identity.csproj Switches CShells.FastEndpoints.Abstractions to local ProjectReference. Note: Elsa.Identity already references Elsa.Api.Common (which itself brings in this same project), making this a redundant but harmless direct reference.
src/modules/Elsa.Workflows.Api/Elsa.Workflows.Api.csproj Switches CShells.FastEndpoints.Abstractions to local ProjectReference. Same observations as Elsa.Identity — sibling-repo path dependency and redundant reference via Elsa.Api.Common.

Flowchart

%%{init: {'theme': 'neutral'}}%%
flowchart TD
    subgraph elsa-core repo
        SLN[Elsa.sln]
        FEA[Elsa.Features.csproj]
        API[Elsa.Api.Common.csproj]
        IDN[Elsa.Identity.csproj]
        WFA[Elsa.Workflows.Api.csproj]
        WEB[Elsa.ModularServer.Web.csproj]
    end

    subgraph cshells sibling repo
        CA[CShells.Abstractions]
        C[CShells]
        CASP[CShells.AspNetCore.Abstractions]
        CASP2[CShells.AspNetCore]
        CFE[CShells.FastEndpoints.Abstractions]
        CFE2[CShells.FastEndpoints]
    end

    subgraph NuGet
        NU_CASP2["CShells.AspNetCore v0.0.11"]
        NU_CFE2["CShells.FastEndpoints v0.0.11"]
    end

    SLN -->|solution folder| CA
    SLN -->|solution folder| C
    SLN -->|solution folder| CASP
    SLN -->|solution folder| CASP2
    SLN -->|solution folder| CFE
    SLN -->|solution folder| CFE2

    FEA -->|ProjectReference NEW| CA
    API -->|ProjectReference NEW| CASP
    API -->|ProjectReference NEW| CFE
    IDN -->|ProjectReference NEW| CFE
    WFA -->|ProjectReference NEW| CFE

    WEB -->|PackageReference UNCHANGED| NU_CASP2
    WEB -->|PackageReference UNCHANGED| NU_CFE2

    NU_CASP2 -.->|transitive NuGet dep| CASP
    NU_CFE2 -.->|transitive NuGet dep| CFE

    style NU_CASP2 fill:#f96,stroke:#c00
    style NU_CFE2 fill:#f96,stroke:#c00
Loading

Comments Outside Diff (1)

  1. src/apps/Elsa.ModularServer.Web/Elsa.ModularServer.Web.csproj, line 3-4 (link)

    Incomplete migration — mixed PackageReference/ProjectReference for CShells

    Elsa.ModularServer.Web.csproj still consumes CShells.AspNetCore and CShells.FastEndpoints via PackageReference (NuGet v0.0.11), while all their upstream dependencies (CShells.Abstractions, CShells.AspNetCore.Abstractions, CShells.FastEndpoints.Abstractions) have been switched to local ProjectReferences in this PR.

    At build time the NuGet concrete packages will pull in their own transitive dependency on CShells.*Abstractions v0.0.11 from NuGet. MSBuild will therefore try to reconcile two copies of those assemblies: one from the local project build and one from NuGet. Depending on the final resolution, the wrong ABI version could end up in the output, silently shadowing the locally-built abstractions or causing type-identity mismatches at runtime.

    To stay consistent, CShells.AspNetCore and CShells.FastEndpoints should also be switched to ProjectReference here:

    <ProjectReference Include="..\..\..\..\cshells\src\CShells.AspNetCore\CShells.AspNetCore.csproj" />
    <ProjectReference Include="..\..\..\..\cshells\src\CShells.FastEndpoints\CShells.FastEndpoints.csproj" />

    Both target projects are already registered in Elsa.sln under the new cshells solution folder.

Last reviewed commit: 01e458a


<ItemGroup>
<PackageReference Include="CShells.Abstractions" />
<ProjectReference Include="..\..\..\..\cshells\src\CShells.Abstractions\CShells.Abstractions.csproj" />
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

External sibling-repository dependency breaks default contributor workflow

The ProjectReference path ../../../../cshells/src/CShells.Abstractions/CShells.Abstractions.csproj resolves to a directory that is a sibling of the elsa-core repo root (i.e. ../cshells/ relative to the solution). This pattern requires every developer and every CI agent to check out the cshells repository beside elsa-core before the solution can build.

Without an explicit README note, a git submodule, or a CI pipeline step that clones cshells as a sibling, any fresh clone of elsa-core alone will fail to restore/build with an error like:

error MSB3202: The project file "..\cshells\src\CShells.Abstractions\CShells.Abstractions.csproj" was not found.

Consider documenting the required sibling checkout in the repository README (or CONTRIBUTING.md), and adding the corresponding checkout step to the CI workflow. The same concern applies to Elsa.Api.Common.csproj, Elsa.Identity.csproj, and Elsa.Workflows.Api.csproj where the same relative path pattern is used.

@sfmskywalker sfmskywalker deleted the enh/shells branch March 8, 2026 14:37
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant