You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Copy file name to clipboardExpand all lines: docs/architecture/dapr-for-net-developers/actors.md
+19-19Lines changed: 19 additions & 19 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -2,7 +2,7 @@
2
2
title: The Dapr actors building block
3
3
description: A deep dive into the Dapr actors building block and how to apply it
4
4
author: amolenk
5
-
ms.date: 05/30/2021
5
+
ms.date: 06/22/2021
6
6
---
7
7
8
8
# The Dapr actors building block
@@ -96,7 +96,7 @@ public int Increment()
96
96
{
97
97
intnewValue;
98
98
99
-
lock (this.lockObject)
99
+
lock (_lockObject)
100
100
{
101
101
varcurrentValue=GetValue();
102
102
newValue=currentValue+1;
@@ -236,15 +236,15 @@ Let's now implement the `IncrementScoreAsync` method of the interface:
236
236
```csharp
237
237
public Task<int> IncrementScoreAsync()
238
238
{
239
-
return this.StateManager.AddOrUpdateStateAsync(
239
+
return StateManager.AddOrUpdateStateAsync(
240
240
"score",
241
241
1,
242
242
(key, currentScore) => currentScore + 1
243
243
);
244
244
}
245
245
```
246
246
247
-
In the snippet above, a single call to `StateManager.AddOrUpdateStateAsync` provides the full implementation for the `IncrementAsync` method. The `AddOrUpdateStateAsync` method takes three arguments:
247
+
In the snippet above, a single call to `StateManager.AddOrUpdateStateAsync` provides the full implementation for the `IncrementScoreAsync` method. The `AddOrUpdateStateAsync` method takes three arguments:
248
248
249
249
1. The key of the state to update.
250
250
1. The value to write if no score is stored in the state store yet.
@@ -255,7 +255,7 @@ The `GetScoreAsync` implementation reads the current score from the state store
255
255
```csharp
256
256
public async Task<int> GetScoreAsync()
257
257
{
258
-
var scoreValue = await this.StateManager.TryGetStateAsync<int>("score");
258
+
var scoreValue = await StateManager.TryGetStateAsync<int>("score");
259
259
if (scoreValue.HasValue)
260
260
{
261
261
return scoreValue.Value;
@@ -288,7 +288,7 @@ public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
288
288
The actors endpoints are necessary because the Dapr sidecar calls the application to host and interact with actor instances.
289
289
290
290
> [!IMPORTANT]
291
-
> By default, a generated `Startup` class contains an `app.UseHttpsRedirection` call to redirect client to the HTTPS endpoint. This will not work with actors and must be removed. By design, a Dapr sidecar send requests over unencrypted HTTP by default. The HTTPS middleware will block these requests when enabled.
291
+
> By default, a generated `Startup` class contains an `app.UseHttpsRedirection` call to redirect client to the HTTPS endpoint. This will not work with actors and must be removed. By design, a Dapr sidecar sends requests over unencrypted HTTP by default. The HTTPS middleware will block these requests when enabled.
292
292
293
293
The `Startup` class is also the place to register the specific actor types. In the example below, `ConfigureServices` registers the `ScoreActor` using `services.AddActors`:
294
294
@@ -307,7 +307,7 @@ public void ConfigureServices(IServiceCollection services)
307
307
At this point, the ASP.NET Core service is ready to host the `ScoreActor` and accept incoming requests. Client applications use actor proxies to invoke operations on actors. The following example shows how a console client application invokes the `IncrementScoreAsync` operation on a `ScoreActor` instance:
The above example uses the `Dapr.Actors` package to call the actor service. To invoke an operation on an actor, you need to be able to address it. You'll need two parts for this:
322
+
The above example uses the [`Dapr.Actors`](https://www.nuget.org/packages/Dapr.Actors) package to call the actor service. To invoke an operation on an actor, you need to be able to address it. You'll need two parts for this:
323
323
324
324
1. The **actor type** uniquely identifies the actor implementation across the whole application. By default, the actor type is the name of the implementation class (without namespace). You can customize the actor type by adding an `ActorAttribute` to the implementation class and setting its `TypeName` property.
325
325
1. The `ActorId` uniquely identifies an instance of an actor type. You can also use this class to generate a random actor id by calling `ActorId.CreateRandom`.
@@ -366,7 +366,7 @@ public class ScoreController : ControllerBase
366
366
}
367
367
368
368
[HttpPut("{scoreId}")]
369
-
public Task<int> Increment(string scoreId)
369
+
public Task<int> IncrementAsync(string scoreId)
370
370
{
371
371
var scoreActor = _actorProxyFactory.CreateActorProxy<IScoreActor>(
372
372
new ActorId(scoreId),
@@ -414,7 +414,7 @@ You create weakly-typed proxies in a similar way to strongly-typed proxies. Inst
414
414
415
415
```csharp
416
416
[HttpPut("{scoreId}")]
417
-
public Task<int> Increment(string scoreId)
417
+
public Task<int> IncrementAsync(string scoreId)
418
418
{
419
419
var scoreActor = _actorProxyFactory.CreateActorProxy(
420
420
new ActorId(scoreId),
@@ -445,11 +445,11 @@ public class TimerActor : Actor, ITimerActor
@@ -464,7 +464,7 @@ The `StartTimerAsync` method calls `RegisterTimerAsync` to schedule the timer. `
464
464
1. The amount of time to wait before the callback method is first invoked.
465
465
1. The time interval between callback method invocations. You can specify `TimeSpan.FromMilliseconds(-1)` to disable periodic signaling.
466
466
467
-
The `TimerCallback` method receives the user state in binary form. In the example, the callback decodes the state back to a `string` before writing it to the log.
467
+
The `TimerCallbackAsync` method receives the user state in binary form. In the example, the callback decodes the state back to a `string` before writing it to the log.
468
468
469
469
Timers can be stopped by calling `UnregisterTimerAsync`:
470
470
@@ -526,7 +526,7 @@ public class ReminderActor : Actor, IReminderActor, IRemindable
@@ -556,7 +556,7 @@ public interface IVehicleActor : IActor
556
556
}
557
557
```
558
558
559
-
The (simulated) entry cameras call the `RegisterEntry` method when a new vehicle is first detected in the lane. The only responsibility of this method is storing the entry timestamp in the actor state:
559
+
The (simulated) entry cameras call the `RegisterEntryAsync` method when a new vehicle is first detected in the lane. The only responsibility of this method is storing the entry timestamp in the actor state:
560
560
561
561
```csharp
562
562
var vehicleState = new VehicleState
@@ -567,17 +567,17 @@ var vehicleState = new VehicleState
When the vehicle reaches the end of the speed camera zone, the exit camera calls the `RegisterExit` method. The `RegisterExit` method first gets the current states and updates it to include the exit timestamp:
570
+
When the vehicle reaches the end of the speed camera zone, the exit camera calls the `RegisterExitAsync` method. The `RegisterExitAsync` method first gets the current states and updates it to include the exit timestamp:
571
571
572
572
```csharp
573
573
var vehicleState = await StateManager.GetStateAsync<VehicleState>("VehicleState");
574
574
vehicleState.ExitTimestamp = msg.Timestamp;
575
575
```
576
576
577
577
> [!NOTE]
578
-
> The code above currently assumes that a `VehicleState` instance has already been saved by the `RegisterEntry` method. The code could be improved by first checking to make sure the state exists. Thanks to the turn-based access model, no explicit locks are required in the code.
578
+
> The code above currently assumes that a `VehicleState` instance has already been saved by the `RegisterEntryAsync` method. The code could be improved by first checking to make sure the state exists. Thanks to the turn-based access model, no explicit locks are required in the code.
579
579
580
-
After the state is updated, the `RegisterExit` method checks if the vehicle was driving too fast. If it was, the actor publishes a message to the `collectfine` pub/sub topic:
580
+
After the state is updated, the `RegisterExitAsync` method checks if the vehicle was driving too fast. If it was, the actor publishes a message to the `collectfine` pub/sub topic:
581
581
582
582
```csharp
583
583
int violation = _speedingViolationCalculator.DetermineSpeedingViolationInKmh(
@@ -621,7 +621,7 @@ The actor based implementation no longer uses the Dapr state management building
621
621
622
622
## Summary
623
623
624
-
The Dapr actors building block makes it easier to write correct concurrent systems. Actors are small units of state and logic. They use a turn-based access model which saves you from having to write error-prone thread-safe code. Actors are created implicitly and are silently unloaded from memory when no operations are performed. Any state stored in the actor is automatically persisted and loaded when the actor is reactivated. Actor model implementations are typically created for a specific language or platform. With the Dapr actors building block however, you can leverage the actor model from any language or platform.
624
+
The Dapr actors building block makes it easier to write correct concurrent systems. Actors are small units of state and logic. They use a turn-based access model which saves you from having to use locking mechanisms to write thread-safe code. Actors are created implicitly and are silently unloaded from memory when no operations are performed. Any state stored in the actor is automatically persisted and loaded when the actor is reactivated. Actor model implementations are typically created for a specific language or platform. With the Dapr actors building block however, you can leverage the actor model from any language or platform.
625
625
626
626
Actors support timers and reminders to schedule future work. Timers do not reset the idle timer and will allow the actor to be deactivated when no other operations are performed. Reminders do reset the idle timer and are also persisted automatically. Both timers and reminders respect the turn-based access model, making sure that no other operations can execute while the timer/reminder events are handled.
0 commit comments