dapr / dapr/dotnet-sdk

Stale Actor State in Reminder callback with Actor Reentrancy Enabled

Open
#1,615 0 comments 0 reactions 0 assignees View on GitHub
area/actor/client kind/bug
Dominant language
C#
Stars
1.2k
Forks
378
Avg merge
2d 1h
Merged PRs (30d)
6

Description

## Expected Behavior

The ReceiveReminderAsync method should access the most current, up-to-date state of the actor, regardless of whether a separate, call had updated the state.

## Actual Behavior

When using a Dapr Actor with reentrancy enabled, the actor's state is stale when accessed within a reminder callback. The actor's state is being updated by an external method call, but the reminder's ReceiveReminderAsync method receives only the initial state.

## Steps to Reproduce the Problem

Environments:

```
runtime V1.15.10
dotnet-sdk: v1.15.4
```
and
```
runtime V1.16.0-rc.4
dotnet-sdk: v1.16.0-rc15
```

Enable reentrancy
```
options.ReentrancyConfig = new ActorReentrancyConfig { Enabled = true, MaxStackDepth = 32 };
```

After the reminder has started, the ReceiveReminderAsync method will not pick up new state! (STALESTATE is different from ACTUALSTATE after the reminder callback)
```
async Task IDeviceActor.SetStateAsync(int actualState)
{
await StateManager.SetStateAsync(ACTUALSTATE, actualState);
await StateManager.SaveStateAsync();
Logger.LogInformation($"Actor id {Id}: State set to {actualState}");
}

async Task<(int, int)> IDeviceActor.GetStateAsync()
{
var deviceState = await StateManager.GetStateAsync(ACTUALSTATE);
var staleState = await StateManager.TryGetStateAsync(STALESTATE);
Logger.LogInformation($"Actor id {Id}: Actual state: {deviceState} - Stale (reminder) state: {staleState.Value} ");
return (deviceState, staleState.Value);
}

async Task IRemindable.ReceiveReminderAsync(string reminderName, byte[] state, TimeSpan dueTime, TimeSpan period)
{
if (reminderName == REMINDER)
{
var reminderState = await StateManager.GetStateAsync(ACTUALSTATE);
Logger.LogInformation($"Actor id {Id}: Reminder gets state {reminderState}.");

await StateManager.SetStateAsync(STALESTATE, reminderState);
await StateManager.SaveStateAsync();
}
}
```

## Release Note

RELEASE NOTE:

Contributor guide

Open the contributing guide

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.