These are chat archives for akkadotnet/akka.net

7th
Feb 2018
Riccardo Terrell
@TRikace_twitter
Feb 07 2018 14:24

I am trying to create a child actor that is using dependency injection (AutoFac). The Interface (see IProposalService) requires the IPrincipal to instantiate the underlying implementation. However, the current Thread.CurrentPrincipal don't flow in the child actor implementation and I am getting an error.
Here partial code

public class ProposalFilterActor : ReceiveActor
{
    public ProposalFilterActor()
    {
        Receive<SerpFilterEligibleIndividualsParameters>(parameters =>
        {
            var proposalChildActorName = $"proposal-{parameters.ProposalId}";
            if (Context.Child(proposalChildActorName).Equals(ActorRefs.Nobody))
            {
                var proposalChildActor = Context.ActorOf(Context.DI().Props<ProposalFilterEligibleIndividualActor>(), proposalChildActorName);
                proposalChildActor.Tell(parameters.ProposalId);
            }
            else
            {}             
        });
    }
}

public class ProposalFilterEligibleIndividualActor : ReceiveActor
{
    private readonly IProposalService proposalService;
    public ProposalFilterEligibleIndividualActor(IProposalService proposalService)
    {
        this.proposalService = proposalService;

        ReceiveAsync<int>(async proposalId =>

Thoughts ??

Onur Gumus
@OnurGumus
Feb 07 2018 15:51
@TRikace_twitter I wouldn't use Thread.CurrentPrincipal with actors
I just noticed DistributedEvents serializes the published message in json.
Why is that so?
Onur Gumus
@OnurGumus
Feb 07 2018 15:56
I am trying to publish a message that contains NodaTime. But it fails with a deserialization error on the receiver and it is using json.net
Onur Gumus
@OnurGumus
Feb 07 2018 16:08
Hmm weird the default serialization map shows that System.Object is serialized by newtonsoft.json
I thought default is protobuff
Onur Gumus
@OnurGumus
Feb 07 2018 16:30
And I cannot change the serializer for a type it just doesn't work.
Riccardo Terrell
@TRikace_twitter
Feb 07 2018 16:34
@OnurGumus the IPrincipal is used to instantiate the underlying ORM for security reasons
Onur Gumus
@OnurGumus
Feb 07 2018 16:35
It is a contextful threading artifact. It is definitely a no no in the world of actors
Riccardo Terrell
@TRikace_twitter
Feb 07 2018 16:36
what would you recommend in place of Thread.CurrentPrincipal ? I am assuming the creation of a child actor is happening in a different thread (in this case), which looses the IPrincipal
Onur Gumus
@OnurGumus
Feb 07 2018 16:36
Yes.
Riccardo Terrell
@TRikace_twitter
Feb 07 2018 16:36
Agree... looking for alternative
suggestion are welcome
Onur Gumus
@OnurGumus
Feb 07 2018 16:36
You need to pass the principle manually by telling it to the actor
Actually I would just get rid of the principle in actors realm
It is a threading artifact.
But again you can pass it manually , though it will be disassociated from a thread.
Riccardo Terrell
@TRikace_twitter
Feb 07 2018 16:38
agree ... but the re-design would require a huge effort
would you pass the principle as part of the message payload ?
Onur Gumus
@OnurGumus
Feb 07 2018 16:38
Yes
or while creating the actor
pass it to the props if applicable
Your tech stack is quite intriguing, IPrinciple, Actors and ORMs
not a match made in heaven for sure.
Riccardo Terrell
@TRikace_twitter
Feb 07 2018 16:40
I am not sure if intriguing is the word I would use ;)
Onur Gumus
@OnurGumus
Feb 07 2018 16:41
I just wanted to be polite :)
Riccardo Terrell
@TRikace_twitter
Feb 07 2018 16:41
but thank you for the support. LOL
WAIT!!! how would you pass the IPrincipol through props ?? this is interesting
Onur Gumus
@OnurGumus
Feb 07 2018 16:42
just like any ctor parameter.
but once you do it, that principle is fixed to that actor as an input for any new restarts
Riccardo Terrell
@TRikace_twitter
Feb 07 2018 16:43
HA!!! I see ... I thought there was some sort of magical way to do it ;)
Thank you
Onur Gumus
@OnurGumus
Feb 07 2018 16:43
akka is no magic :) that's why it is great.
@TRikace_twitter there is one last resort, but I highly unrecommend it: CallingThreadDispatcher
that would make your actor running on the same thread
Props.Create<MyActor>().WithDispatcher(CallingThreadDispatcher.Id)
I have never used this though.
Riccardo Terrell
@TRikace_twitter
Feb 07 2018 16:47
I ll try that just because, but ultimatlly I won't do that ... sounds 'intriguing' :)
Bartosz Sypytkowski
@Horusiath
Feb 07 2018 16:57
@TRikace_twitter unless you'll manually pin your actor to specific thread (using props.WithDispatcher(dispatcher) method) actor is allowed to to execute every message on different thread
Onur Gumus
@OnurGumus
Feb 07 2018 16:58
@Horusiath can you help me with my serialization questions?
Bartosz Sypytkowski
@Horusiath
Feb 07 2018 17:00
@OnurGumus default serializer for akka.net is json.net - from v1.5 it's planned to be changed in favor of Hyperion. Protobuf is used for some of the internal messages.
Onur Gumus
@OnurGumus
Feb 07 2018 17:00
Oh, yes I digged into that.
Bartosz Sypytkowski
@Horusiath
Feb 07 2018 17:00
I'm not sure what properties of NodaTime objects are failing to be deserialized, Hyperion is usually more tolerant over data format
(except that it's binary format is not set in stone, so it's not good for long living serialization i.e. used in persistence)
Onur Gumus
@OnurGumus
Feb 07 2018 17:01
Well I digged that too. The thing is standard newtonsoft serializer settings it can serialize and deserialize nodatime without an issue.
it's just akka put some $ signs to the text
I mean akka's newtonsoft config.
{"$id":"1","$type":"NodaTime.LocalDateTime, NodaTime","year":{"$":"I2018"},"month":{"$":"I2"},"day":{"$":"I7"},"calendar":0,"nanoOfDay":75753233727600}
Bartosz Sypytkowski
@Horusiath
Feb 07 2018 17:03
we use custom serializer config in order to be able to use polymorphic data types in serializer
  • tracking references between objects
