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
The table of contents is too big for display.
Diff view
Diff view
  •  
  •  
  •  
7 changes: 5 additions & 2 deletions all.sln
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ControllerSample", "example
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Actor", "Actor", "{02374BD0-BF0B-40F8-A04A-C4C4D61D4992}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "IDemoActor", "examples\Actor\IDemoActor\IDemoActor.csproj", "{7957E852-1291-4FAA-9034-FB66CE817FF1}"
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "DemoActor.Interfaces", "examples\Actor\DemoActor.Interfaces\DemoActor.Interfaces.csproj", "{7957E852-1291-4FAA-9034-FB66CE817FF1}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "DemoActor", "examples\Actor\DemoActor\DemoActor.csproj", "{626D74DD-4F37-4F74-87A3-5A6888684F5E}"
EndProject
Expand Down Expand Up @@ -155,6 +155,8 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "JobsSample", "examples\Jobs
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Dapr.Workflow.Test", "test\Dapr.Workflow.Test\Dapr.Workflow.Test.csproj", "{E90114C6-86FC-43B8-AE5C-D9273CF21FE4}"
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Messaging", "Messaging", "{8DB002D2-19E9-4342-A86B-025A367DF3D1}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
Expand Down Expand Up @@ -471,12 +473,13 @@ Global
{00359961-0C50-4BB1-A794-8B06DE991639} = {BF3ED6BF-ADF3-4D25-8E89-02FB8D945CA9}
{4E04EB35-7FD2-4FDB-B09A-F75CE24053B9} = {DD020B34-460F-455F-8D17-CF4A949F100B}
{0EAE36A1-B578-4F13-A113-7A477ECA1BDA} = {27C5D71D-0721-4221-9286-B94AB07B58CF}
{290D1278-F613-4DF3-9DF5-F37E38CDC363} = {0EF6EA64-D7C3-420D-9890-EAE8D54A57E6}
{C8BB6A85-A7EA-40C0-893D-F36F317829B3} = {27C5D71D-0721-4221-9286-B94AB07B58CF}
{BF9828E9-5597-4D42-AA6E-6E6C12214204} = {DD020B34-460F-455F-8D17-CF4A949F100B}
{D9697361-232F-465D-A136-4561E0E88488} = {D687DDC4-66C5-4667-9E3A-FD8B78ECAA78}
{9CAF360E-5AD3-4C4F-89A0-327EEB70D673} = {D9697361-232F-465D-A136-4561E0E88488}
{E90114C6-86FC-43B8-AE5C-D9273CF21FE4} = {DD020B34-460F-455F-8D17-CF4A949F100B}
{8DB002D2-19E9-4342-A86B-025A367DF3D1} = {D687DDC4-66C5-4667-9E3A-FD8B78ECAA78}
{290D1278-F613-4DF3-9DF5-F37E38CDC363} = {8DB002D2-19E9-4342-A86B-025A367DF3D1}
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {65220BF2-EAE1-4CB2-AA58-EBE80768CB40}
Expand Down
2 changes: 1 addition & 1 deletion examples/Actor/ActorClient/ActorClient.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@

<ItemGroup>
<ProjectReference Include="..\..\..\src\Dapr.Actors\Dapr.Actors.csproj" />
<ProjectReference Include="..\IDemoActor\IDemoActor.csproj" />
<ProjectReference Include="..\DemoActor.Interfaces\DemoActor.Interfaces.csproj" />
</ItemGroup>

</Project>
249 changes: 113 additions & 136 deletions examples/Actor/ActorClient/Program.cs
Original file line number Diff line number Diff line change
Expand Up @@ -11,146 +11,123 @@
// limitations under the License.
// ------------------------------------------------------------------------

using Dapr.Actors.Communication;
using System;
using System.Threading;
using System.Threading.Tasks;
using Dapr.Actors;
using Dapr.Actors.Client;
using IDemoActor;

namespace ActorClient
var data = new MyData("ValueA", "ValueB");

