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
When defining a side effect in PersistentFSM, the data object passed to the AndThen callback is NOT the version returned from ApplyEvent.
Consider this actor. When it receives a Command, it updates the state data (Data) by applying the CommandReceived event and uses the AndThen function to reply the current Data to the sender.
public class AndThenTestActor : PersistentFSM<AndThenTestActor.IState, AndThenTestActor.Data, AndThenTestActor.IEvent>
{
public override string PersistenceId => "PersistentFSMSpec.AndThenTestActor";
public AndThenTestActor()
{
StartWith(Init.Instance, new Data());
When(Init.Instance, (evt, state) =>
{
switch (evt.FsmEvent)
{
case Command cmd:
return Stay()
.Applying(new CommandReceived(cmd.Value))
.AndThen(data =>
{
// NOTE At this point, I'd expect data to be the value returned by ApplyEvent
Sender.Tell(data, Self);
});
default:
return Stay();
}
});
}
protected override Data ApplyEvent(IEvent domainEvent, Data currentData)
{
switch (domainEvent)
{
case CommandReceived cmd:
// Data is immutable; a new object with the applied event is returned
return new Data(cmd.Value);
default:
return currentData;
}
}
public interface IState : PersistentFSM.IFsmState
{
}
public class Init : IState
{
public static readonly Init Instance = new Init();
public string Identifier => "Init";
}
public class Data
{
public Data()
{
}
public Data(string value)
{
Value = value;
}
public string Value { get; }
}
public interface IEvent
{
}
public class CommandReceived : IEvent
{
public CommandReceived(string value)
{
Value = value;
}
public string Value { get; }
}
public class Command
{
public Command(string value)
{
Value = value;
}
public string Value { get; }
}
}
Let's say I ask the actor like so, I'd expect the returned data to reflect the latest changes.
var response = await actor.Ask<AndThenTestActor.Data>(new AndThenTestActor.Command("test"));
Assert.Equal("test", response.Value);
However, it does not! Instead I get the Data object that was the state data before applying the event.
nextState.Using(nextData) creates a copy of the state with the new data applied, however, the nextState used to access StateData in nextState.AfterTransitionDo?.Invoke(nextState.StateData); is the old state, before the copy.
I've created fix + tests in a separate pull request.
The text was updated successfully, but these errors were encountered:
Akka version: 1.3.10
Platform : .NET Core 2.1/Windows
When defining a side effect in PersistentFSM, the data object passed to the AndThen callback is NOT the version returned from ApplyEvent.
Consider this actor. When it receives a
Command
, it updates the state data (Data
) by applying theCommandReceived
event and uses the AndThen function to reply the currentData
to the sender.Let's say I ask the actor like so, I'd expect the returned data to reflect the latest changes.
However, it does not! Instead I get the
Data
object that was the state data before applying the event.The reason can be found here:
akka.net/src/core/Akka.Persistence/Fsm/PersistentFSM.cs
Lines 134 to 136 in d9f6c57
nextState.Using(nextData)
creates a copy of the state with the new data applied, however, the nextState used to access StateData innextState.AfterTransitionDo?.Invoke(nextState.StateData);
is the old state, before the copy.I've created fix + tests in a separate pull request.
The text was updated successfully, but these errors were encountered: