Enable customizable Hangfire job storage and deprecate obsolete APIs.
Added support for configuring Hangfire job storage per database provider, including PostgreSql, SQLite, and SQL Server. Introduced new methods for flexible Hangfire setup, while marking older APIs and storage configuration extensions as obsolete. Refactored related configurations for streamlined and centralized job scheduling logic.
This commit is contained in:
parent
279d55c22c
commit
48c453d153
|
|
@ -49,6 +49,7 @@
|
|||
<PackageVersion Include="Grpc.Tools" Version="2.68.1"/>
|
||||
<PackageVersion Include="Hangfire" Version="1.8.17"/>
|
||||
<PackageVersion Include="Hangfire.MemoryStorage" Version="1.8.1.1"/>
|
||||
<PackageVersion Include="Hangfire.PostgreSql" Version="1.20.10"/>
|
||||
<PackageVersion Include="Hangfire.Storage.SQLite" Version="0.4.2"/>
|
||||
<PackageVersion Include="Humanizer.Core" Version="2.14.1"/>
|
||||
<PackageVersion Include="IronCompress" Version="1.6.3"/>
|
||||
|
|
@ -112,44 +113,44 @@
|
|||
<PackageVersion Include="AspNetCore.Authentication.ApiKey" Version="8.0.1"/>
|
||||
</ItemGroup>
|
||||
<ItemGroup Condition="'$(TargetFramework)' == 'net8.0'">
|
||||
<PackageVersion Include="Microsoft.AspNetCore.Authorization" Version="8.0.11" />
|
||||
<PackageVersion Include="Microsoft.AspNetCore.Components.WebAssembly" Version="8.0.11" />
|
||||
<PackageVersion Include="Microsoft.AspNetCore.Components.WebAssembly.DevServer" Version="8.0.11" />
|
||||
<PackageVersion Include="Microsoft.AspNetCore.Components.WebAssembly.Server" Version="8.0.11" />
|
||||
<PackageVersion Include="Microsoft.AspNetCore.DataProtection.Abstractions" Version="8.0.11" />
|
||||
<PackageVersion Include="Microsoft.AspNetCore.Mvc.Testing" Version="8.0.11" />
|
||||
<PackageVersion Include="Microsoft.Data.Sqlite" Version="8.0.11" />
|
||||
<PackageVersion Include="Microsoft.Data.Sqlite.Core" Version="8.0.11" />
|
||||
<PackageVersion Include="Microsoft.EntityFrameworkCore" Version="8.0.11" />
|
||||
<PackageVersion Include="Microsoft.EntityFrameworkCore.Design" Version="8.0.11" />
|
||||
<PackageVersion Include="Microsoft.EntityFrameworkCore.Relational" Version="8.0.11" />
|
||||
<PackageVersion Include="Microsoft.EntityFrameworkCore.Sqlite" Version="8.0.11" />
|
||||
<PackageVersion Include="Microsoft.EntityFrameworkCore.SqlServer" Version="8.0.11" />
|
||||
<PackageVersion Include="Microsoft.Extensions.Caching.Abstractions" Version="8.0.0" />
|
||||
<PackageVersion Include="Microsoft.Extensions.Caching.Memory" Version="8.0.1" />
|
||||
<PackageVersion Include="Microsoft.Extensions.Configuration" Version="8.0.0" />
|
||||
<PackageVersion Include="Microsoft.Extensions.Configuration.Abstractions" Version="8.0.0" />
|
||||
<PackageVersion Include="Microsoft.Extensions.Configuration.Json" Version="8.0.1" />
|
||||
<PackageVersion Include="Microsoft.Extensions.DependencyInjection" Version="8.0.1" />
|
||||
<PackageVersion Include="Microsoft.Extensions.DependencyInjection.Abstractions" Version="8.0.2" />
|
||||
<PackageVersion Include="Microsoft.Extensions.DependencyModel" Version="8.0.2" />
|
||||
<PackageVersion Include="Microsoft.Extensions.Hosting.Abstractions" Version="8.0.1" />
|
||||
<PackageVersion Include="Microsoft.Extensions.Http" Version="8.0.1" />
|
||||
<PackageVersion Include="Microsoft.Extensions.Http.Polly" Version="8.0.11" />
|
||||
<PackageVersion Include="Microsoft.Extensions.Logging" Version="8.0.1" />
|
||||
<PackageVersion Include="Microsoft.Extensions.Logging.Abstractions" Version="8.0.2" />
|
||||
<PackageVersion Include="Microsoft.Extensions.Logging.Console" Version="8.0.1" />
|
||||
<PackageVersion Include="Microsoft.Extensions.Options" Version="8.0.2" />
|
||||
<PackageVersion Include="Microsoft.Extensions.Options.ConfigurationExtensions" Version="8.0.0" />
|
||||
<PackageVersion Include="Npgsql" Version="8.0.6" />
|
||||
<PackageVersion Include="Npgsql.EntityFrameworkCore.PostgreSQL" Version="8.0.11" />
|
||||
<PackageVersion Include="Oracle.EntityFrameworkCore" Version="8.23.60" />
|
||||
<PackageVersion Include="Polly" Version="8.4.2" />
|
||||
<PackageVersion Include="Pomelo.EntityFrameworkCore.MySql" Version="8.0.2" />
|
||||
<PackageVersion Include="Refit" Version="8.0.0" />
|
||||
<PackageVersion Include="Refit.HttpClientFactory" Version="8.0.0" />
|
||||
<PackageVersion Include="System.Formats.Asn1" Version="8.0.1" />
|
||||
<PackageVersion Include="System.Text.Json" Version="8.0.5" />
|
||||
<PackageVersion Include="Microsoft.AspNetCore.Authorization" Version="8.0.11"/>
|
||||
<PackageVersion Include="Microsoft.AspNetCore.Components.WebAssembly" Version="8.0.11"/>
|
||||
<PackageVersion Include="Microsoft.AspNetCore.Components.WebAssembly.DevServer" Version="8.0.11"/>
|
||||
<PackageVersion Include="Microsoft.AspNetCore.Components.WebAssembly.Server" Version="8.0.11"/>
|
||||
<PackageVersion Include="Microsoft.AspNetCore.DataProtection.Abstractions" Version="8.0.11"/>
|
||||
<PackageVersion Include="Microsoft.AspNetCore.Mvc.Testing" Version="8.0.11"/>
|
||||
<PackageVersion Include="Microsoft.Data.Sqlite" Version="8.0.11"/>
|
||||
<PackageVersion Include="Microsoft.Data.Sqlite.Core" Version="8.0.11"/>
|
||||
<PackageVersion Include="Microsoft.EntityFrameworkCore" Version="8.0.11"/>
|
||||
<PackageVersion Include="Microsoft.EntityFrameworkCore.Design" Version="8.0.11"/>
|
||||
<PackageVersion Include="Microsoft.EntityFrameworkCore.Relational" Version="8.0.11"/>
|
||||
<PackageVersion Include="Microsoft.EntityFrameworkCore.Sqlite" Version="8.0.11"/>
|
||||
<PackageVersion Include="Microsoft.EntityFrameworkCore.SqlServer" Version="8.0.11"/>
|
||||
<PackageVersion Include="Microsoft.Extensions.Caching.Abstractions" Version="8.0.0"/>
|
||||
<PackageVersion Include="Microsoft.Extensions.Caching.Memory" Version="8.0.1"/>
|
||||
<PackageVersion Include="Microsoft.Extensions.Configuration" Version="8.0.0"/>
|
||||
<PackageVersion Include="Microsoft.Extensions.Configuration.Abstractions" Version="8.0.0"/>
|
||||
<PackageVersion Include="Microsoft.Extensions.Configuration.Json" Version="8.0.1"/>
|
||||
<PackageVersion Include="Microsoft.Extensions.DependencyInjection" Version="8.0.1"/>
|
||||
<PackageVersion Include="Microsoft.Extensions.DependencyInjection.Abstractions" Version="8.0.2"/>
|
||||
<PackageVersion Include="Microsoft.Extensions.DependencyModel" Version="8.0.2"/>
|
||||
<PackageVersion Include="Microsoft.Extensions.Hosting.Abstractions" Version="8.0.1"/>
|
||||
<PackageVersion Include="Microsoft.Extensions.Http" Version="8.0.1"/>
|
||||
<PackageVersion Include="Microsoft.Extensions.Http.Polly" Version="8.0.11"/>
|
||||
<PackageVersion Include="Microsoft.Extensions.Logging" Version="8.0.1"/>
|
||||
<PackageVersion Include="Microsoft.Extensions.Logging.Abstractions" Version="8.0.2"/>
|
||||
<PackageVersion Include="Microsoft.Extensions.Logging.Console" Version="8.0.1"/>
|
||||
<PackageVersion Include="Microsoft.Extensions.Options" Version="8.0.2"/>
|
||||
<PackageVersion Include="Microsoft.Extensions.Options.ConfigurationExtensions" Version="8.0.0"/>
|
||||
<PackageVersion Include="Npgsql" Version="8.0.6"/>
|
||||
<PackageVersion Include="Npgsql.EntityFrameworkCore.PostgreSQL" Version="8.0.11"/>
|
||||
<PackageVersion Include="Oracle.EntityFrameworkCore" Version="8.23.60"/>
|
||||
<PackageVersion Include="Polly" Version="8.4.2"/>
|
||||
<PackageVersion Include="Pomelo.EntityFrameworkCore.MySql" Version="8.0.2"/>
|
||||
<PackageVersion Include="Refit" Version="8.0.0"/>
|
||||
<PackageVersion Include="Refit.HttpClientFactory" Version="8.0.0"/>
|
||||
<PackageVersion Include="System.Formats.Asn1" Version="8.0.1"/>
|
||||
<PackageVersion Include="System.Text.Json" Version="8.0.5"/>
|
||||
</ItemGroup>
|
||||
<ItemGroup Condition="'$(TargetFramework)' == 'net9.0'">
|
||||
<PackageVersion Include="Microsoft.AspNetCore.Authorization" Version="9.0.0"/>
|
||||
|
|
|
|||
|
|
@ -58,6 +58,7 @@
|
|||
<PackageReference Include="DistributedLock.Postgres"/>
|
||||
<PackageReference Include="DistributedLock.Redis"/>
|
||||
<PackageReference Include="FluentStorage.Azure.Blobs"/>
|
||||
<PackageReference Include="Hangfire.PostgreSql" />
|
||||
<PackageReference Include="Proto.Cluster.Kubernetes" />
|
||||
<PackageReference Include="Grpc.Net.Client" />
|
||||
<PackageReference Include="Proto.Persistence.Sqlite"/>
|
||||
|
|
|
|||
|
|
@ -49,6 +49,12 @@ using Elsa.Workflows.Runtime.Distributed.Extensions;
|
|||
using Elsa.Workflows.Runtime.Options;
|
||||
using Elsa.Workflows.Runtime.Stores;
|
||||
using Elsa.Workflows.Runtime.Tasks;
|
||||
using Hangfire;
|
||||
using Hangfire.MemoryStorage;
|
||||
using Hangfire.PostgreSql;
|
||||
using Hangfire.PostgreSql.Factories;
|
||||
using Hangfire.SqlServer;
|
||||
using Hangfire.Storage.SQLite;
|
||||
using JetBrains.Annotations;
|
||||
using Medallion.Threading.FileSystem;
|
||||
using Medallion.Threading.Postgres;
|
||||
|
|
@ -78,8 +84,8 @@ const bool useSignalR = false; // Disabled until Elsa Studio sends authenticated
|
|||
const WorkflowRuntime workflowRuntime = WorkflowRuntime.Distributed;
|
||||
const DistributedCachingTransport distributedCachingTransport = DistributedCachingTransport.MassTransit;
|
||||
const MassTransitBroker massTransitBroker = MassTransitBroker.Memory;
|
||||
const bool useMultitenancy = false;
|
||||
const bool useTenantsFromConfiguration = false;
|
||||
const bool useMultitenancy = true;
|
||||
const bool useTenantsFromConfiguration = true;
|
||||
const bool useAgents = false;
|
||||
const bool useSecrets = false;
|
||||
const bool disableVariableWrappers = false;
|
||||
|
|
@ -133,7 +139,36 @@ services
|
|||
});
|
||||
|
||||
if (useHangfire)
|
||||
elsa.UseHangfire();
|
||||
{
|
||||
JobStorage jobStorage;
|
||||
if (sqlDatabaseProvider == SqlDatabaseProvider.PostgreSql)
|
||||
{
|
||||
jobStorage = new PostgreSqlStorage(new NpgsqlConnectionFactory(postgresConnectionString, new()
|
||||
{
|
||||
QueuePollInterval = TimeSpan.FromSeconds(1)
|
||||
}));
|
||||
}
|
||||
else if (sqlDatabaseProvider == SqlDatabaseProvider.Sqlite)
|
||||
{
|
||||
jobStorage = new SQLiteStorage(sqliteConnectionString, new()
|
||||
{
|
||||
QueuePollInterval = TimeSpan.FromSeconds(1)
|
||||
});
|
||||
}
|
||||
else if (sqlDatabaseProvider == SqlDatabaseProvider.SqlServer)
|
||||
{
|
||||
jobStorage = new SqlServerStorage(sqlServerConnectionString, new()
|
||||
{
|
||||
QueuePollInterval = TimeSpan.FromSeconds(1)
|
||||
});
|
||||
}
|
||||
else
|
||||
{
|
||||
jobStorage = new MemoryStorage();
|
||||
}
|
||||
|
||||
elsa.UseHangfire(hangfire => hangfire.UseJobStorage(jobStorage));
|
||||
}
|
||||
|
||||
elsa
|
||||
.AddActivitiesFrom<Program>()
|
||||
|
|
|
|||
|
|
@ -2,14 +2,7 @@
|
|||
"Logging": {
|
||||
"LogLevel": {
|
||||
"Default": "Warning",
|
||||
"Elsa": "Warning",
|
||||
"MassTransit": "Warning",
|
||||
"Microsoft.Extensions.Http": "Warning",
|
||||
"Microsoft.Hosting.Lifetime": "Information",
|
||||
"Microsoft.EntityFrameworkCore": "Warning",
|
||||
"Microsoft.AspNetCore": "Warning",
|
||||
"Quartz": "Warning",
|
||||
"System.Net.Http": "Warning"
|
||||
"Microsoft.Hosting.Lifetime": "Information"
|
||||
}
|
||||
},
|
||||
"HostBuilder": {
|
||||
|
|
|
|||
|
|
@ -8,14 +8,14 @@
|
|||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Hangfire" />
|
||||
<PackageReference Include="Hangfire.MemoryStorage" />
|
||||
<PackageReference Include="Hangfire.Storage.SQLite" />
|
||||
<PackageReference Include="Hangfire"/>
|
||||
<PackageReference Include="Hangfire.MemoryStorage"/>
|
||||
<PackageReference Include="Hangfire.Storage.SQLite"/>
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\..\common\Elsa.Features\Elsa.Features.csproj" />
|
||||
<ProjectReference Include="..\Elsa.Scheduling\Elsa.Scheduling.csproj" />
|
||||
<ProjectReference Include="..\..\common\Elsa.Features\Elsa.Features.csproj"/>
|
||||
<ProjectReference Include="..\Elsa.Scheduling\Elsa.Scheduling.csproj"/>
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
|
|
|
|||
|
|
@ -25,6 +25,7 @@ public static class ModuleExtensions
|
|||
/// <summary>
|
||||
/// Configures Hangfire to use SQL Server storage. Only use this feature if you are not configuring Hangfire yourself.
|
||||
/// </summary>
|
||||
[Obsolete("Configure storage directly on the HangfireFeature.")]
|
||||
public static HangfireFeature UseSqlServerStorage(this HangfireFeature feature, Action<HangfireSqlServerStorageFeature> configure)
|
||||
{
|
||||
feature.Module.Use(configure);
|
||||
|
|
@ -34,6 +35,7 @@ public static class ModuleExtensions
|
|||
/// <summary>
|
||||
/// Configures Hangfire to use SQLite storage. Only use this feature if you are not configuring Hangfire yourself.
|
||||
/// </summary>
|
||||
[Obsolete("Configure storage directly on the HangfireFeature.")]
|
||||
public static HangfireFeature UseSqliteStorage(this HangfireFeature feature, Action<HangfireSqliteStorageFeature> configure)
|
||||
{
|
||||
feature.Module.Use(configure);
|
||||
|
|
|
|||
|
|
@ -1,5 +1,7 @@
|
|||
using Elsa.Features.Abstractions;
|
||||
using Elsa.Features.Attributes;
|
||||
using Elsa.Features.Services;
|
||||
using Elsa.Workflows.Runtime.Features;
|
||||
using Hangfire;
|
||||
using Hangfire.MemoryStorage;
|
||||
using Newtonsoft.Json;
|
||||
|
|
@ -9,35 +11,63 @@ namespace Elsa.Hangfire.Features;
|
|||
/// <summary>
|
||||
/// Sets up Hangfire. If you're setting up Hangfire yourself, then you should not enable this feature.
|
||||
/// </summary>
|
||||
public class HangfireFeature : FeatureBase
|
||||
[DependsOn(typeof(WorkflowRuntimeFeature))] // Ensure that the workflow runtime feature's hosted services have executed before Hangfire Server starts.
|
||||
public class HangfireFeature(IModule module) : FeatureBase(module)
|
||||
{
|
||||
/// <inheritdoc />
|
||||
public HangfireFeature(IModule module) : base(module)
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// A delegate that configures Hangfire.
|
||||
/// </summary>
|
||||
public Action<IServiceProvider, IGlobalConfiguration> ConfigureHangfire { get; set; } = (_, cfg) => cfg.UseMemoryStorage();
|
||||
private Action<IServiceProvider, IGlobalConfiguration> _configureHangfire = (_, _) => { };
|
||||
|
||||
/// <summary>
|
||||
/// A delegate that configures Hangfire's background job server options.
|
||||
/// </summary>
|
||||
public Action<IServiceProvider, BackgroundJobServerOptions> ConfigureBackgroundServerOptions { get; set; } = (_, _) => { };
|
||||
private Action<IServiceProvider, BackgroundJobServerOptions> _configureBackgroundServerOptions = (_, _) => { };
|
||||
|
||||
/// <summary>
|
||||
/// A delegate that creates a job storage instance.
|
||||
/// </summary>
|
||||
public Func<JobStorage> CreateJobStorage { get; set; } = () => new MemoryStorage();
|
||||
private Func<JobStorage> _createJobStorage = () => new MemoryStorage();
|
||||
|
||||
/// <summary>
|
||||
/// Configures Hangfire.
|
||||
/// </summary>
|
||||
public HangfireFeature ConfigureHangfire(Action<IServiceProvider, IGlobalConfiguration> configure)
|
||||
{
|
||||
_configureHangfire += configure;
|
||||
return this;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Configures Hangfire's background job server options.
|
||||
/// </summary>
|
||||
public HangfireFeature ConfigureBackgroundServerOptions(Action<IServiceProvider, BackgroundJobServerOptions> configure)
|
||||
{
|
||||
_configureBackgroundServerOptions += configure;
|
||||
return this;
|
||||
}
|
||||
|
||||
public HangfireFeature UseMemoryStorage()
|
||||
{
|
||||
return UseJobStorage(new MemoryStorage());
|
||||
}
|
||||
|
||||
public HangfireFeature UseJobStorage(JobStorage storage)
|
||||
{
|
||||
_createJobStorage = () => storage;
|
||||
return this;
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public override void Apply()
|
||||
{
|
||||
var jobStorage = _createJobStorage();
|
||||
|
||||
Action<IServiceProvider, IGlobalConfiguration> configAction = (sp, cfg) =>
|
||||
{
|
||||
cfg.UseSimpleAssemblyNameTypeSerializer();
|
||||
cfg.UseRecommendedSerializerSettings(json => json.TypeNameHandling = TypeNameHandling.Objects);
|
||||
cfg.UseStorage(jobStorage);
|
||||
};
|
||||
|
||||
Action<IServiceProvider, BackgroundJobServerOptions> serverOptionsAction = (sp, options) =>
|
||||
|
|
@ -46,10 +76,10 @@ public class HangfireFeature : FeatureBase
|
|||
options.SchedulePollingInterval = TimeSpan.FromSeconds(1);
|
||||
};
|
||||
|
||||
configAction += ConfigureHangfire;
|
||||
serverOptionsAction += ConfigureBackgroundServerOptions;
|
||||
configAction += _configureHangfire;
|
||||
serverOptionsAction += _configureBackgroundServerOptions;
|
||||
|
||||
Services.AddHangfire(configAction);
|
||||
Services.AddHangfireServer(serverOptionsAction, CreateJobStorage());
|
||||
Services.AddHangfireServer(serverOptionsAction, jobStorage);
|
||||
}
|
||||
}
|
||||
|
|
@ -11,18 +11,14 @@ namespace Elsa.Hangfire.Features;
|
|||
/// Configures the Hangfire feature to use SQL Server storage. If you're setting up Hangfire yourself, then you should not enable this feature.
|
||||
/// </summary>
|
||||
[DependsOn(typeof(HangfireFeature))]
|
||||
public class HangfireSqlServerStorageFeature : FeatureBase
|
||||
[Obsolete("Configure storage directly on the HangfireFeature.")]
|
||||
public class HangfireSqlServerStorageFeature(IModule module) : FeatureBase(module)
|
||||
{
|
||||
/// <inheritdoc />
|
||||
public HangfireSqlServerStorageFeature(IModule module) : base(module)
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// The connection string to use when connecting to SQL Server, or the name of the connection string.
|
||||
/// </summary>
|
||||
public string NameOrConnectionString { get; set; } = default!;
|
||||
|
||||
public string NameOrConnectionString { get; set; } = null!;
|
||||
|
||||
/// <summary>
|
||||
/// Configures the SQL Server storage options.
|
||||
/// </summary>
|
||||
|
|
@ -41,13 +37,11 @@ public class HangfireSqlServerStorageFeature : FeatureBase
|
|||
UseRecommendedIsolationLevel = true
|
||||
};
|
||||
ConfigureSqlServerStorageOptions(storageOptions);
|
||||
|
||||
hangfireFeature.ConfigureHangfire = (_, cfg) =>
|
||||
|
||||
hangfireFeature.ConfigureHangfire((_, cfg) =>
|
||||
{
|
||||
cfg.UseSqlServerStorage(NameOrConnectionString, storageOptions);
|
||||
};
|
||||
|
||||
hangfireFeature.CreateJobStorage = () => new SqlServerStorage(NameOrConnectionString, storageOptions);
|
||||
});
|
||||
});
|
||||
}
|
||||
}
|
||||
|
|
@ -10,17 +10,13 @@ namespace Elsa.Hangfire.Features;
|
|||
/// Configures the Hangfire feature to use SQLite storage. If you're setting up Hangfire yourself, then you should not enable this feature.
|
||||
/// </summary>
|
||||
[DependsOn(typeof(HangfireFeature))]
|
||||
public class HangfireSqliteStorageFeature : FeatureBase
|
||||
[Obsolete("Configure storage directly on the HangfireFeature.")]
|
||||
public class HangfireSqliteStorageFeature(IModule module) : FeatureBase(module)
|
||||
{
|
||||
/// <inheritdoc />
|
||||
public HangfireSqliteStorageFeature(IModule module) : base(module)
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// The connection string to use when connecting to SQL Server, or the name of the connection string.
|
||||
/// </summary>
|
||||
public string NameOrConnectionString { get; set; } = default!;
|
||||
public string NameOrConnectionString { get; set; } = null!;
|
||||
|
||||
/// <summary>
|
||||
/// Configures the SQL Server storage options.
|
||||
|
|
@ -38,12 +34,10 @@ public class HangfireSqliteStorageFeature : FeatureBase
|
|||
};
|
||||
ConfigureSqlServerStorageOptions(storageOptions);
|
||||
|
||||
hangfireFeature.ConfigureHangfire = (_, cfg) =>
|
||||
hangfireFeature.ConfigureHangfire((_, cfg) =>
|
||||
{
|
||||
cfg.UseSQLiteStorage(NameOrConnectionString, storageOptions);
|
||||
};
|
||||
|
||||
hangfireFeature.CreateJobStorage = () => new SQLiteStorage(NameOrConnectionString, storageOptions);
|
||||
});
|
||||
});
|
||||
}
|
||||
}
|
||||
|
|
@ -22,7 +22,7 @@ namespace Elsa.Workflows;
|
|||
/// <param name="Child">The child <see cref="IActivity"/> being scheduled.</param>
|
||||
/// <param name="CompletionCallback">The <see cref="ActivityCompletionCallback"/> delegate to invoke when the scheduled <see cref="Child"/> activity completes.</param>
|
||||
/// <param name="Tag">An optional tag.</param>
|
||||
public record ActivityCompletionCallbackEntry(ActivityExecutionContext Owner, ActivityNode Child, ActivityCompletionCallback? CompletionCallback, object? Tag = default);
|
||||
public record ActivityCompletionCallbackEntry(ActivityExecutionContext Owner, ActivityNode Child, ActivityCompletionCallback? CompletionCallback, object? Tag = null);
|
||||
|
||||
/// <summary>
|
||||
/// Provides context to the currently executing workflow.
|
||||
|
|
@ -239,7 +239,7 @@ public partial class WorkflowExecutionContext : IExecutionContext
|
|||
public WorkflowSubStatus SubStatus { get; internal set; }
|
||||
|
||||
/// The root <see cref="MemoryRegister"/> associated with the execution context.
|
||||
public MemoryRegister MemoryRegister { get; private set; } = default!;
|
||||
public MemoryRegister MemoryRegister { get; private set; } = null!;
|
||||
|
||||
/// A unique ID of the execution context.
|
||||
public string Id { get; set; }
|
||||
|
|
@ -406,7 +406,7 @@ public partial class WorkflowExecutionContext : IExecutionContext
|
|||
/// <summary>
|
||||
/// Registers a completion callback for the specified activity.
|
||||
/// </summary>
|
||||
internal void AddCompletionCallback(ActivityExecutionContext owner, ActivityNode child, ActivityCompletionCallback? completionCallback = default, object? tag = default)
|
||||
internal void AddCompletionCallback(ActivityExecutionContext owner, ActivityNode child, ActivityCompletionCallback? completionCallback = null, object? tag = null)
|
||||
{
|
||||
var entry = new ActivityCompletionCallbackEntry(owner, child, completionCallback, tag);
|
||||
_completionCallbackEntries.Add(entry);
|
||||
|
|
@ -420,7 +420,7 @@ public partial class WorkflowExecutionContext : IExecutionContext
|
|||
var entry = _completionCallbackEntries.FirstOrDefault(x => x.Owner == owner && x.Child == child);
|
||||
|
||||
if (entry == null)
|
||||
return default;
|
||||
return null;
|
||||
|
||||
RemoveCompletionCallback(entry);
|
||||
return entry;
|
||||
|
|
@ -449,25 +449,25 @@ public partial class WorkflowExecutionContext : IExecutionContext
|
|||
? FindActivityByInstanceId(handle.ActivityInstanceId)
|
||||
: handle.ActivityHash != null
|
||||
? FindActivityByHash(handle.ActivityHash)
|
||||
: default;
|
||||
: null;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns the <see cref="ActivityNode"/> with the specified activity ID from the workflow graph.
|
||||
/// </summary>
|
||||
public ActivityNode? FindNodeById(string nodeId) => NodeIdLookup.TryGetValue(nodeId, out var node) ? node : default;
|
||||
public ActivityNode? FindNodeById(string nodeId) => NodeIdLookup.TryGetValue(nodeId, out var node) ? node : null;
|
||||
|
||||
/// <summary>
|
||||
/// Returns the <see cref="ActivityNode"/> with the specified hash of the activity node ID from the workflow graph.
|
||||
/// </summary>
|
||||
/// <param name="hash">The hash of the activity node ID.</param>
|
||||
/// <returns>The <see cref="ActivityNode"/> with the specified hash of the activity node ID.</returns>
|
||||
public ActivityNode? FindNodeByHash(string hash) => NodeHashLookup.TryGetValue(hash, out var node) ? node : default;
|
||||
public ActivityNode? FindNodeByHash(string hash) => NodeHashLookup.TryGetValue(hash, out var node) ? node : null;
|
||||
|
||||
/// Returns the <see cref="ActivityNode"/> containing the specified activity from the workflow graph.
|
||||
public ActivityNode? FindNodeByActivity(IActivity activity)
|
||||
{
|
||||
return NodeActivityLookup.TryGetValue(activity, out var node) ? node : default;
|
||||
return NodeActivityLookup.TryGetValue(activity, out var node) ? node : null;
|
||||
}
|
||||
|
||||
/// Returns the <see cref="ActivityNode"/> associated with the specified activity ID.
|
||||
|
|
@ -526,7 +526,7 @@ public partial class WorkflowExecutionContext : IExecutionContext
|
|||
}
|
||||
|
||||
/// Creates a new <see cref="ActivityExecutionContext"/> for the specified activity.
|
||||
public async Task<ActivityExecutionContext> CreateActivityExecutionContextAsync(IActivity activity, ActivityInvocationOptions? options = default)
|
||||
public async Task<ActivityExecutionContext> CreateActivityExecutionContextAsync(IActivity activity, ActivityInvocationOptions? options = null)
|
||||
{
|
||||
var activityDescriptor = await ActivityRegistryLookup.FindAsync(activity) ?? throw new ActivityNotFoundException(activity.Type);
|
||||
var tag = options?.Tag;
|
||||
|
|
@ -568,7 +568,7 @@ public partial class WorkflowExecutionContext : IExecutionContext
|
|||
public ActivityOutputRegister GetActivityOutputRegister() => TransientProperties.GetOrAdd(ActivityOutputRegistryKey, () => new ActivityOutputRegister());
|
||||
|
||||
/// Returns the last activity result.
|
||||
public object? GetLastActivityResult() => TransientProperties.TryGetValue(LastActivityResultKey, out var value) ? value : default;
|
||||
public object? GetLastActivityResult() => TransientProperties.TryGetValue(LastActivityResultKey, out var value) ? value : null;
|
||||
|
||||
/// Adds the specified <see cref="ActivityExecutionContext"/> to the workflow execution context.
|
||||
public void AddActivityExecutionContext(ActivityExecutionContext context) => _activityExecutionContexts.Add(context);
|
||||
|
|
|
|||
Loading…
Reference in a new issue