Onur Gumus
@OnurGumus
Feb 07 2018 17:03
this is the serialized string, and while deserializing it, it thinks $:l2 is a integer
and boom
Bartosz Sypytkowski
@Horusiath
Feb 07 2018 17:04
where are you deserializing it?
Onur Gumus
@OnurGumus
Feb 07 2018 17:05
The original issue happened when I published a distributed event, and receiver threw this exception, now to isolate the issue, I use the serializer directly by
  var s2 = (NewtonSoftJsonSerializer) system.Serialization.FindSerializerFor(typeof(LocalDateTime));
and I serialize locally
and desrialize locally
it now has nothing to do with akka, and still causes this error the sameway
so your settings are somewhat incompatible with nodatime
if I use newtonsoft with default it just works fine
second thing is I just tried things like :
    serializers {
           json = "Akka.Serialization.NewtonSoftJsonSerializer"
           bytes = "Akka.Serialization.ByteArraySerializer"

          }
           serialization-bindings {
              "System.Object" = bytes
          }
or even hyperion, it doesn't take any affect.
 akka {
           actor.provider = cluster
            remote {
                dot-netty.tcp {
                    port = 8082
                    hostname = localhost
                }
            }
          cluster {
             seed-nodes = ["akka.tcp://ClusterSystem@localhost:8081","akka.tcp://ClusterSystem@localhost:8082"] # address of seed node
          }
            serializers {
           json = "Akka.Serialization.NewtonSoftJsonSerializer"
           bytes = "Akka.Serialization.ByteArraySerializer"

          }
           serialization-bindings {
              "System.Object" = bytes
          }
        }