// Create an actor Id.
var actorId = new ActorId("abc");

// Make strongly typed Actor calls with Remoting.
// DemoActor is the type registered with Dapr runtime in the service.
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));
Console.WriteLine("Making call using actor proxy to get data.");
var receivedData = await proxy.GetData();
Console.WriteLine($"Received data is {receivedData}.");

// Making some more calls to test methods.
try
{
Console.WriteLine("Making calls to an actor method which has no argument and no return type.");
await proxy.TestNoArgumentNoReturnType();
}
catch (Exception ex)
{
Console.WriteLine($"ERROR: Got exception while making call to method with No Argument & No Return Type. Exception: {ex}");
}

try
{
await proxy.TestThrowException();
}
catch (ActorMethodInvocationException ex)
{
using System;
using System.Threading;
using System.Threading.Tasks;
using Dapr.Actors;
using Dapr.Actors.Client;

/// <summary>
/// Actor Client class.
/// </summary>
public class Program
if (ex.InnerException is ActorInvokeException invokeEx && invokeEx.ActualExceptionType is "System.NotImplementedException")
{
/// <summary>
/// Entry point.
/// </summary>
/// <param name="args">Arguments.</param>
/// <returns>A <see cref="Task"/> representing the asynchronous operation.</returns>
public static async Task Main(string[] args)
{
var data = new MyData()
{
PropertyA = "ValueA",
PropertyB = "ValueB",
};

// Create an actor Id.
var actorId = new ActorId("abc");

// Make strongly typed Actor calls with Remoting.
// DemoActor is the type registered with Dapr runtime in the service.
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));
Console.WriteLine("Making call using actor proxy to get data.");
var receivedData = await proxy.GetData();
Console.WriteLine($"Received data is {receivedData}.");

// Making some more calls to test methods.
try
{
Console.WriteLine("Making calls to an actor method which has no argument and no return type.");
await proxy.TestNoArgumentNoReturnType();
}
catch (Exception ex)
{
Console.WriteLine($"ERROR: Got exception while making call to method with No Argument & No Return Type. Exception: {ex}");
}

try
{
await proxy.TestThrowException();
}
catch (ActorMethodInvocationException ex)
{
if (ex.InnerException is ActorInvokeException invokeEx && invokeEx.ActualExceptionType is "System.NotImplementedException")
{
Console.WriteLine($"Got Correct Exception from actor method invocation.");
}
else
{
Console.WriteLine($"Got Incorrect Exception from actor method invocation. Exception {ex.InnerException}");
}
}

// Making calls without Remoting, this shows method invocation using InvokeMethodAsync methods, the method name and its payload is provided as arguments to InvokeMethodAsync methods.
Console.WriteLine("Making calls without Remoting.");
var nonRemotingProxy = ActorProxy.Create(actorId, "DemoActor");
await nonRemotingProxy.InvokeMethodAsync("TestNoArgumentNoReturnType");
await nonRemotingProxy.InvokeMethodAsync("SaveData", data);
await nonRemotingProxy.InvokeMethodAsync<MyData>("GetData");

Console.WriteLine("Registering the timer and reminder");
await proxy.RegisterTimer();
await proxy.RegisterReminder();
Console.WriteLine("Waiting so the timer and reminder can be triggered");
await Task.Delay(6000);

Console.WriteLine("Making call using actor proxy to get data after timer and reminder triggered");
receivedData = await proxy.GetData();
Console.WriteLine($"Received data is {receivedData}.");

Console.WriteLine("Getting details of the registered reminder");
var reminder = await proxy.GetReminder();
Console.WriteLine($"Received reminder is {reminder}.");

Console.WriteLine("Deregistering timer. Timers would any way stop if the actor is deactivated as part of Dapr garbage collection.");
await proxy.UnregisterTimer();
Console.WriteLine("Deregistering reminder. Reminders are durable and would not stop until an explicit deregistration or the actor is deleted.");
await proxy.UnregisterReminder();
Console.WriteLine($"Got Correct Exception from actor method invocation.");
}
else
{
Console.WriteLine($"Got Incorrect Exception from actor method invocation. Exception {ex.InnerException}");
}
}

// Making calls without Remoting, this shows method invocation using InvokeMethodAsync methods, the method name and its payload is provided as arguments to InvokeMethodAsync methods.
Console.WriteLine("Making calls without Remoting.");
var nonRemotingProxy = ActorProxy.Create(actorId, "DemoActor");
await nonRemotingProxy.InvokeMethodAsync("TestNoArgumentNoReturnType");
await nonRemotingProxy.InvokeMethodAsync("SaveData", data);
await nonRemotingProxy.InvokeMethodAsync<MyData>("GetData");

Console.WriteLine("Registering the timer and reminder");
await proxy.RegisterTimer();
await proxy.RegisterReminder();
Console.WriteLine("Waiting so the timer and reminder can be triggered");
await Task.Delay(6000);

Console.WriteLine("Making call using actor proxy to get data after timer and reminder triggered");
receivedData = await proxy.GetData();
Console.WriteLine($"Received data is {receivedData}.");

Console.WriteLine("Getting details of the registered reminder");
var reminder = await proxy.GetReminder();
Console.WriteLine($"Received reminder is {reminder}.");

Console.WriteLine("Deregistering timer. Timers would any way stop if the actor is deactivated as part of Dapr garbage collection.");
await proxy.UnregisterTimer();
Console.WriteLine("Deregistering reminder. Reminders are durable and would not stop until an explicit deregistration or the actor is deleted.");
await proxy.UnregisterReminder();

Console.WriteLine("Registering reminder with repetitions - The reminder will repeat 3 times.");
await proxy.RegisterReminderWithRepetitions(3);
Console.WriteLine("Waiting so the reminder can be triggered");
await Task.Delay(5000);
Console.WriteLine("Getting details of the registered reminder");
reminder = await proxy.GetReminder();
Console.WriteLine($"Received reminder is {reminder?.ToString() ?? "None"} (expecting None).");
Console.WriteLine("Registering reminder with ttl and repetitions, i.e. reminder stops when either condition is met - The reminder will repeat 2 times.");
await proxy.RegisterReminderWithTtlAndRepetitions(TimeSpan.FromSeconds(5), 2);
Console.WriteLine("Getting details of the registered reminder");
reminder = await proxy.GetReminder();
Console.WriteLine($"Received reminder is {reminder}.");
Console.WriteLine("Deregistering reminder. Reminders are durable and would not stop until an explicit deregistration or the actor is deleted.");
await proxy.UnregisterReminder();

Console.WriteLine("Registering reminder and Timer with TTL - The reminder will self delete after 10 seconds.");
await proxy.RegisterReminderWithTtl(TimeSpan.FromSeconds(10));
await proxy.RegisterTimerWithTtl(TimeSpan.FromSeconds(10));
Console.WriteLine("Getting details of the registered reminder");
reminder = await proxy.GetReminder();
Console.WriteLine($"Received reminder is {reminder}.");

// Track the reminder.
var timer = new Timer(async state => Console.WriteLine($"Received data: {await proxy.GetData()}"), null, TimeSpan.FromSeconds(5), TimeSpan.FromSeconds(5));
await Task.Delay(TimeSpan.FromSeconds(21));
await timer.DisposeAsync();

