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
Original file line number Diff line number Diff line change
Expand Up @@ -97,19 +97,7 @@ public async Task<DaprTestApplication> BuildAndStartAsync()
}
catch (Exception ex)
{
lastError = ex;

if (attemptApp is not null)
{
try
{
await attemptApp.StopAsync();
}
finally
{
await attemptApp.DisposeAsync();
}
}
lastError = await StopAndDisposeAppAsync(attemptApp, ex);
}
}

Expand Down Expand Up @@ -148,19 +136,7 @@ public async Task<DaprTestApplication> BuildAndStartAsync()
}
catch (Exception ex)
{
lastError = ex;

if (attemptApp is not null)
{
try
{
await attemptApp.StopAsync();
}
finally
{
await attemptApp.DisposeAsync();
}
}
lastError = await StopAndDisposeAppAsync(attemptApp, ex);

// Try again with a frest set of ports
}
Expand Down Expand Up @@ -212,4 +188,34 @@ private static int GetBoundPort(WebApplication app)

throw new InvalidOperationException($"Unable to determine bound port from addresses: {string.Join(", ", addresses)}");
}

private static async Task<Exception> StopAndDisposeAppAsync(WebApplication? app, Exception startupException)
{
if (app is null)
{
return startupException;
}

try
{
await app.StopAsync();
}
catch (Exception stopException)
{
startupException = new AggregateException(startupException, stopException);
}
finally
{
try
{
await app.DisposeAsync();
}
catch (Exception disposeException)
{
startupException = new AggregateException(startupException, disposeException);
}
}

return startupException;
}
}
17 changes: 17 additions & 0 deletions src/Dapr.Workflow.Versioning.Runtime/AssemblyInfo.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
// ------------------------------------------------------------------------
// Copyright 2026 The Dapr Authors
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
// http://www.apache.org/licenses/LICENSE-2.0
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
// ------------------------------------------------------------------------

using System.Runtime.CompilerServices;

// Allow Dapr.Workflow to order versioning registrations before plain auto-registrations.
[assembly: InternalsVisibleTo("Dapr.Workflow, PublicKey=0024000004800000940000000602000000240000525341310004000001000100b1f597635c44597fcecb493e2b1327033b29b1a98ac956a1a538664b68f87d45fbaada0438a15a6265e62864947cc067d8da3a7d93c5eb2fcbb850e396c8684dba74ea477d82a1bbb18932c0efb30b64ff1677f85ae833818707ac8b49ad8062ca01d2c89d8ab1843ae73e8ba9649cd28666b539444dcdee3639f95e2a099bb2")]
20 changes: 14 additions & 6 deletions src/Dapr.Workflow/WorkflowServiceCollectionExtensions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
using Dapr.Workflow.Grpc.Extensions;
using Dapr.Workflow.Registration;
using Dapr.Workflow.Serialization;
using Dapr.Workflow.Versioning;
using Dapr.Workflow.Worker;
using Grpc.Net.ClientFactory;
using Microsoft.Extensions.Configuration;
Expand Down Expand Up @@ -174,12 +175,6 @@ private static void AddDaprWorkflowCore(
var options = new WorkflowRuntimeOptions();
configure(options);

// Apply source-generated auto-registrations (workflows and activities discovered by the
// Dapr Workflow source generator). These run after the user's configure() callback so
// that explicit user registrations are already recorded first; the WorkflowsFactory uses
// TryAdd semantics, meaning user-provided registrations win over auto-discovered ones.
WorkflowAutoRegistry.Apply(options);

// Register options as a singleton as they don't change at runtime
serviceCollection.AddSingleton(options);

Expand All @@ -196,6 +191,19 @@ private static void AddDaprWorkflowCore(
var logger = loggerFactory.CreateLogger<WorkflowsFactory>();
var factory = new WorkflowsFactory(logger);

if (sp.GetService<IWorkflowVersionStrategyFactory>() is not null &&
sp.GetService<IWorkflowVersionSelectorFactory>() is not null)
{
WorkflowVersioningRegistry.Apply(sp);
}

// Apply source-generated auto-registrations (workflows and activities discovered by the
// Dapr Workflow source generator). These run after the user's configure() callback, and
// after versioning-generated registrations when versioning is configured. The factory uses
// TryAdd semantics, so user-provided registrations win over versioning aliases, and
// versioning aliases win over plain generated simple-name registrations.
WorkflowAutoRegistry.Apply(options);

// Apply all registrations from options
options.ApplyRegistrations(factory);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -80,14 +80,16 @@ public async Task ShouldCombinePatchAndNameBasedVersioning()
using var resumeCts = new CancellationTokenSource(TimeSpan.FromMinutes(2));
var resumed = await client2.WaitForWorkflowCompletionAsync(instanceIdV1, cancellation: resumeCts.Token);
Assert.Equal(WorkflowRuntimeStatus.Completed, resumed.RuntimeStatus);
Assert.Equal("v1:6:resume", resumed.ReadOutputAs<string>());
Assert.StartsWith("v1:", resumed.ReadOutputAs<string>());
Assert.EndsWith(":resume", resumed.ReadOutputAs<string>());

await client2.ScheduleNewWorkflowAsync(latestNameV2, instanceIdV2, 5);
await client2.RaiseEventAsync(instanceIdV2, ResumeEventName, "resume", resumeCts.Token);
using var latestCts = new CancellationTokenSource(TimeSpan.FromMinutes(2));
var latest = await client2.WaitForWorkflowCompletionAsync(instanceIdV2, cancellation: latestCts.Token);
Assert.Equal(WorkflowRuntimeStatus.Completed, latest.RuntimeStatus);
Assert.Equal("v2:16:resume", latest.ReadOutputAs<string>());
Assert.StartsWith("v1:", resumed.ReadOutputAs<string>());
Assert.EndsWith(":resume", resumed.ReadOutputAs<string>());
}
}

Expand Down
Loading
Loading