Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions SKILL.md
Original file line number Diff line number Diff line change
Expand Up @@ -456,6 +456,8 @@ services
services.RegisterWorkflow<SignalWait>();
```

`RegisterWaiter` and `ISignalStore` are registered only by `AddSignalWait`. Projects that call `AddConductorSharpPatterns()` or `AddCSharpLambdaTasks()` without `AddSignalWait` need no signal store.

**Important**: The `InMemorySignalStore` is only suitable for development/testing. For production, implement `ISignalStore` with a persistent backend (database, Redis, etc.) to ensure signals survive process restarts and work across multiple instances.

#### Using Signal Wait in a Workflow
Expand Down
2 changes: 1 addition & 1 deletion src/ConductorSharp.Client/ConductorSharp.Client.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
<Authors>Codaxy</Authors>
<Company>Codaxy</Company>
<PackageId>ConductorSharp.Client</PackageId>
<Version>4.4.0</Version>
<Version>4.4.1</Version>
<Description>Client library for Netflix Conductor, with some additional quality of life features.</Description>
<RepositoryUrl>https://github.com/codaxy/conductor-sharp</RepositoryUrl>
<PackageTags>netflix;conductor</PackageTags>
Expand Down
2 changes: 1 addition & 1 deletion src/ConductorSharp.Engine/ConductorSharp.Engine.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
<Authors>Codaxy</Authors>
<Company>Codaxy</Company>
<PackageId>ConductorSharp.Engine</PackageId>
<Version>4.4.0</Version>
<Version>4.4.1</Version>
<Description>Client library for Netflix Conductor, with some additional quality of life features.</Description>
<RepositoryUrl>https://github.com/codaxy/conductor-sharp</RepositoryUrl>
<PackageTags>netflix;conductor</PackageTags>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
<TargetFramework>net6.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
<Version>4.4.0</Version>
<Version>4.4.1</Version>
<Authors>Codaxy</Authors>
<Company>Codaxy</Company>
</PropertyGroup>
Expand Down
2 changes: 1 addition & 1 deletion src/ConductorSharp.Patterns/ConductorSharp.Patterns.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
<GeneratePackageOnBuild>False</GeneratePackageOnBuild>
<Authors>Codaxy</Authors>
<Company>Codaxy</Company>
<Version>4.4.0</Version>
<Version>4.4.1</Version>
</PropertyGroup>

<ItemGroup>
Expand Down
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
using System.Reflection;
using ConductorSharp.Engine.Extensions;
using ConductorSharp.Engine.Interface;
using ConductorSharp.Engine.Util;
Expand All @@ -16,7 +17,7 @@ public static IExecutionManagerBuilder AddConductorSharpPatterns(this IExecution
executionManagerBuilder.Builder.RegisterWorkerTask<ReadWorkflowTasks>();
executionManagerBuilder.Builder.RegisterWorkerTask<WaitSeconds>();
executionManagerBuilder.Builder.RegisterWorkerTask<BuildFailureError>();
executionManagerBuilder.Builder.AddMediatR(cfg => cfg.RegisterServicesFromAssemblies(typeof(WaitSeconds).Assembly));
executionManagerBuilder.Builder.AddMediatR(cfg => RegisterPatternHandlers(cfg, typeof(WaitSeconds).Assembly));

return executionManagerBuilder;
}
Expand All @@ -30,7 +31,7 @@ public static IExecutionManagerBuilder AddCSharpLambdaTasks(
{
options.OwnerEmail = "owneremail@gmail.com";
});
executionManagerBuilder.Builder.AddMediatR(cfg => cfg.RegisterServicesFromAssemblies(typeof(CSharpLambdaTask).Assembly));
executionManagerBuilder.Builder.AddMediatR(cfg => RegisterPatternHandlers(cfg, typeof(CSharpLambdaTask).Assembly));
executionManagerBuilder.Builder.AddSingleton(
new ConfigurationProperty(CSharpLambdaTask.LambdaTaskNameConfigurationProperty, csharpLambdaTaskNamePrefix)
);
Expand Down Expand Up @@ -95,5 +96,13 @@ public static IExecutionManagerBuilder AddSignalWait<TSignalStore>(

return executionManagerBuilder;
}

// RegisterWaiter depends on ISignalStore, which only AddSignalWait registers,
// so the other registrations leave it out of the assembly scan.
private static void RegisterPatternHandlers(MediatRServiceConfiguration cfg, Assembly assembly)
{
cfg.RegisterServicesFromAssemblies(assembly);
cfg.TypeEvaluator = type => type != typeof(RegisterWaiter);
}
}
}
2 changes: 1 addition & 1 deletion src/ConductorSharp.Toolkit/ConductorSharp.Toolkit.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
<Nullable>disable</Nullable>
<PackAsTool>true</PackAsTool>
<ToolCommandName>dotnet-conductorsharp</ToolCommandName>
<Version>4.4.0</Version>
<Version>4.4.1</Version>
</PropertyGroup>

<ItemGroup>
Expand Down
63 changes: 63 additions & 0 deletions test/ConductorSharp.Engine.Tests/Unit/PatternsRegistrationTests.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
using ConductorSharp.Engine.Extensions;
using ConductorSharp.Engine.Interface;
using ConductorSharp.Patterns.Extensions;
using ConductorSharp.Patterns.Services;
using ConductorSharp.Patterns.Tasks;
using MediatR;
using Microsoft.Extensions.DependencyInjection;

namespace ConductorSharp.Engine.Tests.Unit
{
public class PatternsRegistrationTests
{
private static readonly ServiceProviderOptions ValidateOnBuild = new() { ValidateOnBuild = true, ValidateScopes = true };

private static (IServiceCollection Services, IExecutionManagerBuilder Builder) CreateBuilder()
{
var services = new ServiceCollection();
var builder = services
.AddConductorSharp(baseUrl: "http://empty/empty")
.AddExecutionManager(
maxConcurrentWorkers: 1,
sleepInterval: 1,
longPollInterval: 1,
domain: null,
handlerAssemblies: typeof(PatternsRegistrationTests).Assembly
);

return (services, builder);
}

[Fact]
public void PatternsWithoutSignalWaitDoNotRequireSignalStore()
{
var (services, builder) = CreateBuilder();
builder.AddConductorSharpPatterns().AddCSharpLambdaTasks();

using var provider = services.BuildServiceProvider(ValidateOnBuild);

Assert.DoesNotContain(services, d => d.ImplementationType == typeof(RegisterWaiter));
}

[Theory]
[InlineData(true)]
[InlineData(false)]
public void SignalWaitRegistersRegisterWaiterHandler(bool signalWaitFirst)
{
var (services, builder) = CreateBuilder();
if (signalWaitFirst)
builder.AddSignalWait<InMemorySignalStore>().AddConductorSharpPatterns().AddCSharpLambdaTasks();
else
builder.AddConductorSharpPatterns().AddCSharpLambdaTasks().AddSignalWait<InMemorySignalStore>();

using var provider = services.BuildServiceProvider(ValidateOnBuild);

Assert.Contains(
services,
d =>
d.ServiceType == typeof(IRequestHandler<RegisterWaiterRequest, RegisterWaiterResponse>)
&& d.ImplementationType == typeof(RegisterWaiter)
);
}
}
}
Loading