this is my whole section
I still see System.Object is newtonsoft
from the mapper by debugger
Onur Gumus
@OnurGumus
Feb 07 2018 17:18
public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
            {
                if (value is int || value is decimal || value is float)
                {
                    writer.WriteStartObject();
                    writer.WritePropertyName("$");
                    writer.WriteValue(this.GetString(value));
                    writer.WriteEndObject();
                    return;
                }
                ISurrogated surrogated = value as ISurrogated;
                if (surrogated != null)
                {
                    ISurrogate surrogate = surrogated.ToSurrogate(this._parent.system);
                    serializer.Serialize(writer, surrogate);
                    return;
                }
I guess this is where you add $
I think this is a bug with akka serializer
Bartosz Sypytkowski
@Horusiath
Feb 07 2018 17:30
can you create an issue?
Onur Gumus
@OnurGumus
Feb 07 2018 17:30
Yes I was doing that.
Onur Gumus
@OnurGumus
Feb 07 2018 17:37
@Horusiath akkadotnet/akka.net#3319
@Horusiath how about the second issue. I am not able to specify a custom serializer for my types via config.
akka just ignores it.
Bartosz Sypytkowski
@Horusiath
Feb 07 2018 17:48
can you present your hocon config?
for serializers only
Onur Gumus
@OnurGumus
Feb 07 2018 17:48
Already above
   serializers {
           json = "Akka.Serialization.NewtonSoftJsonSerializer"
           bytes = "Akka.Serialization.ByteArraySerializer"

          }
           serialization-bindings {
              "System.Object" = bytes
          }
Bartosz Sypytkowski
@Horusiath
Feb 07 2018 17:51
this is not full path
Onur Gumus
@OnurGumus
Feb 07 2018 17:51
you mean hocon ?
I am not sure what you mean by not full path?
Bartosz Sypytkowski
@Horusiath
Feb 07 2018 17:52
akka
  actor {
    serializers {
      bytes  = "Akka.Serialization.ByteArraySerializer, Akka"
    }
    serialization-bindings {
      "System.Object" = bytes
    }
  }
}
totally different thing is that this will break your actor system apart
Onur Gumus
@OnurGumus
Feb 07 2018 17:53
oh wait serializers should be inside the actor
hang on
Bartosz Sypytkowski
@Horusiath
Feb 07 2018 17:53
usually you'll need to add assembly name too, along with type name
Onur Gumus
@OnurGumus
Feb 07 2018 17:54
the docs doesn't say so.
my hocon is correct
Bartosz Sypytkowski
@Horusiath
Feb 07 2018 17:56
this is not akka requirement, it's a .net
Onur Gumus
@OnurGumus
Feb 07 2018 17:56
@Horusiath it just doesn't work
Well I tried above as well
Bartosz Sypytkowski
@Horusiath
Feb 07 2018 17:57
how are you pushing your hocon config to your actor system?
Onur Gumus
@OnurGumus
Feb 07 2018 17:57
I am sure my hocon is parsed since I am using a cluster and cluster is working
I load it by Configuration.Load();
ConfigurationFactory.Load();
Then pass this to ActorSystem.Create
Assembly name is implicit for Akka
Oh wait
@Horusiath I am sorry. This was my mistake. now it works
So, never mind.
Bartosz Sypytkowski
@Horusiath
Feb 07 2018 18:00
no problem ;)
Onur Gumus
@OnurGumus
Feb 07 2018 18:01
What do you think of Hyperion
for these corner cases like nodatime , shall I use it ?
Bartosz Sypytkowski
@Horusiath
Feb 07 2018 18:01
it's not in it's final version, but it can handle more cases (and with higher performance) than json.net
Onur Gumus
@OnurGumus
Feb 07 2018 18:02
What was your motivation for switching to newtonsoft? It is buggy ?
Bartosz Sypytkowski
@Horusiath
Feb 07 2018 18:02
besides, it's already required for some of the higher-level plugins (because Json.net couldn't handle some corner cases)
Onur Gumus
@OnurGumus
Feb 07 2018 18:03
Is it fine if I use it for production ?
Bartosz Sypytkowski
@Horusiath
Feb 07 2018 18:06
yes, except persistence
Onur Gumus
@OnurGumus
Feb 07 2018 18:07
And for persistence, it is buggy?
Bartosz Sypytkowski
@Horusiath
Feb 07 2018 18:08
no, because its binary format will change in the future - for remoting it's problematic but not critical (it's just harder to gradually upgrade your cluster). But binary format change for persistence means, that you'll be no longer able to replay past data after serializer update
Onur Gumus
@OnurGumus
Feb 07 2018 18:09
Yeah
Can you specify serializers for persistence and remoting differently?
akka {
  actor {
    serializers {
      hyperion = "Akka.Serialization.HyperionSerializer, Akka.Serialization.Hyperion"
    }
    serialization-bindings {
      "System.Object" = hyperion
    }
  }
}
if I do does this both persistence and remoting change?
Bartosz Sypytkowski
@Horusiath
Feb 07 2018 18:12
  1. this depends on the actual persistence plugin
  2. in general a common pattern here is to specify custom marker interface, and set up a custom serializer for this interface type
Onur Gumus
@OnurGumus
Feb 07 2018 18:13
I see. Good idea.
Bartosz Sypytkowski
@Horusiath
Feb 07 2018 18:13
I've written a blog post about persistence some time ago: http://bartoszsypytkowski.com/akka-persistence-most-common-misconceptions/
Onur Gumus
@OnurGumus
Feb 07 2018 18:16
One of the first mistakes, everyone do, is giving up your data in the hands of the default serializer.
Lol
Onur Gumus
@OnurGumus
Feb 07 2018 18:29
@Horusiath Has hyperion's name changed? Because the assembly is now named Hyperion. And if I try to configure it like Hyperion.Serializer, Hyperion, it complains that constructor not found.
Probably trying to pass the actor system to its constructor
Not sure though
Bartosz Sypytkowski
@Horusiath
Feb 07 2018 18:29
Hyperion is generic serializer - the akka.net compatible is part of Akka.Serialization.Hyperion package
Onur Gumus
@OnurGumus
Feb 07 2018 18:30
ah it's prerelease that's why I didn't see it on nuget
@Horusiath another question, AFAIK regardless the serializer you use, the end result is converted to bytearray after serialization right? What if I want to keep it as JSON
I mean as a string
For example SQLServer 2017 supports json columns as strings
I guess it is journal plugin's duty convert it back
Bartosz Sypytkowski
@Horusiath
Feb 07 2018 18:35
json support was in different stages depending on the persistence plugin used - afaik Postgres was the most advanced one. Sql Server is waiting for its turn.
Onur Gumus
@OnurGumus
Feb 07 2018 18:35
It is quite good on Sql server 2017.
Oracle also is quite good
Bartosz Sypytkowski
@Horusiath
Feb 07 2018 18:43
I know, we just don't have enough time to work on everything that needs attention. It's community-based project, afaik no one is paid to work on it full-time ;)
Onur Gumus
@OnurGumus
Feb 07 2018 18:47
Yeah probably.
Onur Gumus
@OnurGumus
Feb 07 2018 19:04
@Horusiath I worked around nodatime issue by creating a custom serializer that uses plain old newtonsoft
@Horusiath The type's signature is as below :
public struct LocalDateTime : IEquatable<LocalDateTime>, IComparable<LocalDateTime>, IComparable, IFormattable, IXmlSerializable, ISerializable
Note that it implements ISerializable
I think this causes on deserialization, it short circuits your serializer.
and directly tries to deserialize the string itself