< Summary

Information
Class: Elsa.WorkflowProviders.BlobStorage.Handlers.JsonBlobWorkflowFormatHandler
Assembly: Elsa.WorkflowProviders.BlobStorage
File(s): /home/runner/work/elsa-core/elsa-core/src/modules/Elsa.WorkflowProviders.BlobStorage/Handlers/JsonBlobWorkflowFormatHandler.cs
Line coverage
78%
Covered lines: 18
Uncovered lines: 5
Coverable lines: 23
Total lines: 68
Line coverage: 78.2%
Branch coverage
50%
Covered branches: 1
Total branches: 2
Branch coverage: 50%
Method coverage

Feature is only available for sponsors

Upgrade to PRO version

Metrics

MethodBranch coverage Crap Score Cyclomatic complexity Line coverage
.ctor(...)100%11100%
get_Name()100%210%
get_SupportedExtensions()100%11100%
CanHandle(...)50%2266.66%
TryParseAsync(...)100%1178.57%

File(s)

/home/runner/work/elsa-core/elsa-core/src/modules/Elsa.WorkflowProviders.BlobStorage/Handlers/JsonBlobWorkflowFormatHandler.cs

#LineLine coverage
 1using Elsa.WorkflowProviders.BlobStorage.Contracts;
 2using Elsa.Workflows;
 3using Elsa.Workflows.Management.Mappers;
 4using Elsa.Workflows.Management.Materializers;
 5using Elsa.Workflows.Management.Models;
 6using Elsa.Workflows.Runtime;
 7using FluentStorage.Blobs;
 8using Microsoft.Extensions.Logging;
 9
 10namespace Elsa.WorkflowProviders.BlobStorage.Handlers;
 11
 12/// <summary>
 13/// Handles JSON-formatted workflow definitions from blob storage.
 14/// </summary>
 26615public class JsonBlobWorkflowFormatHandler(
 26616    IActivitySerializer activitySerializer,
 26617    WorkflowDefinitionMapper workflowDefinitionMapper,
 26618    ILogger<JsonBlobWorkflowFormatHandler> logger) : IBlobWorkflowFormatHandler
 19{
 20    /// <inheritdoc />
 021    public string Name => "Json";
 22
 23    /// <inheritdoc />
 824    public IEnumerable<string> SupportedExtensions => ["json"];
 25
 26    /// <inheritdoc />
 27    public bool CanHandle(Blob blob, string? contentType)
 28    {
 29        // Extension filtering is already handled by the provider via SupportedExtensions.
 30        // Here we can optionally check content type for additional validation.
 16831        if (!string.IsNullOrEmpty(contentType) && contentType.Contains("json", StringComparison.OrdinalIgnoreCase))
 032            return true;
 33
 34        // If no content type is available, assume we can handle it (since extension was already validated)
 16835        return true;
 36    }
 37
 38    /// <inheritdoc />
 39    public ValueTask<MaterializedWorkflow?> TryParseAsync(Blob blob, string content, CancellationToken cancellationToken
 40    {
 41        try
 42        {
 16843            var workflowDefinitionModel = activitySerializer.Deserialize<WorkflowDefinitionModel>(content);
 16844            var workflow = workflowDefinitionMapper.Map(workflowDefinitionModel);
 45
 16846            var materialized = new MaterializedWorkflow(
 16847                workflow,
 16848                ProviderName: "FluentStorage",
 16849                MaterializerName: JsonWorkflowMaterializer.MaterializerName,
 16850                MaterializerContext: null,
 16851                OriginalSource: content // Preserve full JSON for symmetric round-trip
 16852            );
 53
 16854            return new(materialized);
 55        }
 056        catch (Exception ex)
 57        {
 58            // Intentionally catching all exceptions here to gracefully handle any failure during workflow parsing.
 59            // This includes JsonException, IOException, deserialization errors, or any unexpected exceptions.
 60            // Since this is a format handler for user-provided files, we want to log and skip invalid files
 61            // rather than crashing the workflow loading process.
 062            logger.LogWarning(ex, "Failed to parse JSON workflow from blob '{BlobPath}'. The file will be skipped.", blo
 63
 64            // Return null to indicate this handler can't process the content
 065            return new((MaterializedWorkflow?)null);
 66        }
 16867    }
 68}