mirror of https://github.com/dapr/dotnet-sdk.git
				
				
				
			
		
			
				
	
	
		
			199 lines
		
	
	
		
			7.3 KiB
		
	
	
	
		
			C#
		
	
	
	
			
		
		
	
	
			199 lines
		
	
	
		
			7.3 KiB
		
	
	
	
		
			C#
		
	
	
	
| // ------------------------------------------------------------------------
 | |
| // 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.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.
 | |
| // In this case the actor interfaces are DemoActor.Interfaces and IBankActor.
 | |
| // 
 | |
| // 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(ActorHost host, BankService bank) : Actor(host), IDemoActor.IDemoActor, IBankActor, IRemindable
 | |
| {
 | |
|     private const string StateName = "my_data";
 | |
| 
 | |
|     public async Task SaveData(MyData data, TimeSpan ttl)
 | |
|     {
 | |
|         Console.WriteLine($"This is Actor id {this.Id} with data {data}.");
 | |
| 
 | |
|         // Set State using StateManager, state is saved after the method execution.
 | |
|         await this.StateManager.SetStateAsync(StateName, data, ttl);
 | |
|     }
 | |
| 
 | |
|     public Task<MyData> GetData()
 | |
|     {
 | |
|         // Get state using StateManager.
 | |
|         return this.StateManager.GetStateAsync<MyData>(StateName);
 | |
|     }
 | |
| 
 | |
|     public Task TestThrowException()
 | |
|     {
 | |
|         throw new NotImplementedException();
 | |
|     }
 | |
| 
 | |
|     public Task TestNoArgumentNoReturnType()
 | |
|     {
 | |
|         return Task.CompletedTask;
 | |
|     }
 | |
| 
 | |
|     public async Task RegisterReminder()
 | |
|     {
 | |
|         await this.RegisterReminderAsync("TestReminder", null, TimeSpan.FromSeconds(5), TimeSpan.FromSeconds(5));
 | |
|     }
 | |
| 
 | |
|     public async Task RegisterReminderWithTtl(TimeSpan ttl)
 | |
|     {
 | |
|         await this.RegisterReminderAsync("TestReminder", null, TimeSpan.FromSeconds(5), TimeSpan.FromSeconds(5), ttl);
 | |
|     }
 | |
|         
 | |
|     public async Task RegisterReminderWithRepetitions(int repetitions)
 | |
|     {
 | |
|         await this.RegisterReminderAsync("TestReminder", null, TimeSpan.FromSeconds(0), TimeSpan.FromSeconds(1), repetitions);
 | |
|     }
 | |
|         
 | |
|     public async Task RegisterReminderWithTtlAndRepetitions(TimeSpan ttl, int repetitions)
 | |
|     {
 | |
|         await this.RegisterReminderAsync("TestReminder", null, TimeSpan.FromSeconds(0), TimeSpan.FromSeconds(1), repetitions, ttl);
 | |
|     }
 | |
| 
 | |
|     public async Task<ActorReminderData?> GetReminder()
 | |
|     {
 | |
|         var reminder = await this.GetReminderAsync("TestReminder");
 | |
| 
 | |
|         return reminder is not null
 | |
|             ? new ActorReminderData
 | |
|             {
 | |
|                 Name = reminder.Name,
 | |
|                 Period = reminder.Period,
 | |
|                 DueTime = reminder.DueTime
 | |
|             }
 | |
|             : null;
 | |
|     }
 | |
|         
 | |
|     public Task UnregisterReminder()
 | |
|     {
 | |
|         return this.UnregisterReminderAsync("TestReminder");
 | |
|     }
 | |
| 
 | |
|     public async Task ReceiveReminderAsync(string reminderName, byte[] state, TimeSpan dueTime, TimeSpan period)
 | |
|     {
 | |
|         // This method is invoked when an actor reminder is fired.
 | |
|         var actorState = await this.StateManager.GetStateAsync<MyData>(StateName);
 | |
|         var updatedActorState = actorState with
 | |
|         {
 | |
|             PropertyB = $"Reminder triggered at '{DateTime.Now:yyyy-MM-ddTHH:mm:ss}'"
 | |
|         };
 | |
|         await this.StateManager.SetStateAsync<MyData>(StateName, updatedActorState, ttl: TimeSpan.FromMinutes(5));
 | |
|     }
 | |
| 
 | |
|     class TimerParams
 | |
|     {
 | |
|         public int IntParam { get; set; }
 | |
|         public string? StringParam { get; set; }
 | |
|     }
 | |
| 
 | |
|     /// <inheritdoc/>
 | |
|     public Task RegisterTimer()
 | |
|     {
 | |
|         var timerParams = new TimerParams
 | |
|         {
 | |
|             IntParam = 100,
 | |
|             StringParam = "timer test",
 | |
|         };
 | |
| 
 | |
|         var serializedTimerParams = JsonSerializer.SerializeToUtf8Bytes(timerParams);
 | |
|         return this.RegisterTimerAsync("TestTimer", nameof(this.TimerCallback), serializedTimerParams, TimeSpan.FromSeconds(3), TimeSpan.FromSeconds(3));
 | |
|     }
 | |
| 
 | |
|     public Task RegisterTimerWithTtl(TimeSpan ttl)
 | |
|     {
 | |
|         var timerParams = new TimerParams
 | |
|         {
 | |
|             IntParam = 100,
 | |
|             StringParam = "timer test",
 | |
|         };
 | |
| 
 | |
|         var serializedTimerParams = JsonSerializer.SerializeToUtf8Bytes(timerParams);
 | |
|         return this.RegisterTimerAsync("TestTimer", nameof(this.TimerCallback), serializedTimerParams, TimeSpan.FromSeconds(3), TimeSpan.FromSeconds(3), ttl);
 | |
|     }
 | |
| 
 | |
|     public Task UnregisterTimer()
 | |
|     {
 | |
|         return this.UnregisterTimerAsync("TestTimer");
 | |
|     }
 | |
| 
 | |
|     // This method is called whenever an actor is activated.
 | |
|     // An actor is activated the first time any of its methods are invoked.
 | |
|     protected override Task OnActivateAsync()
 | |
|     {
 | |
|         // Provides opportunity to perform some optional setup.
 | |
|         return Task.CompletedTask;
 | |
|     }
 | |
| 
 | |
|     // This method is called whenever an actor is deactivated after a period of inactivity.
 | |
|     protected override Task OnDeactivateAsync()
 | |
|     {
 | |
|         // Provides Opportunity to perform optional cleanup.
 | |
|         return Task.CompletedTask;
 | |
|     }
 | |
| 
 | |
|     /// <summary>
 | |
|     /// This method is called when the timer is triggered based on its registration.
 | |
|     /// It updates the PropertyA value.
 | |
|     /// </summary>
 | |
|     /// <param name="data">Timer input data.</param>
 | |
|     /// <returns>A task that represents the asynchronous operation.</returns>
 | |
|     public async Task TimerCallback(byte[] data)
 | |
|     {
 | |
|         var state = await this.StateManager.GetStateAsync<MyData>(StateName);
 | |
|         var updatedState = state with { PropertyA = $"Timer triggered at '{DateTime.Now:yyyyy-MM-ddTHH:mm:s}'" };
 | |
|         await this.StateManager.SetStateAsync<MyData>(StateName, updatedState, ttl: TimeSpan.FromMinutes(5));
 | |
|         var timerParams = JsonSerializer.Deserialize<TimerParams>(data);
 | |
|         if (timerParams != null)
 | |
|         {
 | |
|             Console.WriteLine($"Timer parameter1: {timerParams.IntParam}");
 | |
|             Console.WriteLine($"Timer parameter2: {timerParams.StringParam ?? ""}");
 | |
|         }
 | |
|     }
 | |
| 
 | |
|     public async Task<AccountBalance> GetAccountBalance()
 | |
|     {
 | |
|         var starting = new AccountBalance(this.Id.GetId(), 100m); // Start new accounts with 100 million; we're pretty generous
 | |
| 
 | |
|         var balance = await this.StateManager.GetOrAddStateAsync<AccountBalance>("balance", starting);
 | |
|         return balance;
 | |
|     }
 | |
| 
 | |
|     public async Task Withdraw(WithdrawRequest withdraw)
 | |
|     {
 | |
|         var starting = new AccountBalance(this.Id.GetId(), 100m); // Start new accounts with 100 million; we're pretty generous.
 | |
| 
 | |
|         var balance = await this.StateManager.GetOrAddStateAsync<AccountBalance>("balance", starting);
 | |
| 
 | |
|         // Throws Overdraft exception if the account doesn't have enough money.
 | |
|         var updated = bank.Withdraw(balance.Balance, withdraw.Amount);
 | |
| 
 | |
|         balance = balance with { Balance = updated };
 | |
|         await this.StateManager.SetStateAsync("balance", balance);
 | |
|     }
 | |
| }
 |