diff --git a/Directory.Packages.props b/Directory.Packages.props
index 0ae482e5..6858226c 100644
--- a/Directory.Packages.props
+++ b/Directory.Packages.props
@@ -41,6 +41,7 @@
+
diff --git a/src/modules/Directory.Build.props b/src/modules/Directory.Build.props
index bd564a59..de79e646 100644
--- a/src/modules/Directory.Build.props
+++ b/src/modules/Directory.Build.props
@@ -17,4 +17,8 @@
-
\ No newline at end of file
+
+
+
+
+
diff --git a/src/modules/scheduling/Elsa.Scheduling.Hangfire/ShellFeatures/HangfireShellFeature.cs b/src/modules/scheduling/Elsa.Scheduling.Hangfire/ShellFeatures/HangfireShellFeature.cs
index 31a02b28..393fce86 100644
--- a/src/modules/scheduling/Elsa.Scheduling.Hangfire/ShellFeatures/HangfireShellFeature.cs
+++ b/src/modules/scheduling/Elsa.Scheduling.Hangfire/ShellFeatures/HangfireShellFeature.cs
@@ -1,4 +1,5 @@
using CShells.Features;
+using Elsa.PackageManifest.Generator.Hints;
using Hangfire;
using Hangfire.MemoryStorage;
using JetBrains.Annotations;
@@ -16,8 +17,25 @@ namespace Elsa.Scheduling.Hangfire.ShellFeatures;
[UsedImplicitly]
public class HangfireShellFeature : IShellFeature
{
+ [ManifestSetting(
+ DisplayName = "Use memory storage",
+ Description = "Use Hangfire's in-memory storage provider.",
+ Category = "Storage",
+ RestartRequired = true)]
public bool UseMemoryStorage { get; set; } = true;
+
+ [ManifestSetting(
+ DisplayName = "Worker count",
+ Description = "The number of Hangfire worker threads to run.",
+ Category = "Workers",
+ RestartRequired = true)]
public int WorkerCount { get; set; } = 1;
+
+ [ManifestSetting(
+ DisplayName = "Schedule polling interval",
+ Description = "The Hangfire schedule polling interval in seconds.",
+ Category = "Scheduling",
+ RestartRequired = true)]
public int SchedulePollingIntervalSeconds { get; set; } = 1;
public void ConfigureServices(IServiceCollection services)
@@ -38,4 +56,3 @@ public void ConfigureServices(IServiceCollection services)
});
}
}
-
diff --git a/src/modules/scheduling/Elsa.Scheduling.Quartz.EFCore.MySql/ShellFeatures/QuartzMySqlFeature.cs b/src/modules/scheduling/Elsa.Scheduling.Quartz.EFCore.MySql/ShellFeatures/QuartzMySqlFeature.cs
index 735f0793..2ccfb39f 100644
--- a/src/modules/scheduling/Elsa.Scheduling.Quartz.EFCore.MySql/ShellFeatures/QuartzMySqlFeature.cs
+++ b/src/modules/scheduling/Elsa.Scheduling.Quartz.EFCore.MySql/ShellFeatures/QuartzMySqlFeature.cs
@@ -1,5 +1,6 @@
using CShells.Features;
using CShells.Lifecycle;
+using Elsa.PackageManifest.Generator.Hints;
using Elsa.Scheduling.Quartz.EFCore.MySql;
using Elsa.Scheduling.Quartz.ShellFeatures;
using JetBrains.Annotations;
@@ -17,15 +18,35 @@ namespace Elsa.Scheduling.Quartz.EFCore.MySql.ShellFeatures;
Description = "Configures Quartz.NET to persist jobs and triggers in MySQL",
DependsOn = [typeof(QuartzSchedulerFeature)])]
[UsedImplicitly]
+[ManifestInfrastructure("mysql-database", "database", Reason = "Stores Quartz scheduler data in MySQL.", Providers = new[] { "MySQL" }, ConfigurationKeys = new[] { "ConnectionString" })]
public class QuartzMySqlFeature : IShellFeature
{
/// The MySQL connection string.
+ [ManifestSetting(
+ DisplayName = "Connection string",
+ Description = "The MySQL connection string used by the Quartz persistent job store.",
+ Category = "Persistence",
+ Secret = true,
+ Required = true,
+ HasRequired = true,
+ RestartRequired = true)]
public string ConnectionString { get; set; } = "Server=localhost;Database=quartz;User=root;Password=root;";
/// Enable Quartz clustering. Defaults to true.
+ [ManifestSetting(
+ DisplayName = "Use clustering",
+ Description = "Enable Quartz clustering.",
+ Category = "Persistence",
+ RestartRequired = true)]
public bool UseClustering { get; set; } = true;
/// Use a pooled IDbContextFactory. Defaults to false.
+ [ManifestSetting(
+ DisplayName = "Use context pooling",
+ Description = "Use a pooled EF Core IDbContextFactory.",
+ Category = "Persistence",
+ Advanced = true,
+ RestartRequired = true)]
public bool UseContextPooling { get; set; }
public void ConfigureServices(IServiceCollection services)
diff --git a/src/modules/scheduling/Elsa.Scheduling.Quartz.EFCore.PostgreSql/ShellFeatures/QuartzPostgreSqlFeature.cs b/src/modules/scheduling/Elsa.Scheduling.Quartz.EFCore.PostgreSql/ShellFeatures/QuartzPostgreSqlFeature.cs
index 8a4f9a91..b43ff39a 100644
--- a/src/modules/scheduling/Elsa.Scheduling.Quartz.EFCore.PostgreSql/ShellFeatures/QuartzPostgreSqlFeature.cs
+++ b/src/modules/scheduling/Elsa.Scheduling.Quartz.EFCore.PostgreSql/ShellFeatures/QuartzPostgreSqlFeature.cs
@@ -1,5 +1,6 @@
using CShells.Features;
using CShells.Lifecycle;
+using Elsa.PackageManifest.Generator.Hints;
using Elsa.Scheduling.Quartz.EFCore.PostgreSql;
using Elsa.Scheduling.Quartz.ShellFeatures;
using JetBrains.Annotations;
@@ -17,15 +18,35 @@ namespace Elsa.Scheduling.Quartz.EFCore.PostgreSql.ShellFeatures;
Description = "Configures Quartz.NET to persist jobs and triggers in PostgreSQL",
DependsOn = [typeof(QuartzSchedulerFeature)])]
[UsedImplicitly]
+[ManifestInfrastructure("postgresql-database", "database", Reason = "Stores Quartz scheduler data in PostgreSQL.", Providers = new[] { "PostgreSQL" }, ConfigurationKeys = new[] { "ConnectionString" })]
public class QuartzPostgreSqlFeature : IShellFeature
{
/// The PostgreSQL connection string.
+ [ManifestSetting(
+ DisplayName = "Connection string",
+ Description = "The PostgreSQL connection string used by the Quartz persistent job store.",
+ Category = "Persistence",
+ Secret = true,
+ Required = true,
+ HasRequired = true,
+ RestartRequired = true)]
public string ConnectionString { get; set; } = "Host=localhost;Database=quartz;Username=postgres;Password=postgres";
/// Enable Quartz clustering. Defaults to true.
+ [ManifestSetting(
+ DisplayName = "Use clustering",
+ Description = "Enable Quartz clustering.",
+ Category = "Persistence",
+ RestartRequired = true)]
public bool UseClustering { get; set; } = true;
/// Use a pooled IDbContextFactory. Defaults to false.
+ [ManifestSetting(
+ DisplayName = "Use context pooling",
+ Description = "Use a pooled EF Core IDbContextFactory.",
+ Category = "Persistence",
+ Advanced = true,
+ RestartRequired = true)]
public bool UseContextPooling { get; set; }
public void ConfigureServices(IServiceCollection services)
diff --git a/src/modules/scheduling/Elsa.Scheduling.Quartz.EFCore.SqlServer/ShellFeatures/QuartzSqlServerFeature.cs b/src/modules/scheduling/Elsa.Scheduling.Quartz.EFCore.SqlServer/ShellFeatures/QuartzSqlServerFeature.cs
index 76da2398..a4e8bf1e 100644
--- a/src/modules/scheduling/Elsa.Scheduling.Quartz.EFCore.SqlServer/ShellFeatures/QuartzSqlServerFeature.cs
+++ b/src/modules/scheduling/Elsa.Scheduling.Quartz.EFCore.SqlServer/ShellFeatures/QuartzSqlServerFeature.cs
@@ -1,5 +1,6 @@
using CShells.Features;
using CShells.Lifecycle;
+using Elsa.PackageManifest.Generator.Hints;
using Elsa.Scheduling.Quartz.EFCore.SqlServer;
using Elsa.Scheduling.Quartz.ShellFeatures;
using JetBrains.Annotations;
@@ -17,15 +18,35 @@ namespace Elsa.Scheduling.Quartz.EFCore.SqlServer.ShellFeatures;
Description = "Configures Quartz.NET to persist jobs and triggers in SQL Server",
DependsOn = [typeof(QuartzSchedulerFeature)])]
[UsedImplicitly]
+[ManifestInfrastructure("sqlserver-database", "database", Reason = "Stores Quartz scheduler data in SQL Server.", Providers = new[] { "SQL Server" }, ConfigurationKeys = new[] { "ConnectionString" })]
public class QuartzSqlServerFeature : IShellFeature
{
/// The SQL Server connection string.
+ [ManifestSetting(
+ DisplayName = "Connection string",
+ Description = "The SQL Server connection string used by the Quartz persistent job store.",
+ Category = "Persistence",
+ Secret = true,
+ Required = true,
+ HasRequired = true,
+ RestartRequired = true)]
public string ConnectionString { get; set; } = "Server=localhost;Database=Quartz;Trusted_Connection=True;";
/// Enable Quartz clustering. Defaults to true.
+ [ManifestSetting(
+ DisplayName = "Use clustering",
+ Description = "Enable Quartz clustering.",
+ Category = "Persistence",
+ RestartRequired = true)]
public bool UseClustering { get; set; } = true;
/// Use a pooled IDbContextFactory. Defaults to false.
+ [ManifestSetting(
+ DisplayName = "Use context pooling",
+ Description = "Use a pooled EF Core IDbContextFactory.",
+ Category = "Persistence",
+ Advanced = true,
+ RestartRequired = true)]
public bool UseContextPooling { get; set; }
public void ConfigureServices(IServiceCollection services)
diff --git a/src/modules/scheduling/Elsa.Scheduling.Quartz.EFCore.Sqlite/ShellFeatures/QuartzSqliteFeature.cs b/src/modules/scheduling/Elsa.Scheduling.Quartz.EFCore.Sqlite/ShellFeatures/QuartzSqliteFeature.cs
index 4d849581..0597a164 100644
--- a/src/modules/scheduling/Elsa.Scheduling.Quartz.EFCore.Sqlite/ShellFeatures/QuartzSqliteFeature.cs
+++ b/src/modules/scheduling/Elsa.Scheduling.Quartz.EFCore.Sqlite/ShellFeatures/QuartzSqliteFeature.cs
@@ -1,5 +1,6 @@
using CShells.Features;
using CShells.Lifecycle;
+using Elsa.PackageManifest.Generator.Hints;
using Elsa.Scheduling.Quartz.EFCore.Sqlite;
using Elsa.Scheduling.Quartz.ShellFeatures;
using JetBrains.Annotations;
@@ -17,18 +18,39 @@ namespace Elsa.Scheduling.Quartz.EFCore.Sqlite.ShellFeatures;
Description = "Configures Quartz.NET to persist jobs and triggers in SQLite",
DependsOn = [typeof(QuartzSchedulerFeature)])]
[UsedImplicitly]
+[ManifestInfrastructure("sqlite-database", "database", Reason = "Stores Quartz scheduler data in SQLite.", Providers = new[] { "SQLite" }, ConfigurationKeys = new[] { "ConnectionString" })]
public class QuartzSqliteFeature : IShellFeature, IPostConfigureShellServices
{
/// The SQLite connection string.
+ [ManifestSetting(
+ DisplayName = "Connection string",
+ Description = "The SQLite connection string used by the Quartz persistent job store.",
+ Category = "Persistence",
+ Secret = true,
+ Required = true,
+ HasRequired = true,
+ RestartRequired = true)]
public string ConnectionString { get; set; } = "Data Source=quartz.db";
///
/// Enable Quartz clustering. Defaults to false — SQLite does not
/// support true multi-node clustering.
///
+ [ManifestSetting(
+ DisplayName = "Use clustering",
+ Description = "Enable Quartz clustering. SQLite does not support true multi-node clustering.",
+ Category = "Persistence",
+ Advanced = true,
+ RestartRequired = true)]
public bool UseClustering { get; set; }
/// Use a pooled IDbContextFactory. Defaults to false.
+ [ManifestSetting(
+ DisplayName = "Use context pooling",
+ Description = "Use a pooled EF Core IDbContextFactory.",
+ Category = "Persistence",
+ Advanced = true,
+ RestartRequired = true)]
public bool UseContextPooling { get; set; }
public void ConfigureServices(IServiceCollection services)
diff --git a/src/modules/scheduling/Elsa.Scheduling.Quartz/ShellFeatures/QuartzFeature.cs b/src/modules/scheduling/Elsa.Scheduling.Quartz/ShellFeatures/QuartzFeature.cs
index acd6bd39..58af3e7f 100644
--- a/src/modules/scheduling/Elsa.Scheduling.Quartz/ShellFeatures/QuartzFeature.cs
+++ b/src/modules/scheduling/Elsa.Scheduling.Quartz/ShellFeatures/QuartzFeature.cs
@@ -1,5 +1,6 @@
using CShells.Features;
using CShells.Lifecycle;
+using Elsa.PackageManifest.Generator.Hints;
using JetBrains.Annotations;
using Microsoft.Extensions.DependencyInjection;
using Quartz;
@@ -18,21 +19,42 @@ public class QuartzFeature : IShellFeature, IPostConfigureShellServices
///
/// Optional delay before the scheduler begins processing jobs after shell activation.
///
+ [ManifestSetting(
+ DisplayName = "Start delay",
+ Description = "Optional delay before the scheduler begins processing jobs after shell activation.",
+ Category = "Scheduler",
+ Advanced = true,
+ RestartRequired = true)]
public TimeSpan? StartDelay { get; set; }
///
/// Whether to wait for running jobs to complete before the scheduler shuts down on
/// shell deactivation. Defaults to true.
///
+ [ManifestSetting(
+ DisplayName = "Wait for jobs to complete",
+ Description = "Wait for running jobs to complete before the scheduler shuts down on shell deactivation.",
+ Category = "Scheduler",
+ RestartRequired = true)]
public bool WaitForJobsToComplete { get; set; } = true;
///
/// The Quartz scheduler instance ID. Use "AUTO" (default) for automatic
/// generation, which is required for clustering.
///
+ [ManifestSetting(
+ DisplayName = "Scheduler ID",
+ Description = "The Quartz scheduler instance ID. Use AUTO for automatic generation, which is required for clustering.",
+ Category = "Scheduler",
+ RestartRequired = true)]
public string SchedulerId { get; set; } = "AUTO";
/// The Quartz scheduler name. Defaults to "ElsaScheduler".
+ [ManifestSetting(
+ DisplayName = "Scheduler name",
+ Description = "The Quartz scheduler name.",
+ Category = "Scheduler",
+ RestartRequired = true)]
public string SchedulerName { get; set; } = "ElsaScheduler";
public void ConfigureServices(IServiceCollection services)
diff --git a/src/modules/scheduling/Elsa.Scheduling.Quartz/ShellFeatures/QuartzSchedulerFeature.cs b/src/modules/scheduling/Elsa.Scheduling.Quartz/ShellFeatures/QuartzSchedulerFeature.cs
index 243735ee..5a0c3751 100644
--- a/src/modules/scheduling/Elsa.Scheduling.Quartz/ShellFeatures/QuartzSchedulerFeature.cs
+++ b/src/modules/scheduling/Elsa.Scheduling.Quartz/ShellFeatures/QuartzSchedulerFeature.cs
@@ -16,7 +16,10 @@ namespace Elsa.Scheduling.Quartz.ShellFeatures;
///
/// A feature that installs Quartz.NET implementations for .
///
-[ShellFeature(DependsOn = [
+[ShellFeature(
+ DisplayName = "Quartz Workflow Scheduler",
+ Description = "Uses Quartz.NET to schedule workflow execution.",
+ DependsOn = [
typeof(QuartzFeature),
typeof(SchedulingFeature),
typeof(ResilienceFeature)])]
@@ -34,4 +37,4 @@ public void ConfigureServices(IServiceCollection services)
.AddSingleton()
.AddQuartz();
}
-}
\ No newline at end of file
+}
diff --git a/src/modules/servicebus/Elsa.ServiceBus.AzureServiceBus/ShellFeatures/AzureServiceBusShellFeature.cs b/src/modules/servicebus/Elsa.ServiceBus.AzureServiceBus/ShellFeatures/AzureServiceBusShellFeature.cs
index ed686070..84595dc2 100644
--- a/src/modules/servicebus/Elsa.ServiceBus.AzureServiceBus/ShellFeatures/AzureServiceBusShellFeature.cs
+++ b/src/modules/servicebus/Elsa.ServiceBus.AzureServiceBus/ShellFeatures/AzureServiceBusShellFeature.cs
@@ -1,4 +1,5 @@
using CShells.Features;
+using Elsa.PackageManifest.Generator.Hints;
using JetBrains.Annotations;
using Microsoft.Extensions.DependencyInjection;
@@ -11,8 +12,17 @@ namespace Elsa.ServiceBus.AzureServiceBus.ShellFeatures;
DisplayName = "Azure Service Bus",
Description = "Enables Azure Service Bus for message publishing and handling")]
[UsedImplicitly]
+[ManifestInfrastructure("azure-service-bus", "service-bus", Reason = "Publishes and consumes workflow messages through Azure Service Bus.", Providers = new[] { "Azure Service Bus" }, ConfigurationKeys = new[] { "ConnectionStringOrName" })]
public class AzureServiceBusShellFeature : IShellFeature
{
+ [ManifestSetting(
+ DisplayName = "Connection string or name",
+ Description = "The Azure Service Bus connection string or configured connection string name.",
+ Category = "Connection",
+ Secret = true,
+ Required = true,
+ HasRequired = true,
+ RestartRequired = true)]
public string ConnectionStringOrName { get; set; } = string.Empty;
public void ConfigureServices(IServiceCollection services)
@@ -22,4 +32,3 @@ public void ConfigureServices(IServiceCollection services)
.Configure(options => options.ConnectionStringOrName = ConnectionStringOrName);
}
}
-
diff --git a/src/modules/servicebus/Elsa.ServiceBus.Kafka/ShellFeatures/KafkaShellFeature.cs b/src/modules/servicebus/Elsa.ServiceBus.Kafka/ShellFeatures/KafkaShellFeature.cs
index a289a4cb..ec65b5da 100644
--- a/src/modules/servicebus/Elsa.ServiceBus.Kafka/ShellFeatures/KafkaShellFeature.cs
+++ b/src/modules/servicebus/Elsa.ServiceBus.Kafka/ShellFeatures/KafkaShellFeature.cs
@@ -1,4 +1,5 @@
using CShells.Features;
+using Elsa.PackageManifest.Generator.Hints;
using JetBrains.Annotations;
using Microsoft.Extensions.DependencyInjection;
@@ -11,9 +12,15 @@ namespace Elsa.ServiceBus.Kafka.ShellFeatures;
DisplayName = "Kafka Service Bus",
Description = "Enables Apache Kafka for message publishing and handling")]
[UsedImplicitly]
+[ManifestInfrastructure("kafka-broker", "message-broker", Reason = "Publishes and consumes workflow messages through Apache Kafka.", Providers = new[] { "Apache Kafka" }, ConfigurationKeys = new[] { "WorkflowInstanceIdHeaderKey" })]
public class KafkaShellFeature : IShellFeature
{
- public string WorkflowInstanceIdHeaderKey { get; set; } = "localhost:9092";
+ [ManifestSetting(
+ DisplayName = "Workflow instance ID header key",
+ Description = "The Kafka message header key used to carry the workflow instance ID.",
+ Category = "Headers",
+ RestartRequired = true)]
+ public string WorkflowInstanceIdHeaderKey { get; set; } = "x-workflow-instance-id";
public void ConfigureServices(IServiceCollection services)
{
@@ -25,4 +32,3 @@ public void ConfigureServices(IServiceCollection services)
});
}
}
-
diff --git a/src/modules/servicebus/Elsa.ServiceBus.MassTransit.AzureServiceBus/ShellFeatures/MassTransitAzureServiceBusFeature.cs b/src/modules/servicebus/Elsa.ServiceBus.MassTransit.AzureServiceBus/ShellFeatures/MassTransitAzureServiceBusFeature.cs
index 157b0af9..dec254bf 100644
--- a/src/modules/servicebus/Elsa.ServiceBus.MassTransit.AzureServiceBus/ShellFeatures/MassTransitAzureServiceBusFeature.cs
+++ b/src/modules/servicebus/Elsa.ServiceBus.MassTransit.AzureServiceBus/ShellFeatures/MassTransitAzureServiceBusFeature.cs
@@ -1,6 +1,7 @@
using Azure.Messaging.ServiceBus.Administration;
using CShells.Configuration;
using CShells.Features;
+using Elsa.PackageManifest.Generator.Hints;
using Elsa.ServiceBus.MassTransit.AzureServiceBus.Configurators;
using Elsa.ServiceBus.MassTransit.AzureServiceBus.Handlers;
using Elsa.ServiceBus.MassTransit.AzureServiceBus.HostedServices;
@@ -30,12 +31,19 @@ namespace Elsa.ServiceBus.MassTransit.AzureServiceBus.ShellFeatures;
Description = "Configures MassTransit to use Azure Service Bus as the message transport",
DependsOn = [typeof(MassTransitFeature)])]
[UsedImplicitly]
+[ManifestInfrastructure("azure-service-bus", "service-bus", Reason = "Configures MassTransit to use Azure Service Bus as its transport.", Providers = new[] { "Azure Service Bus" }, ConfigurationKeys = new[] { "MassTransitAzureServiceBus:ConnectionStringOrName", "MassTransitAzureServiceBusCleanup" })]
public class MassTransitAzureServiceBusFeature : IShellFeature
{
///
/// When true, registers a hosted service that periodically removes orphaned
/// subscriptions whose connected queues no longer exist.
///
+ [ManifestSetting(
+ DisplayName = "Enable automated subscription cleanup",
+ Description = "Periodically removes orphaned Azure Service Bus subscriptions whose connected queues no longer exist.",
+ Category = "Cleanup",
+ Advanced = true,
+ RestartRequired = true)]
public bool EnableAutomatedSubscriptionCleanup { get; set; }
public void ConfigureServices(IServiceCollection services)
@@ -71,4 +79,4 @@ public void ConfigureServices(IServiceCollection services)
// Replace the default InMemoryTransportConfigurator.
services.AddSingleton();
}
-}
\ No newline at end of file
+}
diff --git a/src/modules/servicebus/Elsa.ServiceBus.MassTransit.RabbitMq/ShellFeatures/MassTransitRabbitMqFeature.cs b/src/modules/servicebus/Elsa.ServiceBus.MassTransit.RabbitMq/ShellFeatures/MassTransitRabbitMqFeature.cs
index badbdebf..30eab87d 100644
--- a/src/modules/servicebus/Elsa.ServiceBus.MassTransit.RabbitMq/ShellFeatures/MassTransitRabbitMqFeature.cs
+++ b/src/modules/servicebus/Elsa.ServiceBus.MassTransit.RabbitMq/ShellFeatures/MassTransitRabbitMqFeature.cs
@@ -1,5 +1,6 @@
using CShells.Configuration;
using CShells.Features;
+using Elsa.PackageManifest.Generator.Hints;
using Elsa.ServiceBus.MassTransit.Contracts;
using Elsa.ServiceBus.MassTransit.RabbitMq.Configurators;
using Elsa.ServiceBus.MassTransit.RabbitMq.Options;
@@ -25,6 +26,7 @@ namespace Elsa.ServiceBus.MassTransit.RabbitMq.ShellFeatures;
Description = "Configures MassTransit to use RabbitMQ as the message transport",
DependsOn = [typeof(MassTransitFeature)])]
[UsedImplicitly]
+[ManifestInfrastructure("rabbitmq-broker", "message-broker", Reason = "Configures MassTransit to use RabbitMQ as its transport.", Providers = new[] { "RabbitMQ" }, ConfigurationKeys = new[] { "MassTransitRabbitMq" })]
public class MassTransitRabbitMqFeature : IShellFeature
{
public void ConfigureServices(IServiceCollection services)