Console.WriteLine("Creating a Bank Actor");
var bank = ActorProxy.Create<IBankActor>(ActorId.CreateRandom(), "DemoActor");
while (true)
{
var balance = await bank.GetAccountBalance();
Console.WriteLine($"Balance for account '{balance.AccountId}' is '{balance.Balance:c}'.");

Console.WriteLine($"Withdrawing '{10m:c}'...");
try
{
await bank.Withdraw(new WithdrawRequest() { Amount = 10m, });
}
catch (ActorMethodInvocationException ex)
{
Console.WriteLine("Overdraft: " + ex.Message);
break;
}
}
}
Console.WriteLine("Registering reminder with repetitions - The reminder will repeat 3 times.");
await proxy.RegisterReminderWithRepetitions(3);
Console.WriteLine("Waiting so the reminder can be triggered");
await Task.Delay(5000);
Console.WriteLine("Getting details of the registered reminder");
reminder = await proxy.GetReminder();
Console.WriteLine($"Received reminder is {reminder?.ToString() ?? "None"} (expecting None).");
Console.WriteLine("Registering reminder with ttl and repetitions, i.e. reminder stops when either condition is met - The reminder will repeat 2 times.");
await proxy.RegisterReminderWithTtlAndRepetitions(TimeSpan.FromSeconds(5), 2);
Console.WriteLine("Getting details of the registered reminder");
reminder = await proxy.GetReminder();
Console.WriteLine($"Received reminder is {reminder}.");
Console.WriteLine("Deregistering reminder. Reminders are durable and would not stop until an explicit deregistration or the actor is deleted.");
await proxy.UnregisterReminder();

Console.WriteLine("Registering reminder and Timer with TTL - The reminder will self delete after 10 seconds.");
await proxy.RegisterReminderWithTtl(TimeSpan.FromSeconds(10));
await proxy.RegisterTimerWithTtl(TimeSpan.FromSeconds(10));
Console.WriteLine("Getting details of the registered reminder");
reminder = await proxy.GetReminder();
Console.WriteLine($"Received reminder is {reminder}.");

// Track the reminder.
var timer = new Timer(async state => Console.WriteLine($"Received data: {await proxy.GetData()}"), null, TimeSpan.FromSeconds(5), TimeSpan.FromSeconds(5));
await Task.Delay(TimeSpan.FromSeconds(21));
await timer.DisposeAsync();

Console.WriteLine("Creating a Bank Actor");
var bank = ActorProxy.Create<IBankActor>(ActorId.CreateRandom(), "DemoActor");
while (true)
{
var balance = await bank.GetAccountBalance();
Console.WriteLine($"Balance for account '{balance.AccountId}' is '{balance.Balance:c}'.");

Console.WriteLine($"Withdrawing '{10m:c}'...");
try
{
await bank.Withdraw(new WithdrawRequest(10m));
}
catch (ActorMethodInvocationException ex)
{
Console.WriteLine($"Overdraft: {ex.Message}");
break;
}
}
Original file line number Diff line number Diff line change
@@ -1,5 +1,10 @@
<Project Sdk="Microsoft.NET.Sdk">

<PropertyGroup>
<RootNamespace>IDemoActor</RootNamespace>
<Nullable>enable</Nullable>
</PropertyGroup>

<ItemGroup>
<ProjectReference Include="..\..\..\src\Dapr.Actors\Dapr.Actors.csproj" />
</ItemGroup>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,32 +15,18 @@
using System.Threading.Tasks;
using Dapr.Actors;

namespace IDemoActor
{
public interface IBankActor : IActor
{
Task<AccountBalance> GetAccountBalance();
namespace IDemoActor;

Task Withdraw(WithdrawRequest withdraw);
}
public interface IBankActor : IActor
{
Task<AccountBalance> GetAccountBalance();

public class AccountBalance
{
public string AccountId { get; set; }
Task Withdraw(WithdrawRequest withdraw);
}

public decimal Balance { get; set; }
}
public sealed record AccountBalance(string AccountId, decimal Balance);

public class WithdrawRequest
{
public decimal Amount { get; set; }
}
public sealed record WithdrawRequest(decimal Amount);

public class OverdraftException : Exception
{
public OverdraftException(decimal balance, decimal amount)
: base($"Your current balance is {balance:c} - that's not enough to withdraw {amount:c}.")
{
}
}
}
public class OverdraftException(decimal balance, decimal amount)
: Exception($"Your current balance is {balance:c} - that's not enough to withdraw {amount:c}.");
Loading