问题
I am trying to get my head around persistence and I am yet to be able to recover an actor.
My intention is to get an Actor by its persistenceId (Same way we we get an Entity using GetById in DDD).
I can get the reference to List and add it to a variable in List Manager but what I am looking for is that once the Actor dies how to get the Actor with its current state (Revovery By Events) so that modification can be done.
Let me know if my question is not clear
This is what I have done so far: **Commands and Events **
using System;
namespace AkkaPersistence
{
public class CreateNewList
{
public string ListName { get; private set; }
public Guid UserId { get; private set; }
public string ListId { get; set; }
public CreateNewList(string listName, Guid userId, string listId)
{
ListName = listName;
UserId = userId;
ListId = listId;
}
}
public class RemoveList
{
public string ListId { get; private set; }
public Guid UserId { get; private set; }
public RemoveList(string listId, Guid userId)
{
ListId = listId;
UserId = userId;
}
}
public class ListCreated
{
public string ListName { get; private set; }
public Guid UserId { get; private set; }
public string ListId { get; private set; }
public ListCreated(string listName, Guid userId, string listId)
{
ListName = listName;
UserId = userId;
ListId = listId;
}
}
public class ListRemoved
{
public Guid UserId { get; private set; }
public string ListId { get; private set; }
public ListRemoved(Guid userId, string listId)
{
UserId = userId;
ListId = listId;
}
}
}
**List Class **
using System;
using Akka.Actor;
using Akka.Persistence;
namespace AkkaPersistence
{
public class List: ReceivePersistentActor
{
public override string PersistenceId => "AKKANETLIST";
private string Name { get; set; }
private Guid CreatedBy { get; set; }
private Guid ModifiedBy { get; set; }
public List()
{
Recover<ListCreated>(evnt =>
{
Console.WriteLine(" List :: Recovery Hit'");
Console.WriteLine("PID:{0}, Name {1}, CreatedBy:{2}, ModifiedBy{3}", PersistenceId, evnt.ListName, evnt.UserId, evnt.UserId);
Name = evnt.ListName;
CreatedBy = evnt.UserId;
ModifiedBy = evnt.UserId;
});
Command<CreateNewList>(cmd =>
{
Console.WriteLine(" List :: Received Command 'CreateNewList'");
var listCreated= new ListCreated(cmd.ListName,cmd.UserId, PersistenceId);
Persist(listCreated, lc =>
{
Console.WriteLine(" List::Event 'ListCreated' persisted");
Name = cmd.ListName;
CreatedBy = cmd.UserId;
ModifiedBy = cmd.UserId;
Sender.Tell(listCreated, ActorRefs.Nobody);
Console.WriteLine(" List::Event 'ListCreated' sent out");
});
});
Command<RemoveList>(cmd =>
{
Console.WriteLine(" List :: Received Command 'RemoveList'");
Console.WriteLine("PID:{0}, Name {1}, CreatedBy:{2}, ModifiedBy{3}",PersistenceId, Name, CreatedBy, ModifiedBy);
var listRemoved = new ListRemoved(cmd.UserId,PersistenceId);
Persist(listRemoved, lc =>
{
Console.WriteLine(" List::Event 'ListRemoved' persisted");
ModifiedBy = cmd.UserId;
Sender.Tell(listRemoved, ActorRefs.Nobody);
Console.WriteLine(" List::Event 'ListRemoved' sent out");
});
});
}
}
}
** List Manager **
using System;
using Akka.Actor;
namespace AkkaPersistence
{
public class ListManager : ReceiveActor
{
public ListManager()
{
Receive<CreateNewList>(cmd =>
{
Console.WriteLine(" List Manager:: Received Command 'CreateNewList'");
var newListRef = Context.ActorOf(Props.Create(typeof(List)));
newListRef.Tell(cmd, Self);
Console.WriteLine(" List Manager:: Command To Create New List sent to List Actor");
});
Receive<RemoveList>(cmd =>
{
Console.WriteLine(" List Manager:: Received Command 'RemoveList'");
var newListRef = Context.ActorOf(Props.Create(() => new List()), "AKKANETLIST");
newListRef.Tell(cmd, Self);
Console.WriteLine(" List Manager:: Command To 'Remove List' sent to List Actor");
});
Receive<ListCreated>(evnt =>
{
Console.WriteLine(" List Manager:: Event 'ListCreated' Received");
});
}
}
}
** Program.cs ** namespace AkkaPersistence { class Program { static void Main(string[] args) {
var system = ActorSystem.Create("MySystem");
var listManager = system.ActorOf<ListManager>("ListManager");
// create command
var newListId = Guid.NewGuid().ToString("N");
var createCommand= new CreateNewList("Akka List 1", Guid.NewGuid(), newListId);
listManager.Tell(createCommand);
//remove Command
var removeCommand = new RemoveList(newListId, createCommand.UserId);
listManager.Tell(removeCommand);
Console.ReadLine();
}
}
}
** Console Text **
[WARNING][1/21/2017 3:11:47 PM][Thread 0009][ActorSystem(MySystem)] NewtonSoftJsonSerializer has been detected as a default serializer. It will be obsoleted in Akka.NET starting from version 1.5 in the favor of Wire (for more info visit: http://getakka.net/docs/Serialization#how-to-setup-wire-as-default-serializer ). If you want to suppress this message set HOCON `akka.suppress-json-serializer-warning` config flag to on.
List Manager:: Received Command 'CreateNewList'
List Manager:: Command To Create New List sent to List Actor
List Manager:: Received Command 'RemoveList'
List Manager:: Command To 'Remove List' sent to List Actor
List :: Received Command 'CreateNewList'
List :: Received Command 'RemoveList'
PID:AKKANETLIST, Name , CreatedBy:00000000-0000-0000-0000-000000000000, ModifiedBy00000000-0000-0000-0000-000000000000
List::Event 'ListCreated' persisted
List::Event 'ListCreated' sent out
List Manager:: Event 'ListCreated' Received
List::Event 'ListRemoved' persisted
List::Event 'ListRemoved' sent out
** Update 1 **2017-01-24
further effort, I was able to get instance of an Actor based on Name. For this I need to create the PersistenceId as part of command and Name the Actor with the persistence Id
By doing this I could use Context.Child(Name) to get the Actor.
I am doing a Context.Stop(newListRef) in the ListManager:Receive assuming this will stop the List Actor and force it to Recover when I access using Context.Child(Name) but that does not happen, but somehow the List State is correct. Not sure how.
I will do some more test based on comment that I received today from Horusiath
回答1:
I may not quite understand your question, but when you need to recreate a persistent actor, you simply create another actor instance with the same PersistenceId
.
Only thing to keep in mind here is that you should never have more than one living instance of persistent actor with the same PersistenceId
at the time. Otherwise you may end with multiple actors trying to write events at the same time, possibly corrupting an event stream.
来源:https://stackoverflow.com/questions/41781012/akka-net-and-in-memory-peristence