Skip to content

Commit

Permalink
Merge branch 'main' into primary-ctors
Browse files Browse the repository at this point in the history
  • Loading branch information
jviau committed Apr 4, 2024
2 parents df25197 + a0eddf4 commit 18a2125
Show file tree
Hide file tree
Showing 30 changed files with 312 additions and 86 deletions.
15 changes: 14 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,10 +1,23 @@
# Changelog

# v1.2.1

- Fix typo in `PurgeInstanceAsync` in `DurableTaskClient` (https://github.com/microsoft/durabletask-dotnet/pull/264)
- Fix `TaskFailureDetails.IsCausedBy` to support custom exceptions and 3rd party exceptions ([#273](https://github.com/microsoft/durabletask-dotnet/pull/273))
- Microsoft.Azure.DurableTask.Core dependency increased to `2.16.2`

# v1.2.0

- Adds support to recursively terminate/purge sub-orchestrations in `GrpcDurableTaskClient` (https://github.com/microsoft/durabletask-dotnet/pull/262)

# v1.1.1

- Microsoft.Azure.DurableTask.Core dependency increased to `2.16.1`

# v1.1.0

- Microsoft.Azure.DurableTask.Core dependency increased to `2.16.0`


## v1.1.0-preview.2

- Microsoft.Azure.DurableTask.Core dependency increased to `2.16.0-preview.2`
Expand Down
8 changes: 7 additions & 1 deletion azure-pipelines-release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,13 @@ steps:
submodules: true

- task: UseDotNet@2
displayName: 'Install .NET SDK'
displayName: 'Install .NET 6 SDK (ESRP)' # This is needed for ESRP.
inputs:
packageType: 'sdk'
version: '6.x'

- task: UseDotNet@2
displayName: 'Install .NET SDK (Build)' # This is needed for the build.
inputs:
packageType: 'sdk'
useGlobalJson: true
Expand Down
22 changes: 22 additions & 0 deletions doc/release_process.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
# Release Process

1. Rev versions as appropriate following semver.
- Repo-wide versions can be found in `eng/targets/Release.props`
- Individual packages can version independently by adding the `<VersionPrefix>` and `<VersionSuffix>` properties directly in their `.csproj`.
- We follow an approach of just releasing everything, even if the package has no changes. _Unless_ we intentionally do not want to release a package.
2. Ensure appropriate `RELEASENOTES.md` are updated in the repository.
- These are per-package and contain only that packages changes.
- The contents will be included in the `.nupkg` and show up in nuget.org's release notes tab.
- Clear these files after a release.
3. Ensure `CHANGELOG.md` in repo root is updated.
4. Tag the release.
- `git tag v<version>`, `git push <remote> -u <tag>`
5. Draft github release for new tag.
6. Kick off [ADO release build](https://dev.azure.com/durabletaskframework/Durable%20Task%20Framework%20CI/_build?definitionId=29) (use the tag as the build target, enter `refs/tags/<tag>`)
7. Validate signing, package contents (if build changes were made.)
8. Create ADO release.
- From successful ADO release build, click 3 dots in top right -> 'Release'.
9. Release to ADO feed.
10. Release to nuget once validated (and dependencies are also released to nuget.)
11. Publish github draft release.
12. Delete contents of all `RELEASENOTES.md` files.
2 changes: 1 addition & 1 deletion eng/proto
2 changes: 1 addition & 1 deletion eng/targets/Release.props
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@
</PropertyGroup>

<PropertyGroup>
<VersionPrefix>1.1.0</VersionPrefix>
<VersionPrefix>1.2.2</VersionPrefix>
<VersionSuffix></VersionSuffix>
</PropertyGroup>

Expand Down
1 change: 1 addition & 0 deletions misc/misc.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
<None Include="$(RepoRoot)nuget.config" />
<None Include="$(EngRoot)**" LinkBase="eng" />
<None Include="$(RepoRoot).github/**" LinkBase="github" />
<None Include="$(RepoRoot)doc/**" LinkBase="doc" />
</ItemGroup>

</Project>
6 changes: 3 additions & 3 deletions samples/AzureFunctionsApp/AzureFunctionsApp.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -8,10 +8,10 @@
</PropertyGroup>

<ItemGroup>
<PackageReference Include="Microsoft.Azure.Functions.Worker" Version="1.19.0" />
<PackageReference Include="Microsoft.Azure.Functions.Worker.Extensions.DurableTask" Version="1.1.0-preview.2" />
<PackageReference Include="Microsoft.Azure.Functions.Worker" Version="1.20.0" />
<PackageReference Include="Microsoft.Azure.Functions.Worker.Extensions.DurableTask" Version="1.1.0" />
<PackageReference Include="Microsoft.Azure.Functions.Worker.Extensions.Http" Version="3.0.13" />
<PackageReference Include="Microsoft.Azure.Functions.Worker.Sdk" Version="1.16.0-preview2" OutputItemType="Analyzer" />
<PackageReference Include="Microsoft.Azure.Functions.Worker.Sdk" Version="1.16.2" OutputItemType="Analyzer" />
<PackageReference Include="Microsoft.DurableTask.Generators" Version="1.0.0-preview.1" OutputItemType="Analyzer" />
</ItemGroup>

Expand Down
4 changes: 2 additions & 2 deletions samples/ConsoleApp/ConsoleApp.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,8 @@

<ItemGroup>
<PackageReference Include="Microsoft.Extensions.Hosting" Version="6.0.0" />
<PackageReference Include="Microsoft.DurableTask.Client.Grpc" Version="1.0.0" />
<PackageReference Include="Microsoft.DurableTask.Worker.Grpc" Version="1.0.0" />
<PackageReference Include="Microsoft.DurableTask.Client.Grpc" Version="1.1.0" />
<PackageReference Include="Microsoft.DurableTask.Worker.Grpc" Version="1.1.0" />
</ItemGroup>

</Project>
4 changes: 2 additions & 2 deletions samples/NetFxConsoleApp/NetFxConsoleApp.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,8 @@

<ItemGroup>
<PackageReference Include="Microsoft.Extensions.Hosting" Version="6.0.0" />
<PackageReference Include="Microsoft.DurableTask.Client.Grpc" Version="1.0.0" />
<PackageReference Include="Microsoft.DurableTask.Worker.Grpc" Version="1.0.0" />
<PackageReference Include="Microsoft.DurableTask.Client.Grpc" Version="1.1.0" />
<PackageReference Include="Microsoft.DurableTask.Worker.Grpc" Version="1.1.0" />
</ItemGroup>

</Project>
4 changes: 2 additions & 2 deletions samples/WebAPI/WebAPI.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,8 @@
</PropertyGroup>

<ItemGroup>
<PackageReference Include="Microsoft.DurableTask.Client.Grpc" Version="1.0.0" />
<PackageReference Include="Microsoft.DurableTask.Worker.Grpc" Version="1.0.0" />
<PackageReference Include="Microsoft.DurableTask.Client.Grpc" Version="1.1.0" />
<PackageReference Include="Microsoft.DurableTask.Worker.Grpc" Version="1.1.0" />
<PackageReference Include="Microsoft.DurableTask.Generators" Version="1.0.0-preview.1" OutputItemType="Analyzer" />
</ItemGroup>

Expand Down
2 changes: 1 addition & 1 deletion src/Abstractions/Abstractions.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
</PropertyGroup>

<ItemGroup>
<PackageReference Include="Microsoft.Azure.DurableTask.Core" Version="2.16.0" />
<PackageReference Include="Microsoft.Azure.DurableTask.Core" Version="2.16.2" />
<PackageReference Include="Microsoft.Bcl.AsyncInterfaces" Version="6.0.0" />
<PackageReference Include="Microsoft.Extensions.DependencyInjection.Abstractions" Version="6.0.0" />
<PackageReference Include="Microsoft.Extensions.Logging.Abstractions" Version="6.0.0" />
Expand Down
2 changes: 0 additions & 2 deletions src/Abstractions/RELEASENOTES.md
Original file line number Diff line number Diff line change
@@ -1,2 +0,0 @@
- Add support for durable entities
- Microsoft.Azure.DurableTask.Core dependency increased to `2.16.0-preview.2`
5 changes: 4 additions & 1 deletion src/Abstractions/RetryPolicy.cs
Original file line number Diff line number Diff line change
Expand Up @@ -123,8 +123,11 @@ public RetryPolicy(
/// </value>
public TimeSpan RetryTimeout { get; }

#pragma warning disable SA1623 // Property summary documentation should match accessors
/// <summary>
/// Gets or sets a Func to call on exception to determine if retries should proceed.
/// This functionality is not implemented. Will be removed in the future. Use TaskOptions.FromRetryHandler instead.
/// </summary>
[Obsolete("This functionality is not implemented. Will be removed in the future. Use TaskOptions.FromRetryHandler instead.")]
public Func<Exception, Task<bool>>? HandleAsync { get; set; }
#pragma warning restore SA1623 // Property summary documentation should match accessors
}
64 changes: 60 additions & 4 deletions src/Abstractions/TaskFailureDetails.cs
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT License.

using System.Reflection;
using CoreOrchestrationException = DurableTask.Core.Exceptions.OrchestrationException;

namespace Microsoft.DurableTask;
Expand All @@ -14,7 +15,7 @@ namespace Microsoft.DurableTask;
/// <param name="InnerFailure">The inner cause of the task failure.</param>
public record TaskFailureDetails(string ErrorType, string ErrorMessage, string? StackTrace, TaskFailureDetails? InnerFailure)
{
Type? exceptionType;
Type? loadedExceptionType;

/// <summary>
/// Gets a debug-friendly description of the failure information.
Expand All @@ -34,13 +35,68 @@ public override string ToString()
/// for any reason, this method will return <c>false</c>. Base types are supported.
/// </remarks>
/// <typeparam name="T">The type of exception to test against.</typeparam>
/// <exception cref="AmbiguousMatchException">If multiple exception types with the same name are found.</exception>
/// <returns>
/// Returns <c>true</c> if the <see cref="ErrorType"/> value matches <typeparamref name="T"/>; <c>false</c> otherwise.
/// <c>true</c> if the <see cref="ErrorType"/> value matches <typeparamref name="T"/>; <c>false</c> otherwise.
/// </returns>
public bool IsCausedBy<T>() where T : Exception
{
this.exceptionType ??= Type.GetType(this.ErrorType, throwOnError: false);
return this.exceptionType != null && typeof(T).IsAssignableFrom(this.exceptionType);
return this.IsCausedBy(typeof(T));
}

/// <returns>
/// <c>true</c> if the <see cref="ErrorType"/> value matches <paramref name="targetBaseExceptionType"/>; <c>false</c> otherwise.
/// </returns>
/// <exception cref="ArgumentException">If <paramref name="targetBaseExceptionType"/> is not an exception type.</exception>
/// <inheritdoc cref="IsCausedBy{T}"/>
public bool IsCausedBy(Type targetBaseExceptionType)
{
Check.NotNull(targetBaseExceptionType);

if (!typeof(Exception).IsAssignableFrom(targetBaseExceptionType))
{
throw new ArgumentException($"The type {targetBaseExceptionType} is not an exception type.", nameof(targetBaseExceptionType));
}

if (string.IsNullOrEmpty(this.ErrorType))
{
return false;
}

// This check works for .NET exception types defined in System.Core.PrivateLib (aka mscorelib.dll)
this.loadedExceptionType ??= Type.GetType(this.ErrorType, throwOnError: false);

// For exception types defined in the same assembly as the target exception type.
this.loadedExceptionType ??= targetBaseExceptionType.Assembly.GetType(this.ErrorType, throwOnError: false);

// For custom exception types defined in the app's assembly
this.loadedExceptionType ??= Assembly.GetCallingAssembly().GetType(this.ErrorType);

if (this.loadedExceptionType is null)
{
// This last check works for exception types defined in any loaded assembly (e.g. NuGet packages, etc.).
// This is a fallback that should rarely be needed except in obscure cases.
List<Type> matchingExceptionTypes = AppDomain.CurrentDomain.GetAssemblies()
.Select(a => a.GetType(this.ErrorType, throwOnError: false))
.Where(t => t is not null)
.ToList();
if (matchingExceptionTypes.Count == 1)
{
this.loadedExceptionType = matchingExceptionTypes[0];
}
else if (matchingExceptionTypes.Count > 1)
{
throw new AmbiguousMatchException($"Multiple exception types with the name '{this.ErrorType}' were found.");
}
}

if (this.loadedExceptionType is null)
{
// The actual exception type could not be loaded, so we cannot determine if it matches the target type.
return false;
}

return targetBaseExceptionType.IsAssignableFrom(this.loadedExceptionType);
}

/// <summary>
Expand Down
56 changes: 50 additions & 6 deletions src/Client/Core/DependencyInjection/DurableTaskClientExtensions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -15,24 +15,68 @@ public static class DurableTaskClientExtensions
/// <param name="createdFrom">Filter purging to orchestrations after this date.</param>
/// <param name="createdTo">Filter purging to orchestrations before this date.</param>
/// <param name="statuses">Filter purging to orchestrations with these statuses.</param>
/// <param name="options">The optional options for purging the orchestration.</param>
/// <param name="cancellation">The cancellation token.</param>
/// <returns>
/// This method returns a <see cref="PurgeResult"/> object after the operation has completed with a
/// <see cref="PurgeResult.PurgedInstanceCount"/> value of <c>1</c> or <c>0</c>, depending on whether the target
/// instance was successfully purged.
/// <see cref="PurgeResult.PurgedInstanceCount"/> indicating the number of orchestration instances that were purged,
/// including the count of sub-orchestrations purged if any.
/// </returns>
public static Task<PurgeResult> PurgeInstancesAsync(
this DurableTaskClient client,
DateTimeOffset? createdFrom,
DateTimeOffset? createdTo,
IEnumerable<OrchestrationRuntimeStatus>? statuses,
PurgeInstanceOptions? options,
CancellationToken cancellation = default)
{
Check.NotNull(client);
PurgeInstancesFilter filter = new(createdFrom, createdTo, statuses);
return client.PurgeAllInstancesAsync(filter, cancellation);
return client.PurgeAllInstancesAsync(filter, options, cancellation);
}

/// <summary>
/// Purges orchestration instances metadata from the durable store.
/// </summary>
/// <param name="client">The DurableTask client.</param>
/// <param name="createdFrom">Filter purging to orchestrations after this date.</param>
/// <param name="createdTo">Filter purging to orchestrations before this date.</param>
/// <param name="statuses">Filter purging to orchestrations with these statuses.</param>
/// <param name="cancellation">The cancellation token.</param>
/// <returns>
/// This method returns a <see cref="PurgeResult"/> object after the operation has completed with a
/// <see cref="PurgeResult.PurgedInstanceCount"/> indicating the number of orchestration instances that were purged,
/// including the count of sub-orchestrations purged if any.
/// </returns>
public static Task<PurgeResult> PurgeInstancesAsync(
this DurableTaskClient client,
DateTimeOffset? createdFrom,
DateTimeOffset? createdTo,
IEnumerable<OrchestrationRuntimeStatus>? statuses,
CancellationToken cancellation = default)
=> PurgeInstancesAsync(client, createdFrom, createdTo, statuses, null, cancellation);

/// <summary>
/// Purges orchestration instances metadata from the durable store.
/// </summary>
/// <param name="client">The DurableTask client.</param>
/// <param name="createdFrom">Filter purging to orchestrations after this date.</param>
/// <param name="createdTo">Filter purging to orchestrations before this date.</param>
/// <param name="options">The optional options for purging the orchestration.</param>
/// <param name="cancellation">The cancellation token.</param>
/// <returns>
/// This method returns a <see cref="PurgeResult"/> object after the operation has completed with a
/// <see cref="PurgeResult.PurgedInstanceCount"/> indicating the number of orchestration instances that were purged,
/// including the count of sub-orchestrations purged if any.
/// </returns>
public static Task<PurgeResult> PurgeInstancesAsync(
this DurableTaskClient client,
DateTimeOffset? createdFrom,
DateTimeOffset? createdTo,
PurgeInstanceOptions? options,
CancellationToken cancellation = default)
=> PurgeInstancesAsync(client, createdFrom, createdTo, null, options, cancellation);

/// <summary>
/// Purges orchestration instances metadata from the durable store.
/// </summary>
Expand All @@ -42,13 +86,13 @@ public static Task<PurgeResult> PurgeInstancesAsync(
/// <param name="cancellation">The cancellation token.</param>
/// <returns>
/// This method returns a <see cref="PurgeResult"/> object after the operation has completed with a
/// <see cref="PurgeResult.PurgedInstanceCount"/> value of <c>1</c> or <c>0</c>, depending on whether the target
/// instance was successfully purged.
/// <see cref="PurgeResult.PurgedInstanceCount"/> indicating the number of orchestration instances that were purged,
/// including the count of sub-orchestrations purged if any.
/// </returns>
public static Task<PurgeResult> PurgeInstancesAsync(
this DurableTaskClient client,
DateTimeOffset? createdFrom,
DateTimeOffset? createdTo,
CancellationToken cancellation = default)
=> PurgeInstancesAsync(client, createdFrom, createdTo, null, cancellation);
=> PurgeInstancesAsync(client, createdFrom, createdTo, null, null, cancellation);
}
Loading

0 comments on commit 18a2125

Please sign in to comment.