mirror of https://github.com/dapr/dotnet-sdk.git
Merge branch 'remove-workflow-methods' into remote-workflow-methods-4
# Conflicts: # test/Dapr.E2E.Test/Workflows/WorkflowTest.cs
This commit is contained in:
commit
8948152a87
|
@ -11,6 +11,9 @@
|
|||
// limitations under the License.
|
||||
// ------------------------------------------------------------------------
|
||||
|
||||
using Dapr.Actors.Communication;
|
||||
using IDemoActor;
|
||||
|
||||
namespace ActorClient
|
||||
{
|
||||
using System;
|
||||
|
@ -18,7 +21,6 @@ namespace ActorClient
|
|||
using System.Threading.Tasks;
|
||||
using Dapr.Actors;
|
||||
using Dapr.Actors.Client;
|
||||
using IDemoActorInterface;
|
||||
|
||||
/// <summary>
|
||||
/// Actor Client class.
|
||||
|
@ -43,7 +45,7 @@ namespace ActorClient
|
|||
|
||||
// Make strongly typed Actor calls with Remoting.
|
||||
// DemoActor is the type registered with Dapr runtime in the service.
|
||||
var proxy = ActorProxy.Create<IDemoActor>(actorId, "DemoActor");
|
||||
var proxy = ActorProxy.Create<IDemoActor.IDemoActor>(actorId, "DemoActor");
|
||||
|
||||
Console.WriteLine("Making call using actor proxy to save data.");
|
||||
await proxy.SaveData(data, TimeSpan.FromMinutes(10));
|
||||
|
|
|
@ -11,9 +11,9 @@
|
|||
// limitations under the License.
|
||||
// ------------------------------------------------------------------------
|
||||
|
||||
using IDemoActorInterface;
|
||||
using IDemoActor;
|
||||
|
||||
namespace DaprDemoActor
|
||||
namespace DemoActor
|
||||
{
|
||||
public class BankService
|
||||
{
|
||||
|
|
|
@ -11,14 +11,14 @@
|
|||
// limitations under the License.
|
||||
// ------------------------------------------------------------------------
|
||||
|
||||
namespace DaprDemoActor
|
||||
{
|
||||
using System;
|
||||
using System.Text.Json;
|
||||
using System.Threading.Tasks;
|
||||
using Dapr.Actors.Runtime;
|
||||
using IDemoActorInterface;
|
||||
using System;
|
||||
using System.Text.Json;
|
||||
using System.Threading.Tasks;
|
||||
using Dapr.Actors.Runtime;
|
||||
using IDemoActor;
|
||||
|
||||
namespace DemoActor
|
||||
{
|
||||
// The following example showcases a few features of Actors
|
||||
//
|
||||
// Every actor should inherit from the Actor type, and must implement one or more actor interfaces.
|
||||
|
@ -27,7 +27,7 @@ namespace DaprDemoActor
|
|||
// For Actors to use Reminders, it must derive from IRemindable.
|
||||
// If you don't intend to use Reminder feature, you can skip implementing IRemindable and reminder
|
||||
// specific methods which are shown in the code below.
|
||||
public class DemoActor : Actor, IDemoActor, IBankActor, IRemindable
|
||||
public class DemoActor : Actor, IDemoActor.IDemoActor, IBankActor, IRemindable
|
||||
{
|
||||
private const string StateName = "my_data";
|
||||
|
||||
|
|
|
@ -11,11 +11,11 @@
|
|||
// limitations under the License.
|
||||
// ------------------------------------------------------------------------
|
||||
|
||||
namespace DaprDemoActor
|
||||
{
|
||||
using Microsoft.AspNetCore.Hosting;
|
||||
using Microsoft.Extensions.Hosting;
|
||||
using Microsoft.AspNetCore.Hosting;
|
||||
using Microsoft.Extensions.Hosting;
|
||||
|
||||
namespace DemoActor
|
||||
{
|
||||
public class Program
|
||||
{
|
||||
public static void Main(string[] args)
|
||||
|
|
|
@ -11,14 +11,14 @@
|
|||
// limitations under the License.
|
||||
// ------------------------------------------------------------------------
|
||||
|
||||
namespace DaprDemoActor
|
||||
{
|
||||
using Microsoft.AspNetCore.Builder;
|
||||
using Microsoft.AspNetCore.Hosting;
|
||||
using Microsoft.Extensions.Configuration;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using Microsoft.Extensions.Hosting;
|
||||
using Microsoft.AspNetCore.Builder;
|
||||
using Microsoft.AspNetCore.Hosting;
|
||||
using Microsoft.Extensions.Configuration;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using Microsoft.Extensions.Hosting;
|
||||
|
||||
namespace DemoActor
|
||||
{
|
||||
public class Startup
|
||||
{
|
||||
public Startup(IConfiguration configuration)
|
||||
|
|
|
@ -11,12 +11,12 @@
|
|||
// limitations under the License.
|
||||
// ------------------------------------------------------------------------
|
||||
|
||||
namespace IDemoActorInterface
|
||||
{
|
||||
using System;
|
||||
using System.Threading.Tasks;
|
||||
using Dapr.Actors;
|
||||
using System;
|
||||
using System.Threading.Tasks;
|
||||
using Dapr.Actors;
|
||||
|
||||
namespace IDemoActor
|
||||
{
|
||||
public interface IBankActor : IActor
|
||||
{
|
||||
Task<AccountBalance> GetAccountBalance();
|
||||
|
|
|
@ -11,13 +11,12 @@
|
|||
// limitations under the License.
|
||||
// ------------------------------------------------------------------------
|
||||
|
||||
namespace IDemoActorInterface
|
||||
{
|
||||
using System;
|
||||
using System.Threading.Tasks;
|
||||
using Dapr.Actors;
|
||||
using Dapr.Actors.Runtime;
|
||||
using System;
|
||||
using System.Threading.Tasks;
|
||||
using Dapr.Actors;
|
||||
|
||||
namespace IDemoActor
|
||||
{
|
||||
/// <summary>
|
||||
/// Interface for Actor method.
|
||||
/// </summary>
|
||||
|
|
|
@ -11,6 +11,8 @@
|
|||
// limitations under the License.
|
||||
// ------------------------------------------------------------------------
|
||||
|
||||
using Dapr.AspNetCore;
|
||||
|
||||
namespace ControllerSample
|
||||
{
|
||||
using System;
|
||||
|
|
|
@ -11,6 +11,8 @@
|
|||
// limitations under the License.
|
||||
// ------------------------------------------------------------------------
|
||||
|
||||
using Dapr.AspNetCore;
|
||||
|
||||
namespace ControllerSample
|
||||
{
|
||||
using Microsoft.AspNetCore.Builder;
|
||||
|
|
|
@ -22,7 +22,7 @@ using Grpc.Core;
|
|||
using GrpcServiceSample.Generated;
|
||||
using Microsoft.Extensions.Logging;
|
||||
|
||||
namespace GrpcServiceSample
|
||||
namespace GrpcServiceSample.Services
|
||||
{
|
||||
/// <summary>
|
||||
/// BankAccount gRPC service
|
||||
|
|
|
@ -11,6 +11,8 @@
|
|||
// limitations under the License.
|
||||
// ------------------------------------------------------------------------
|
||||
|
||||
using Dapr.AspNetCore;
|
||||
using GrpcServiceSample.Services;
|
||||
using Microsoft.AspNetCore.Builder;
|
||||
using Microsoft.AspNetCore.Hosting;
|
||||
using Microsoft.AspNetCore.Http;
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
using System;
|
||||
using Dapr.AspNetCore;
|
||||
using Microsoft.AspNetCore.Builder;
|
||||
using Microsoft.AspNetCore.Hosting;
|
||||
using Microsoft.Extensions.Configuration;
|
||||
|
|
|
@ -11,10 +11,9 @@
|
|||
// limitations under the License.
|
||||
// ------------------------------------------------------------------------
|
||||
|
||||
using Cryptography;
|
||||
using Cryptography.Examples;
|
||||
|
||||
namespace Samples.Client
|
||||
namespace Cryptography
|
||||
{
|
||||
class Program
|
||||
{
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
using DistributedLock.Services;
|
||||
using Dapr.AspNetCore;
|
||||
using DistributedLock.Services;
|
||||
using Microsoft.AspNetCore.Builder;
|
||||
using Microsoft.AspNetCore.Hosting;
|
||||
using Microsoft.Extensions.Configuration;
|
||||
|
|
|
@ -1,7 +1,6 @@
|
|||
using Dapr.Client;
|
||||
using Dapr.Workflow;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using WorkflowConsoleApp.Models;
|
||||
|
||||
namespace WorkflowConsoleApp.Activities
|
||||
{
|
||||
|
|
|
@ -1,6 +1,5 @@
|
|||
using Dapr.Workflow;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using WorkflowConsoleApp.Models;
|
||||
|
||||
namespace WorkflowConsoleApp.Activities
|
||||
{
|
||||
|
|
|
@ -1,7 +1,6 @@
|
|||
using Dapr.Client;
|
||||
using Dapr.Workflow;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using WorkflowConsoleApp.Models;
|
||||
|
||||
namespace WorkflowConsoleApp.Activities
|
||||
{
|
||||
|
|
|
@ -1,6 +1,5 @@
|
|||
using Dapr.Client;
|
||||
using Dapr.Workflow;
|
||||
using WorkflowConsoleApp.Models;
|
||||
using Microsoft.Extensions.Logging;
|
||||
|
||||
namespace WorkflowConsoleApp.Activities
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
namespace WorkflowConsoleApp.Models
|
||||
namespace WorkflowConsoleApp
|
||||
{
|
||||
public record OrderPayload(string Name, double TotalCost, int Quantity = 1);
|
||||
public record InventoryRequest(string RequestId, string ItemName, int Quantity);
|
||||
|
|
|
@ -1,10 +1,10 @@
|
|||
using Dapr.Client;
|
||||
using Dapr.Workflow;
|
||||
using WorkflowConsoleApp.Activities;
|
||||
using WorkflowConsoleApp.Models;
|
||||
using WorkflowConsoleApp.Workflows;
|
||||
using Microsoft.Extensions.Hosting;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using WorkflowConsoleApp;
|
||||
|
||||
const string StoreName = "statestore";
|
||||
|
||||
|
|
|
@ -1,6 +1,5 @@
|
|||
using Dapr.Workflow;
|
||||
using WorkflowConsoleApp.Activities;
|
||||
using WorkflowConsoleApp.Models;
|
||||
|
||||
namespace WorkflowConsoleApp.Workflows
|
||||
{
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
using System.Threading.Tasks;
|
||||
using Dapr.Workflow;
|
||||
using Moq;
|
||||
using WorkflowConsoleApp;
|
||||
using WorkflowConsoleApp.Activities;
|
||||
using WorkflowConsoleApp.Models;
|
||||
using WorkflowConsoleApp.Workflows;
|
||||
using Xunit;
|
||||
|
||||
|
|
|
@ -1296,192 +1296,7 @@ namespace Dapr.Client
|
|||
string resourceId,
|
||||
string lockOwner,
|
||||
CancellationToken cancellationToken = default);
|
||||
|
||||
/// <summary>
|
||||
/// Attempt to start the given workflow with response indicating success.
|
||||
/// </summary>
|
||||
/// <param name="workflowComponent">The component to interface with.</param>
|
||||
/// <param name="workflowName">Name of the workflow to run.</param>
|
||||
/// <param name="instanceId">Identifier of the specific run.</param>
|
||||
/// <param name="input">The JSON-serializeable input for the given workflow.</param>
|
||||
/// <param name="workflowOptions">The list of options that are potentially needed to start a workflow.</param>
|
||||
/// <param name="cancellationToken">A <see cref="CancellationToken" /> that can be used to cancel the operation.</param>
|
||||
/// <returns>A <see cref="Task"/> containing a <see cref="StartWorkflowResponse"/></returns>
|
||||
[Obsolete("This API is currently not stable as it is in the Alpha stage. This attribute will be removed once it is stable.")]
|
||||
public abstract Task<StartWorkflowResponse> StartWorkflowAsync(
|
||||
string workflowComponent,
|
||||
string workflowName,
|
||||
string instanceId = null,
|
||||
object input = null,
|
||||
IReadOnlyDictionary<string, string> workflowOptions = default,
|
||||
CancellationToken cancellationToken = default);
|
||||
|
||||
/// <summary>
|
||||
/// Waits for a workflow to start running and returns a <see cref="GetWorkflowResponse"/> object that contains metadata
|
||||
/// about the started workflow.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// <para>
|
||||
/// A "started" workflow instance is any instance not in the <see cref="WorkflowRuntimeStatus.Pending"/> state.
|
||||
/// </para><para>
|
||||
/// This method will return a completed task if the workflow has already started running or has already completed.
|
||||
/// </para>
|
||||
/// </remarks>
|
||||
/// <param name="instanceId">The unique ID of the workflow instance to wait for.</param>
|
||||
/// <param name="workflowComponent">The component to interface with.</param>
|
||||
/// <param name="cancellationToken">A <see cref="CancellationToken"/> that can be used to cancel the wait operation.</param>
|
||||
/// <returns>
|
||||
/// Returns a <see cref="GetWorkflowResponse"/> record that describes the workflow instance and its execution status.
|
||||
/// </returns>
|
||||
/// <exception cref="OperationCanceledException">
|
||||
/// Thrown if <paramref name="cancellationToken"/> is canceled before the workflow starts running.
|
||||
/// </exception>
|
||||
[Obsolete("This API is currently not stable as it is in the Alpha stage. This attribute will be removed once it is stable.")]
|
||||
public virtual async Task<GetWorkflowResponse> WaitForWorkflowStartAsync(
|
||||
string instanceId,
|
||||
string workflowComponent,
|
||||
CancellationToken cancellationToken = default)
|
||||
{
|
||||
while (true)
|
||||
{
|
||||
var response = await this.GetWorkflowAsync(instanceId, workflowComponent, cancellationToken);
|
||||
if (response.RuntimeStatus != WorkflowRuntimeStatus.Pending)
|
||||
{
|
||||
return response;
|
||||
}
|
||||
|
||||
await Task.Delay(TimeSpan.FromMilliseconds(500), cancellationToken);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Waits for a workflow to complete and returns a <see cref="GetWorkflowResponse"/>
|
||||
/// object that contains metadata about the started instance.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// <para>
|
||||
/// A "completed" workflow instance is any instance in one of the terminal states. For example, the
|
||||
/// <see cref="WorkflowRuntimeStatus.Completed"/>, <see cref="WorkflowRuntimeStatus.Failed"/>, or
|
||||
/// <see cref="WorkflowRuntimeStatus.Terminated"/> states.
|
||||
/// </para><para>
|
||||
/// Workflows are long-running and could take hours, days, or months before completing.
|
||||
/// Workflows can also be eternal, in which case they'll never complete unless terminated.
|
||||
/// In such cases, this call may block indefinitely, so care must be taken to ensure appropriate timeouts are
|
||||
/// enforced using the <paramref name="cancellationToken"/> parameter.
|
||||
/// </para><para>
|
||||
/// If a workflow instance is already complete when this method is called, the method will return immediately.
|
||||
/// </para>
|
||||
/// </remarks>
|
||||
/// <returns>
|
||||
/// Returns a <see cref="GetWorkflowResponse"/> record that describes the workflow instance and its execution status.
|
||||
/// </returns>
|
||||
/// <exception cref="OperationCanceledException">
|
||||
/// Thrown if <paramref name="cancellationToken"/> is canceled before the workflow completes.
|
||||
/// </exception>
|
||||
[Obsolete("This API is currently not stable as it is in the Alpha stage. This attribute will be removed once it is stable.")]
|
||||
public virtual async Task<GetWorkflowResponse> WaitForWorkflowCompletionAsync(
|
||||
string instanceId,
|
||||
string workflowComponent,
|
||||
CancellationToken cancellationToken = default)
|
||||
{
|
||||
while (true)
|
||||
{
|
||||
var response = await this.GetWorkflowAsync(instanceId, workflowComponent, cancellationToken);
|
||||
if (response.RuntimeStatus == WorkflowRuntimeStatus.Completed ||
|
||||
response.RuntimeStatus == WorkflowRuntimeStatus.Failed ||
|
||||
response.RuntimeStatus == WorkflowRuntimeStatus.Terminated)
|
||||
{
|
||||
return response;
|
||||
}
|
||||
|
||||
await Task.Delay(TimeSpan.FromMilliseconds(500), cancellationToken);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Attempt to get information about the given workflow.
|
||||
/// </summary>
|
||||
/// <param name="instanceId">The unique ID of the target workflow instance.</param>
|
||||
/// <param name="workflowComponent">The component to interface with.</param>
|
||||
/// <param name="cancellationToken">A <see cref="CancellationToken" /> that can be used to cancel the operation.</param>
|
||||
/// <returns>A <see cref="Task"/> containing a <see cref="GetWorkflowResponse"/></returns>
|
||||
[Obsolete("This API is currently not stable as it is in the Alpha stage. This attribute will be removed once it is stable.")]
|
||||
public abstract Task<GetWorkflowResponse> GetWorkflowAsync(
|
||||
string instanceId,
|
||||
string workflowComponent,
|
||||
CancellationToken cancellationToken = default);
|
||||
|
||||
/// <summary>
|
||||
/// Attempt to get terminate the given workflow.
|
||||
/// </summary>
|
||||
/// <param name="instanceId">The unique ID of the target workflow instance.</param>
|
||||
/// <param name="workflowComponent">The component to interface with.</param>
|
||||
/// <param name="cancellationToken">A <see cref="CancellationToken" /> that can be used to cancel the operation.</param>
|
||||
/// <returns>A <see cref="Task" /> that will complete when the terminate operation has been scheduled. If the wrapped value is true the operation suceeded.</returns>
|
||||
[Obsolete("This API is currently not stable as it is in the Alpha stage. This attribute will be removed once it is stable.")]
|
||||
public abstract Task TerminateWorkflowAsync(
|
||||
string instanceId,
|
||||
string workflowComponent,
|
||||
CancellationToken cancellationToken = default);
|
||||
|
||||
/// <summary>
|
||||
/// Attempt to raise an event the given workflow with response indicating success.
|
||||
/// </summary>
|
||||
/// <param name="instanceId">Identifier of the specific run.</param>
|
||||
/// <param name="workflowComponent">The component to interface with.</param>
|
||||
/// <param name="eventName">Name of the event to raise.</param>
|
||||
/// <param name="eventData">The JSON-serializable event payload to include in the raised event.</param>
|
||||
/// <param name="cancellationToken">A <see cref="CancellationToken" /> that can be used to cancel the operation.</param>
|
||||
/// <returns>A <see cref="Task" /> that will complete when the raise event operation has been scheduled. If the wrapped value is true the operation suceeded.</returns>
|
||||
[Obsolete("This API is currently not stable as it is in the Alpha stage. This attribute will be removed once it is stable.")]
|
||||
public abstract Task RaiseWorkflowEventAsync(
|
||||
string instanceId,
|
||||
string workflowComponent,
|
||||
string eventName,
|
||||
object eventData = null,
|
||||
CancellationToken cancellationToken = default);
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Pauses the specified workflow instance.
|
||||
/// </summary>
|
||||
/// <param name="instanceId">The unique ID of the target workflow instance.</param>
|
||||
/// <param name="workflowComponent">The component to interface with.</param>
|
||||
/// <param name="cancellationToken">A <see cref="CancellationToken" /> that can be used to cancel the operation.</param>
|
||||
/// <returns>A <see cref="Task" /> that will complete when the pause operation has been scheduled. If the wrapped value is true the operation suceeded.</returns>
|
||||
[Obsolete("This API is currently not stable as it is in the Alpha stage. This attribute will be removed once it is stable.")]
|
||||
public abstract Task PauseWorkflowAsync(
|
||||
string instanceId,
|
||||
string workflowComponent,
|
||||
CancellationToken cancellationToken = default);
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Resumes a paused workflow instance.
|
||||
/// </summary>
|
||||
/// <param name="instanceId">The unique ID of the target workflow instance.</param>
|
||||
/// <param name="workflowComponent">The component to interface with.</param>
|
||||
/// <param name="cancellationToken">A <see cref="CancellationToken" /> that can be used to cancel the operation.</param>
|
||||
/// <returns>A <see cref="Task" /> that will complete when the resume operation has been scheduled. If the wrapped value is true the operation suceeded.</returns>
|
||||
[Obsolete("This API is currently not stable as it is in the Alpha stage. This attribute will be removed once it is stable.")]
|
||||
public abstract Task ResumeWorkflowAsync(
|
||||
string instanceId,
|
||||
string workflowComponent,
|
||||
CancellationToken cancellationToken = default);
|
||||
|
||||
/// <summary>
|
||||
/// Delete all state associated with the specified workflow instance. The workflow must be in a non-running state to be purged.
|
||||
/// </summary>
|
||||
/// <param name="instanceId">The unique ID of the target workflow instance.</param>
|
||||
/// <param name="workflowComponent">The component to interface with.</param>
|
||||
/// <param name="cancellationToken">A <see cref="CancellationToken" /> that can be used to cancel the operation.</param>
|
||||
/// <returns>A <see cref="Task" /> that will complete when the purge operation has been scheduled. If the wrapped value is true the operation suceeded.</returns>
|
||||
[Obsolete("This API is currently not stable as it is in the Alpha stage. This attribute will be removed once it is stable.")]
|
||||
public abstract Task PurgeWorkflowAsync(
|
||||
string instanceId,
|
||||
string workflowComponent,
|
||||
CancellationToken cancellationToken = default);
|
||||
|
||||
|
||||
/// <inheritdoc />
|
||||
public void Dispose()
|
||||
{
|
||||
|
|
|
@ -2036,287 +2036,6 @@ namespace Dapr.Client
|
|||
|
||||
#endregion
|
||||
|
||||
|
||||
#region Workflow API
|
||||
/// <inheritdoc/>
|
||||
[Obsolete]
|
||||
public async override Task<StartWorkflowResponse> StartWorkflowAsync(
|
||||
string workflowComponent,
|
||||
string workflowName,
|
||||
string instanceId = null,
|
||||
object input = null,
|
||||
IReadOnlyDictionary<string, string> workflowOptions = default,
|
||||
CancellationToken cancellationToken = default)
|
||||
{
|
||||
ArgumentVerifier.ThrowIfNullOrEmpty(instanceId, nameof(instanceId));
|
||||
ArgumentVerifier.ThrowIfNullOrEmpty(workflowComponent, nameof(workflowComponent));
|
||||
ArgumentVerifier.ThrowIfNullOrEmpty(workflowName, nameof(workflowName));
|
||||
ArgumentVerifier.ThrowIfNull(input, nameof(input));
|
||||
|
||||
// Serialize json data. Converts input object to bytes and then bytestring inside the request.
|
||||
byte[] jsonUtf8Bytes = null;
|
||||
if (input is not null)
|
||||
{
|
||||
jsonUtf8Bytes = JsonSerializer.SerializeToUtf8Bytes(input);
|
||||
}
|
||||
|
||||
var request = new Autogenerated.StartWorkflowRequest()
|
||||
{
|
||||
InstanceId = instanceId,
|
||||
WorkflowComponent = workflowComponent,
|
||||
WorkflowName = workflowName,
|
||||
Input = jsonUtf8Bytes is not null ? ByteString.CopyFrom(jsonUtf8Bytes) : null,
|
||||
};
|
||||
|
||||
if (workflowOptions?.Count > 0)
|
||||
{
|
||||
foreach (var item in workflowOptions)
|
||||
{
|
||||
request.Options[item.Key] = item.Value;
|
||||
}
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
var options = CreateCallOptions(headers: null, cancellationToken);
|
||||
var response = await client.StartWorkflowAlpha1Async(request, options);
|
||||
return new StartWorkflowResponse(response.InstanceId);
|
||||
|
||||
}
|
||||
catch (RpcException ex)
|
||||
{
|
||||
throw new DaprException("Start Workflow operation failed: the Dapr endpoint indicated a failure. See InnerException for details.", ex);
|
||||
}
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
[Obsolete]
|
||||
public async override Task<GetWorkflowResponse> GetWorkflowAsync(
|
||||
string instanceId,
|
||||
string workflowComponent,
|
||||
CancellationToken cancellationToken = default)
|
||||
{
|
||||
ArgumentVerifier.ThrowIfNullOrEmpty(instanceId, nameof(instanceId));
|
||||
ArgumentVerifier.ThrowIfNullOrEmpty(workflowComponent, nameof(workflowComponent));
|
||||
|
||||
var request = new Autogenerated.GetWorkflowRequest()
|
||||
{
|
||||
InstanceId = instanceId,
|
||||
WorkflowComponent = workflowComponent
|
||||
};
|
||||
|
||||
try
|
||||
{
|
||||
var options = CreateCallOptions(headers: null, cancellationToken);
|
||||
var response = await client.GetWorkflowAlpha1Async(request, options);
|
||||
if (response == null)
|
||||
{
|
||||
throw new DaprException("Get workflow operation failed: the Dapr endpoint returned an empty result.");
|
||||
}
|
||||
|
||||
response.CreatedAt ??= new Timestamp();
|
||||
response.LastUpdatedAt ??= response.CreatedAt;
|
||||
|
||||
return new GetWorkflowResponse
|
||||
{
|
||||
InstanceId = response.InstanceId,
|
||||
WorkflowName = response.WorkflowName,
|
||||
WorkflowComponentName = workflowComponent,
|
||||
CreatedAt = response.CreatedAt.ToDateTime(),
|
||||
LastUpdatedAt = response.LastUpdatedAt.ToDateTime(),
|
||||
RuntimeStatus = GetWorkflowRuntimeStatus(response.RuntimeStatus),
|
||||
Properties = response.Properties,
|
||||
FailureDetails = GetWorkflowFailureDetails(response, workflowComponent),
|
||||
};
|
||||
}
|
||||
catch (RpcException ex)
|
||||
{
|
||||
throw new DaprException("Get workflow operation failed: the Dapr endpoint indicated a failure. See InnerException for details.", ex);
|
||||
}
|
||||
}
|
||||
|
||||
private static WorkflowRuntimeStatus GetWorkflowRuntimeStatus(string runtimeStatus)
|
||||
{
|
||||
if (!System.Enum.TryParse(runtimeStatus, true /* ignoreCase */, out WorkflowRuntimeStatus status))
|
||||
{
|
||||
status = WorkflowRuntimeStatus.Unknown;
|
||||
}
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
private static WorkflowFailureDetails GetWorkflowFailureDetails(Autogenerated.GetWorkflowResponse response, string componentName)
|
||||
{
|
||||
// FUTURE: Make this part of the protobuf contract instead of getting it from properties
|
||||
// NOTE: The use of | instead of || is intentional. We want to get all the values.
|
||||
if (response.Properties.TryGetValue($"{componentName}.workflow.failure.error_type", out string errorType) |
|
||||
response.Properties.TryGetValue($"{componentName}.workflow.failure.error_message", out string errorMessage) |
|
||||
response.Properties.TryGetValue($"{componentName}.workflow.failure.stack_trace", out string stackTrace))
|
||||
{
|
||||
return new WorkflowFailureDetails(errorMessage, errorType, stackTrace);
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
[Obsolete]
|
||||
public async override Task TerminateWorkflowAsync(
|
||||
string instanceId,
|
||||
string workflowComponent,
|
||||
CancellationToken cancellationToken = default)
|
||||
{
|
||||
ArgumentVerifier.ThrowIfNullOrEmpty(instanceId, nameof(instanceId));
|
||||
ArgumentVerifier.ThrowIfNullOrEmpty(workflowComponent, nameof(workflowComponent));
|
||||
|
||||
var request = new Autogenerated.TerminateWorkflowRequest()
|
||||
{
|
||||
InstanceId = instanceId,
|
||||
WorkflowComponent = workflowComponent
|
||||
};
|
||||
|
||||
var options = CreateCallOptions(headers: null, cancellationToken);
|
||||
|
||||
try
|
||||
{
|
||||
await client.TerminateWorkflowAlpha1Async(request, options);
|
||||
}
|
||||
catch (RpcException ex)
|
||||
{
|
||||
throw new DaprException("Terminate workflow operation failed: the Dapr endpoint indicated a failure. See InnerException for details.", ex);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
[Obsolete]
|
||||
public async override Task RaiseWorkflowEventAsync(
|
||||
string instanceId,
|
||||
string workflowComponent,
|
||||
string eventName,
|
||||
Object eventData,
|
||||
CancellationToken cancellationToken = default)
|
||||
{
|
||||
ArgumentVerifier.ThrowIfNullOrEmpty(instanceId, nameof(instanceId));
|
||||
ArgumentVerifier.ThrowIfNullOrEmpty(workflowComponent, nameof(workflowComponent));
|
||||
ArgumentVerifier.ThrowIfNullOrEmpty(eventName, nameof(eventName));
|
||||
|
||||
byte[] jsonUtf8Bytes = new byte[0];
|
||||
// Serialize json data. Converts eventData object to bytes and then bytestring inside the request.
|
||||
if (eventData != null)
|
||||
{
|
||||
jsonUtf8Bytes = JsonSerializer.SerializeToUtf8Bytes(eventData);
|
||||
}
|
||||
|
||||
var request = new Autogenerated.RaiseEventWorkflowRequest()
|
||||
{
|
||||
InstanceId = instanceId,
|
||||
WorkflowComponent = workflowComponent,
|
||||
EventName = eventName,
|
||||
EventData = ByteString.CopyFrom(jsonUtf8Bytes),
|
||||
};
|
||||
|
||||
var options = CreateCallOptions(headers: null, cancellationToken);
|
||||
|
||||
try
|
||||
{
|
||||
await client.RaiseEventWorkflowAlpha1Async(request, options);
|
||||
}
|
||||
catch (RpcException ex)
|
||||
{
|
||||
throw new DaprException("Start Workflow operation failed: the Dapr endpoint indicated a failure. See InnerException for details.", ex);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/// <inheritdoc/>
|
||||
[Obsolete]
|
||||
public async override Task PauseWorkflowAsync(
|
||||
string instanceId,
|
||||
string workflowComponent,
|
||||
CancellationToken cancellationToken = default)
|
||||
{
|
||||
ArgumentVerifier.ThrowIfNullOrEmpty(instanceId, nameof(instanceId));
|
||||
ArgumentVerifier.ThrowIfNullOrEmpty(workflowComponent, nameof(workflowComponent));
|
||||
|
||||
var request = new Autogenerated.PauseWorkflowRequest()
|
||||
{
|
||||
InstanceId = instanceId,
|
||||
WorkflowComponent = workflowComponent
|
||||
};
|
||||
|
||||
var options = CreateCallOptions(headers: null, cancellationToken);
|
||||
|
||||
try
|
||||
{
|
||||
await client.PauseWorkflowAlpha1Async(request, options);
|
||||
}
|
||||
catch (RpcException ex)
|
||||
{
|
||||
throw new DaprException("Pause workflow operation failed: the Dapr endpoint indicated a failure. See InnerException for details.", ex);
|
||||
}
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
[Obsolete]
|
||||
public async override Task ResumeWorkflowAsync(
|
||||
string instanceId,
|
||||
string workflowComponent,
|
||||
CancellationToken cancellationToken = default)
|
||||
{
|
||||
ArgumentVerifier.ThrowIfNullOrEmpty(instanceId, nameof(instanceId));
|
||||
ArgumentVerifier.ThrowIfNullOrEmpty(workflowComponent, nameof(workflowComponent));
|
||||
|
||||
var request = new Autogenerated.ResumeWorkflowRequest()
|
||||
{
|
||||
InstanceId = instanceId,
|
||||
WorkflowComponent = workflowComponent
|
||||
};
|
||||
|
||||
var options = CreateCallOptions(headers: null, cancellationToken);
|
||||
|
||||
try
|
||||
{
|
||||
await client.ResumeWorkflowAlpha1Async(request, options);
|
||||
}
|
||||
catch (RpcException ex)
|
||||
{
|
||||
throw new DaprException("Resume workflow operation failed: the Dapr endpoint indicated a failure. See InnerException for details.", ex);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
[Obsolete]
|
||||
public async override Task PurgeWorkflowAsync(
|
||||
string instanceId,
|
||||
string workflowComponent,
|
||||
CancellationToken cancellationToken = default)
|
||||
{
|
||||
ArgumentVerifier.ThrowIfNullOrEmpty(instanceId, nameof(instanceId));
|
||||
ArgumentVerifier.ThrowIfNullOrEmpty(workflowComponent, nameof(workflowComponent));
|
||||
|
||||
var request = new Autogenerated.PurgeWorkflowRequest()
|
||||
{
|
||||
InstanceId = instanceId,
|
||||
WorkflowComponent = workflowComponent
|
||||
};
|
||||
|
||||
var options = CreateCallOptions(headers: null, cancellationToken);
|
||||
|
||||
try
|
||||
{
|
||||
await client.PurgeWorkflowAlpha1Async(request, options);
|
||||
}
|
||||
catch (RpcException ex)
|
||||
{
|
||||
throw new DaprException("Purge workflow operation failed: the Dapr endpoint indicated a failure. See InnerException for details.", ex);
|
||||
}
|
||||
|
||||
}
|
||||
#endregion
|
||||
|
||||
|
||||
#region Dapr Sidecar Methods
|
||||
|
||||
/// <inheritdoc/>
|
||||
|
|
|
@ -1,100 +0,0 @@
|
|||
// ------------------------------------------------------------------------
|
||||
// Copyright 2021 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;
|
||||
using System.Collections.Generic;
|
||||
using System.Text.Json;
|
||||
|
||||
namespace Dapr.Client
|
||||
{
|
||||
/// <summary>
|
||||
/// The response type for the <see cref="DaprClient.GetWorkflowAsync"/> API.
|
||||
/// </summary>
|
||||
public class GetWorkflowResponse
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets the instance ID of the workflow.
|
||||
/// </summary>
|
||||
public string InstanceId { get; init; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the name of the workflow.
|
||||
/// </summary>
|
||||
public string WorkflowName { get; init; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the name of the workflow component.
|
||||
/// </summary>
|
||||
public string WorkflowComponentName { get; init; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the time at which the workflow was created.
|
||||
/// </summary>
|
||||
public DateTime CreatedAt { get; init; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the time at which the workflow was last updated.
|
||||
/// </summary>
|
||||
public DateTime LastUpdatedAt { get; init; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the runtime status of the workflow.
|
||||
/// </summary>
|
||||
public WorkflowRuntimeStatus RuntimeStatus { get; init; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the component-specific workflow properties.
|
||||
/// </summary>
|
||||
public IReadOnlyDictionary<string, string> Properties { get; init; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the details associated with the workflow failure, if any.
|
||||
/// </summary>
|
||||
public WorkflowFailureDetails FailureDetails { get; init; }
|
||||
|
||||
/// <summary>
|
||||
/// Deserializes the workflow input into <typeparamref name="T"/> using <see cref="JsonSerializer"/>.
|
||||
/// </summary>
|
||||
/// <typeparam name="T">The type to deserialize the workflow input into.</typeparam>
|
||||
/// <param name="options">Options to control the behavior during parsing.</param>
|
||||
/// <returns>Returns the input as <typeparamref name="T"/>, or returns a default value if the workflow doesn't have an input.</returns>
|
||||
public T ReadInputAs<T>(JsonSerializerOptions options = null)
|
||||
{
|
||||
// FUTURE: Make this part of the protobuf contract instead of properties
|
||||
string defaultInputKey = $"{this.WorkflowComponentName}.workflow.input";
|
||||
if (!this.Properties.TryGetValue(defaultInputKey, out string serializedInput))
|
||||
{
|
||||
return default;
|
||||
}
|
||||
|
||||
return JsonSerializer.Deserialize<T>(serializedInput, options);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Deserializes the workflow output into <typeparamref name="T"/> using <see cref="JsonSerializer"/>.
|
||||
/// </summary>
|
||||
/// <typeparam name="T">The type to deserialize the workflow output into.</typeparam>
|
||||
/// <param name="options">Options to control the behavior during parsing.</param>
|
||||
/// <returns>Returns the output as <typeparamref name="T"/>, or returns a default value if the workflow doesn't have an output.</returns>
|
||||
public T ReadOutputAs<T>(JsonSerializerOptions options = null)
|
||||
{
|
||||
// FUTURE: Make this part of the protobuf contract instead of properties
|
||||
string defaultOutputKey = $"{this.WorkflowComponentName}.workflow.output";
|
||||
if (!this.Properties.TryGetValue(defaultOutputKey, out string serializedOutput))
|
||||
{
|
||||
return default;
|
||||
}
|
||||
|
||||
return JsonSerializer.Deserialize<T>(serializedOutput, options);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,35 +0,0 @@
|
|||
// ------------------------------------------------------------------------
|
||||
// Copyright 2021 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.
|
||||
// ------------------------------------------------------------------------
|
||||
|
||||
namespace Dapr.Client
|
||||
{
|
||||
/// <summary>
|
||||
/// Represents workflow failure details.
|
||||
/// </summary>
|
||||
/// <param name="ErrorMessage">A summary description of the failure, which is typically an exception message.</param>
|
||||
/// <param name="ErrorType">The error type, which is defined by the workflow component implementation.</param>
|
||||
/// <param name="StackTrace">The stack trace of the failure.</param>
|
||||
public record WorkflowFailureDetails(
|
||||
string ErrorMessage,
|
||||
string ErrorType,
|
||||
string StackTrace = null)
|
||||
{
|
||||
/// <summary>
|
||||
/// Creates a user-friendly string representation of the failure information.
|
||||
/// </summary>
|
||||
public override string ToString()
|
||||
{
|
||||
return $"{this.ErrorType}: {this.ErrorMessage}";
|
||||
}
|
||||
}
|
||||
}
|
|
@ -11,7 +11,7 @@
|
|||
// limitations under the License.
|
||||
// ------------------------------------------------------------------------
|
||||
|
||||
namespace Dapr.Client
|
||||
namespace Dapr.Workflow
|
||||
{
|
||||
/// <summary>
|
||||
/// Enum describing the runtime status of a workflow.
|
|
@ -1,171 +0,0 @@
|
|||
// ------------------------------------------------------------------------
|
||||
// Copyright 2022 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;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using Dapr.Client;
|
||||
using FluentAssertions;
|
||||
using Xunit;
|
||||
|
||||
namespace Dapr.E2E.Test
|
||||
{
|
||||
[Obsolete]
|
||||
public partial class E2ETests
|
||||
{
|
||||
[Fact]
|
||||
public async Task TestWorkflowLogging()
|
||||
{
|
||||
// This test starts the daprclient and searches through the logfile to ensure the
|
||||
// workflow logger is correctly logging the registered workflow(s) and activity(s)
|
||||
|
||||
Dictionary<string, bool> logStrings = new Dictionary<string, bool>();
|
||||
logStrings["PlaceOrder"] = false;
|
||||
logStrings["ShipProduct"] = false;
|
||||
var logFilePath = "../../../../../test/Dapr.E2E.Test.App/log.txt";
|
||||
var allLogsFound = false;
|
||||
var timeout = 30; // 30s
|
||||
using var cts = new CancellationTokenSource(TimeSpan.FromSeconds(timeout));
|
||||
using var daprClient = new DaprClientBuilder().UseGrpcEndpoint(this.GrpcEndpoint).UseHttpEndpoint(this.HttpEndpoint).Build();
|
||||
var health = await daprClient.CheckHealthAsync();
|
||||
health.Should().Be(true, "DaprClient is not healthy");
|
||||
|
||||
var searchTask = Task.Run(async () =>
|
||||
{
|
||||
using (StreamReader reader = new StreamReader(logFilePath))
|
||||
{
|
||||
string line;
|
||||
while ((line = await reader.ReadLineAsync().WaitAsync(cts.Token)) != null)
|
||||
{
|
||||
foreach (var entry in logStrings)
|
||||
{
|
||||
if (line.Contains(entry.Key))
|
||||
{
|
||||
logStrings[entry.Key] = true;
|
||||
}
|
||||
}
|
||||
allLogsFound = logStrings.All(k => k.Value);
|
||||
if (allLogsFound)
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}, cts.Token);
|
||||
|
||||
try
|
||||
{
|
||||
await searchTask;
|
||||
}
|
||||
finally
|
||||
{
|
||||
File.Delete(logFilePath);
|
||||
}
|
||||
if (!allLogsFound)
|
||||
{
|
||||
Assert.Fail("The logs were not able to found within the timeout");
|
||||
}
|
||||
}
|
||||
[Fact]
|
||||
public async Task TestWorkflows()
|
||||
{
|
||||
var instanceId = "testInstanceId";
|
||||
var instanceId2 = "EventRaiseId";
|
||||
var workflowComponent = "dapr";
|
||||
var workflowName = "PlaceOrder";
|
||||
object input = "paperclips";
|
||||
Dictionary<string, string> workflowOptions = new Dictionary<string, string>();
|
||||
workflowOptions.Add("task_queue", "testQueue");
|
||||
|
||||
using var daprClient = new DaprClientBuilder().UseGrpcEndpoint(this.GrpcEndpoint).UseHttpEndpoint(this.HttpEndpoint).Build();
|
||||
var health = await daprClient.CheckHealthAsync();
|
||||
health.Should().Be(true, "DaprClient is not healthy");
|
||||
|
||||
// START WORKFLOW TEST
|
||||
var startResponse = await daprClient.StartWorkflowAsync(
|
||||
instanceId: instanceId,
|
||||
workflowComponent: workflowComponent,
|
||||
workflowName: workflowName,
|
||||
input: input,
|
||||
workflowOptions: workflowOptions);
|
||||
|
||||
startResponse.InstanceId.Should().Be("testInstanceId", $"Instance ID {startResponse.InstanceId} was not correct");
|
||||
|
||||
// GET INFO TEST
|
||||
var getResponse = await daprClient.GetWorkflowAsync(instanceId, workflowComponent);
|
||||
getResponse.InstanceId.Should().Be("testInstanceId");
|
||||
getResponse.RuntimeStatus.Should().Be(WorkflowRuntimeStatus.Running, $"Instance ID {getResponse.RuntimeStatus} was not correct");
|
||||
|
||||
// PAUSE TEST:
|
||||
await daprClient.PauseWorkflowAsync(instanceId, workflowComponent);
|
||||
getResponse = await daprClient.GetWorkflowAsync(instanceId, workflowComponent);
|
||||
getResponse.RuntimeStatus.Should().Be(WorkflowRuntimeStatus.Suspended, $"Instance ID {getResponse.RuntimeStatus} was not correct");
|
||||
|
||||
// RESUME TEST:
|
||||
await daprClient.ResumeWorkflowAsync(instanceId, workflowComponent);
|
||||
getResponse = await daprClient.GetWorkflowAsync(instanceId, workflowComponent);
|
||||
getResponse.RuntimeStatus.Should().Be(WorkflowRuntimeStatus.Running, $"Instance ID {getResponse.RuntimeStatus} was not correct");
|
||||
|
||||
// RAISE EVENT TEST
|
||||
await daprClient.RaiseWorkflowEventAsync(instanceId, workflowComponent, "ChangePurchaseItem", "computers");
|
||||
getResponse = await daprClient.GetWorkflowAsync(instanceId, workflowComponent);
|
||||
|
||||
// TERMINATE TEST:
|
||||
await daprClient.TerminateWorkflowAsync(instanceId, workflowComponent);
|
||||
getResponse = await daprClient.GetWorkflowAsync(instanceId, workflowComponent);
|
||||
getResponse.RuntimeStatus.Should().Be(WorkflowRuntimeStatus.Terminated, $"Instance ID {getResponse.RuntimeStatus} was not correct");
|
||||
|
||||
// PURGE TEST
|
||||
await daprClient.PurgeWorkflowAsync(instanceId, workflowComponent);
|
||||
|
||||
try
|
||||
{
|
||||
getResponse = await daprClient.GetWorkflowAsync(instanceId, workflowComponent);
|
||||
Assert.Fail("The GetWorkflowAsync call should have failed since the instance was purged");
|
||||
}
|
||||
catch (DaprException ex)
|
||||
{
|
||||
ex.InnerException.Message.Should().Contain("no such instance exists", $"Instance {instanceId} was not correctly purged");
|
||||
}
|
||||
|
||||
// Start another workflow for event raising purposes
|
||||
startResponse = await daprClient.StartWorkflowAsync(
|
||||
instanceId: instanceId2,
|
||||
workflowComponent: workflowComponent,
|
||||
workflowName: workflowName,
|
||||
input: input,
|
||||
workflowOptions: workflowOptions);
|
||||
|
||||
// PARALLEL RAISE EVENT TEST
|
||||
var event1 = daprClient.RaiseWorkflowEventAsync(instanceId2, workflowComponent, "ChangePurchaseItem", "computers");
|
||||
var event2 = daprClient.RaiseWorkflowEventAsync(instanceId2, workflowComponent, "ChangePurchaseItem", "computers");
|
||||
var event3 = daprClient.RaiseWorkflowEventAsync(instanceId2, workflowComponent, "ChangePurchaseItem", "computers");
|
||||
var event4 = daprClient.RaiseWorkflowEventAsync(instanceId2, workflowComponent, "ChangePurchaseItem", "computers");
|
||||
var event5 = daprClient.RaiseWorkflowEventAsync(instanceId2, workflowComponent, "ChangePurchaseItem", "computers");
|
||||
|
||||
var externalEvents = Task.WhenAll(event1, event2, event3, event4, event5);
|
||||
var winner = await Task.WhenAny(externalEvents, Task.Delay(TimeSpan.FromSeconds(30)));
|
||||
externalEvents.IsCompletedSuccessfully.Should().BeTrue($"Unsuccessful at raising events. Status of events: {externalEvents.IsCompletedSuccessfully}");
|
||||
|
||||
// Wait up to 30 seconds for the workflow to complete and check the output
|
||||
using var cts = new CancellationTokenSource(delay: TimeSpan.FromSeconds(30));
|
||||
getResponse = await daprClient.WaitForWorkflowCompletionAsync(instanceId2, workflowComponent, cts.Token);
|
||||
var outputString = getResponse.Properties["dapr.workflow.output"];
|
||||
outputString.Should().Be("\"computers\"", $"Purchased item {outputString} was not correct");
|
||||
var deserializedOutput = getResponse.ReadOutputAs<string>();
|
||||
deserializedOutput.Should().Be("computers", $"Deserialized output '{deserializedOutput}' was not expected");
|
||||
}
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue