-
Notifications
You must be signed in to change notification settings - Fork 1k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
remote IActorRef deserialization issue for non-existent actors #3204
Comments
Yes .. I'm experiencing this issue while recovering a persistent actor as well
|
Some background about my system: |
The issue happens like this.
If the persistence is not using ... There are more similar scenarios caused by the same issue with IActorRef serialization dropping transport information. I see there two ways how to fix this issue
|
I think, we should revisit how |
I've checked where
This means, that we're missing a lot of cases - bad part in that is that I recall that we have some of those in the past, but I cannot remember why we didn't implemented them. I can fix them, but I actually need help to in building test cases to verify it the issue was resolved - @zbynek001 could you help me prepare test cases? |
@zbynek001 How should one use Serialization.SerializeWithTransport on the plugin side to solve this issue? If I do something like: private byte[] PersistentToBytes(IPersistentRepresentation message)
{
var serializer = Context.System.Serialization.FindSerializerForType(typeof(IPersistentRepresentation));
return Serialization.SerializeWithTransport(Context.System, message.Sender.Path.Address, () => serializer.ToBinary(message));
} on the plugin side, this will not correctly serialize any IActorRef properties in message.Payload because Akka.Serialization.Serialization.SerializedActorPath is only used to serialize IPersistentRepresentation.Sender in Akka.Persistence.Serialization.PersistenceMessageSerializer(v1.3.8): private PersistentMessage GetPersistentMessage(IPersistentRepresentation persistent)
{
PersistentMessage message = new PersistentMessage();
if (persistent.PersistenceId != null) message.PersistenceId = persistent.PersistenceId;
if (persistent.Manifest != null) message.Manifest = persistent.Manifest;
if (persistent.WriterGuid != null) message.WriterGuid = persistent.WriterGuid;
if (persistent.Sender != null) message.Sender = Akka.Serialization.Serialization.SerializedActorPath(persistent.Sender);
message.Payload = GetPersistentPayload(persistent.Payload);
message.SequenceNr = persistent.SequenceNr;
message.Deleted = persistent.IsDeleted;
return message;
}
private PersistentPayload GetPersistentPayload(object obj)
{
Serializer serializer = system.Serialization.FindSerializerFor(obj);
var payload = new PersistentPayload();
if (serializer is SerializerWithStringManifest serializer2)
{
string manifest = serializer2.Manifest(obj);
payload.PayloadManifest = ByteString.CopyFromUtf8(manifest);
}
else
{
if (serializer.IncludeManifest)
{
payload.PayloadManifest = ByteString.CopyFromUtf8(obj.GetType().TypeQualifiedName());
}
}
payload.Payload = ByteString.CopyFrom(serializer.ToBinary(obj));
payload.SerializerId = serializer.Identifier;
return payload;
} Since the region property is part of the payload, I don't understand how this is supposed to work. Please clarify if I misunderstood your point. |
Erik (ef-computas) and I solved this by adding the external address for the local node to the SerializeWithTransport method (in our journal and snapshotstore persistence implementation). The address parameter will only be used if the ActorPath's Address does not have Host and Port value, meaning the ActorPath is local (ref method ToStringWithAddress in ActorPath). We retrieved the protocol (akka.tcp), hostname and port from the config).
Before this change we observed that actor refs was serialized incorrectly (missing host and port) in the persisted sharding events for actor refs on the same node as the coordinator. We assumed that Akka.Persistence.Eventsourced.Persist does send messages over the network to other nodes. Is this a valid assumption? |
We're using custom persistence provider and custom serialization, also for internal akka sharding events, so we were able to hack around this issue. Right now we're using something along these lines:
|
Fixed this as part of Akka.NET v1.3.14. |
When remote actor gets serialized, it's type is based on
ActorRefWithCell
and it looks like this:akka.tcp://engine@127.0.0.1:24710/system/sharding/shardingtype#376727511
Later on, when it's being deserialized and the actor doesn't exists, it'll be deserialized as
EmptyLocalActorRef
akka.net/src/core/Akka/Actor/ActorRefProvider.cs
Line 439 in da41680
which is then like this:
akka://engine/system/sharding/shardingtype#376727511
so the remote part is lost and these two won't be equal anymore.
The text was updated successfully, but these errors were encountered: