These are chat archives for akkadotnet/akka.net

20th
Apr 2016
Bartosz Sypytkowski
@Horusiath
Apr 20 2016 06:09
@ilhadad
  1. If the message has been send but not received, you should be able to see it in DeadLetters.
  2. In the config you've specified, you're using cluster actor ref provider, but there is no cluster seed nodes section specified.
  3. I don't get, why are you using Ask pattern here - it looks like a book example for publish/subscribe model.
Vagif Abilov
@object
Apr 20 2016 06:26

@Horusiath do you think FsApi still needs JSON.NET hack or it can be replaced with generic code. In particular I mean replacing the code:

            let serializer = context.System.Serialization.FindSerializerForType typeof<'Message> :?> Akka.Serialization.NewtonSoftJsonSerializer
            match Serialization.tryDeserializeJObject serializer.Serializer o with
            | Some m -> m
            | None -> raise (InvalidCastException("Tried to cast JObject to " + typeof<'Message>.ToString()))

with code:

            match o with
            | :? (byte[]) as bytes -> 
                let serializer = context.System.Serialization.FindSerializerForType typeof<'Message>
                serializer.FromBinary(bytes, typeof<'Message>) :?> 'Message
            | _ -> raise (InvalidCastException("Tried to cast object to " + typeof<'Message>.ToString()))
I replaced such JSON.NET-specific code with more generic and my persistent actors work. But I wonder if I missed some special case.
Bartosz Sypytkowski
@Horusiath
Apr 20 2016 06:28
push the PR, I'll review it later today
Vagif Abilov
@object
Apr 20 2016 06:30
OK
Bartosz Sypytkowski
@Horusiath
Apr 20 2016 06:30
it will be easier to spot the possible problems this way
Vagif Abilov
@object
Apr 20 2016 06:31
Sure, will push it ASAP.
Jari Pennanen
@Ciantic
Apr 20 2016 08:14
Is the typed actors structurally typed? I mean I can just define my dummy class in another app without referencing some single source of types?
Zetanova
@Zetanova
Apr 20 2016 08:15
@Ciantic The akka asm's need to be linked and the base classes used.
Jari Pennanen
@Ciantic
Apr 20 2016 08:16
okay, so they need single source of types
Zetanova
@Zetanova
Apr 20 2016 08:16
The typed actor is utializing the named methods by reflection for message handling
Jari Pennanen
@Ciantic
Apr 20 2016 08:17
I imagine some structurally typed listener would be useful, one wouldn't need to agree on anything but the fields and the connection string
Zetanova
@Zetanova
Apr 20 2016 08:17
but i think u can easly make an actorbase type that will use an unlinked type to handle messages
i think the feature to handle messages by reflection is now in some kind of helper class
Jari Pennanen
@Ciantic
Apr 20 2016 08:18
I would like to ideally define just interfaces in the listening part
no classes at all
and no assembly linking
Zetanova
@Zetanova
Apr 20 2016 08:19
its not importend what it is, the idea is myInstanceActor.Handle((dynamic)message)
one sec
protected override sealed bool Receive(object message)
        {
            MethodInfo method = GetType().GetMethod("Handle", new[] {message.GetType()});
            if (method == null)
            {
                return false;
            }

            method.Invoke(this, new[] {message});
            return true;
        }
its the current code for typedActor
GetType().GetMethod() is i think pritty slow and Handle((dynamic)message) with trycatch would be much faster
but never the less
Jari Pennanen
@Ciantic
Apr 20 2016 08:23
public interface Greet {
int Id { get; set; }
string Name { get; set; }
}
ReceiveStructure<IGreet>(greet => Console.WriteLine("Hello {0}", greet.Name));
Zetanova
@Zetanova
Apr 20 2016 08:23
if u make an own actor base
that just looks up on the bases interface or class instance
for the handler method
and calls it
ten you have your decopling
Jari Pennanen
@Ciantic
Apr 20 2016 08:24
hmm
Zetanova
@Zetanova
Apr 20 2016 08:25
of course Context is somethign u will need
Jari Pennanen
@Ciantic
Apr 20 2016 08:25
shouldn't it check the type?
Zetanova
@Zetanova
Apr 20 2016 08:25
and IActorRef
Jari Pennanen
@Ciantic
Apr 20 2016 08:25
I mean the fields
not the type name, which might not be available
Maciek Misztal
@mmisztal1980
Apr 20 2016 08:26
good morning
anyone know if Akka.Remote supports port sharing?
Zetanova
@Zetanova
Apr 20 2016 08:27
unlikly
Maciek Misztal
@mmisztal1980
Apr 20 2016 08:28
my scenario is : attempt to run multiple lighthouse instances in a servicefarbric cluster - the local cluster has 5 virtual nodes, but they share the same physical host - so I was curious, if I can get it up and running that way. Apparently the SF communication listeners need to support port sharing :/
Zetanova
@Zetanova
Apr 20 2016 08:30
i am not 100% sure, but for port sharing u need native support in the plattform to route the request to the proper process
like http.sys
Maciek Misztal
@mmisztal1980
Apr 20 2016 08:32
seems that there's a port sharing service available https://msdn.microsoft.com/en-us/library/aa395195(v=vs.110).aspx
and it's being used in WCF
Zetanova
@Zetanova
Apr 20 2016 08:32
yes, WCF
its SOAP
Jari Pennanen
@Ciantic
Apr 20 2016 08:33
namespace ConsoleApplication11
{
    [ResultMatches("MyCompany.OtherAssembly.Greet")]
    public interface IGreet
    {
        public string Who { get; set; }
    }

    public class GreetingActor : ReceiveActor
    {
        public GreetingActor()
        {
            Receive<IGreet>(greet => Console.WriteLine("Hello {0}", greet.Who));
        }
    }
}
I wonder would that work
having own attribute there
which did the "connection"
then I would only need to agree on that string
and not link the assemblies
Zetanova
@Zetanova
Apr 20 2016 08:34
?
and how does the message implementation looks like?
Jari Pennanen
@Ciantic
Apr 20 2016 08:35
sending part?
Zetanova
@Zetanova
Apr 20 2016 08:35
the message implementation is usualy put in a shared assembly
and dont realy need link to akka
you have then
Jari Pennanen
@Ciantic
Apr 20 2016 08:36
yes but I wanted to have one without shared message implementation
Zetanova
@Zetanova
Apr 20 2016 08:36
MyClient.dll
MyBase.dll
MySystem.dll
yes it can work, but its slow and very error prone
Vagif Abilov
@object
Apr 20 2016 08:37
@Horusiath PR is submitted with clarification in PR comment.
Jeff Cyr
@JeffCyr
Apr 20 2016 08:39
@mmisztal1980 When you run multiple service fabric node on the same physical host, the service endpoint's port is not shared, all service instance will be assigned a different private port that is retrievable through the service endpoint
Zetanova
@Zetanova
Apr 20 2016 08:41
@Ciantic its a realy good idea to imeplement the messages in a shared assembly. It is basicly the contract definition without it you can pass JSON strings around, that would be even better then the interfaces
Maciek Misztal
@mmisztal1980
Apr 20 2016 08:42
@JeffCyr Hi Jeff, can you point me to some material on this matter please?
Arjen Smits
@Danthar
Apr 20 2016 08:46
@Ciantic What if you deploy multiple actors which "implement" the same interface ? (because your using a router/pool) How would your glue code handle that ?
Jari Pennanen
@Ciantic
Apr 20 2016 08:50
@Danthar I haven't really thought this out, but I just find the idea that my listener need not to agree on one message assembly intriguing, it would allow me to write e.g. user service, and if I don't update my listeners they still work if their message fields matches with it
it is more error prone yes
but the listener could be even in different language
they just agree that with this string, I get this json
Arjen Smits
@Danthar
Apr 20 2016 08:54
what is the role of your listener ? Where does it sit in your architecture ?
Jari Pennanen
@Ciantic
Apr 20 2016 08:55
well the listnere need to be able to talk back in that example
e.g. "ResetPassword"
Arjen Smits
@Danthar
Apr 20 2016 08:57
Ok, well because it sounds to me what your looking for is an "magic" solution to API versioning.
Jari Pennanen
@Ciantic
Apr 20 2016 08:58
well, if the listener is in different language, it couldn't be bound to as
shared message assembly
it has to agree like string "MyCompany.OtherAssembly.Greet" matches with { Greet: string }
{ Who: string }
Arjen Smits
@Danthar
Apr 20 2016 08:59
Akka.net is .net only. We dont have wire level compatibility with the JVM version. (yet) So im not sure thats actually a problem.
Jari Pennanen
@Ciantic
Apr 20 2016 09:01
I have to look how the Scala version's HTTP layer works
it can be used from other languages
Arjen Smits
@Danthar
Apr 20 2016 09:03
Not familiar with the framework. But im guessing it works because of the common well known protocol namely HTTP ?
Jari Pennanen
@Ciantic
Apr 20 2016 09:04
@Danthar yes, but if you send Something.Greet, it must send the name of the item also
not only the json
Zetanova
@Zetanova
Apr 20 2016 09:05
@Ciantic Newton Json serializer includes the type into the payload
But i dont know how u will conect to akka system with a differnt "languge" that cant reference akka.remote assembly
Jari Pennanen
@Ciantic
Apr 20 2016 09:07
@Zetanova apparently I can't, but someday when .NET Akka supports HTTP it maybe possible
looking now how to "curl in to Akka.io"
Zetanova
@Zetanova
Apr 20 2016 09:08
write an warpper
with WebAPI and singularR and hosted with owin or IIS
it includes security too
there you can map the messages, handle unrelated commands like subscription/unsubscriptions connect/disconnect
and make versioning easy happen
its good for native apps too,
Zetanova
@Zetanova
Apr 20 2016 09:13
singnalR has some support for different languages
Marc Piechura
@marcpiechura
Apr 20 2016 09:22
@Ciantic if you refer to Akka.http, I wouldn't wait for it ;) it took 4 people and two years or so to build this on the jvm
Arjen Smits
@Danthar
Apr 20 2016 09:24
I do think that a small abstraction layer between something like Nancy and Akka.net could go a long way
But even then you'd have come up with a communication protocol. And... well..... before you know it, your redefining something like the SOAP envelope :P
Bartosz Sypytkowski
@Horusiath
Apr 20 2016 10:05
@Ciantic Akka.Http is a web framework written on top of akka, not a transport layer for the cluster
@object thx, I'll try to take a look at it this evening
ilhadad
@ilhadad
Apr 20 2016 12:33

Ok got rid of the ask pattern and instead used a message scheduler to time out. here is the new code and config on the sender side:
CODE:

            //Attempt to get a list of supervisors from the SupervisorRegistry
            SupervisorRegistryGetListRequest request = new SupervisorRegistryGetListRequest(Self);
            _SupervisorRegistry.Tell(request);

            var timeout = Context.System.Scheduler.ScheduleTellOnceCancelable(1000, Self, new SupervisorRegistryGetListEvent(request, null, false), Self);

            Receive<SupervisorRegistryGetListEvent>(e => {

                if(e.Success)
                {
                    _logger.Info("{0} Received supervisor list.", Self.Path.ToStringWithAddress());

                    timeout.Cancel();

                    // Save the list for internal use
                    _AreaToSupervisorActor = e.ResponseGetList.SupervisorDictionary;

                    _logger.Debug("Actor {0} is Initialized, moving to Ready state.", _ActorType);
                    Become(Ready);

                }
                else
                {
                    _logger.Warning("{0} Cannot retrieve list of supervisors. Unable to initialize.  {1} retries.", Self.Path.ToStringWithAddress(), _FetchSupervisorListReties);

                    // retry the request and increase the timeout
                    _FetchSupervisorListReties++;

                    // Set up the timeout
                    timeout = Context.System.Scheduler.ScheduleTellOnceCancelable(1000*_FetchSupervisorListReties, Self, new SupervisorRegistryGetListEvent(request, null, false), Self);

                    // Send the request again
                    _SupervisorRegistry.Tell(request);

                }

and the config on the sender side:

akka {
                    # here we are configuring log levels
                    log-config-on-start = off
                    stdout-loglevel = DEBUG
                    loglevel = DEBUG

          // Define an Nlog logger for the Akka system
          loggers = ["Akka.Logger.NLog.NLogLogger, Akka.Logger.NLog"]

            actor {
              provider = "Akka.Remote.RemoteActorRefProvider, Akka.Remote"
            }

            remote {
                            log-remote-lifecycle-events = DEBUG
                            log-received-messages = on

            helios.tcp {
                                hostname = "127.0.0.1"
                                port = 8777
              }
            }
And here is the new config and code on the receiver side:
        private void HandleGetListRequest(SupervisorRegistryGetListRequest r)
        {
            ImmutableDictionary<MicroServices.Area,IActorRef> immutableDictOfSupervisorsActors = 
                _KnownSupervisorsActors.ToImmutableDictionary(kvp => kvp.Key, kvp => kvp.Value.SupervisorActorReference);

            Sender.Tell(new SupervisorRegistryGetListResponse(r.Requestor,immutableDictOfSupervisorsActors,r));

        }
                akka {
                    # here we are configuring log levels
                    log-config-on-start = off
                    stdout-loglevel = DEBUG
                    loglevel = DEBUG

          // Define an Nlog logger for the Akka system
          loggers = ["Akka.Logger.NLog.NLogLogger, Akka.Logger.NLog"]

          // Enables connectivity to the remote ActorSystemBridge
          actor {
              provider = "Akka.Remote.RemoteActorRefProvider, Akka.Remote"
          }

          remote {
            helios.tcp {
                port = 8888
                hostname = "127.0.0.1"
            }
          }

                }

@Horusiath I took out the cluster

Ok got rid of the ask pattern and instead used a message scheduler to time out. here is the new code and config on the sender side:
CODE

            //Attempt to get a list of supervisors from the SupervisorRegistry
            SupervisorRegistryGetListRequest request = new SupervisorRegistryGetListRequest(Self);
            _SupervisorRegistry.Tell(request);

            var timeout = Context.System.Scheduler.ScheduleTellOnceCancelable(1000, Self, new SupervisorRegistryGetListEvent(request, null, false), Self);

            Receive<SupervisorRegistryGetListEvent>(e => {

                if(e.Success)
                {
                    _logger.Info("{0} Received supervisor list.", Self.Path.ToStringWithAddress());

                    timeout.Cancel();

                    // Save the list for internal use
                    _AreaToSupervisorActor = e.ResponseGetList.SupervisorDictionary;

                    _logger.Debug("Actor {0} is Initialized, moving to Ready state.", _ActorType);
                    Become(Ready);

                }
                else
                {
                    _logger.Warning("{0} Cannot retrieve list of supervisors. Unable to initialize.  {1} retries.", Self.Path.ToStringWithAddress(), _FetchSupervisorListReties);

                    // retry the request and increase the timeout
                    _FetchSupervisorListReties++;

                    // Set up the timeout
                    timeout = Context.System.Scheduler.ScheduleTellOnceCancelable(1000*_FetchSupervisorListReties, Self, new SupervisorRegistryGetListEvent(request, null, false), Self);

                    // Send the request again
                    _SupervisorRegistry.Tell(request);

                }

and the config on the sender side:


akka {
                    # here we are configuring log levels
                    log-config-on-start = off
                    stdout-loglevel = DEBUG
                    loglevel = DEBUG

          // Define an Nlog logger for the Akka system
          loggers = ["Akka.Logger.NLog.NLogLogger, Akka.Logger.NLog"]

            actor {
              provider = "Akka.Remote.RemoteActorRefProvider, Akka.Remote"
            }

            remote {
                            log-remote-lifecycle-events = DEBUG
                            log-received-messages = on

            helios.tcp {
                                hostname = "127.0.0.1"
                                port = 8777
              }
            }
ilhadad
@ilhadad
Apr 20 2016 12:38
How can I examine dead letters to see what's going on? Also how do I get the logger to give me more info as to the root issue? Any other suggestions?
Kris Schepers
@schepersk
Apr 20 2016 13:44
Any idea when the new SqlServer persistence package will be available?
ilhadad
@ilhadad
Apr 20 2016 14:45
@Horusiath I was able to subscribe to the event stream to pull the dead letters it seems the messages are arriving at the remote system but they are all landing in deadletters. Not sure how to figure out what's wrong by looking at the deadletters. Any suggestions?
Bartosz Sypytkowski
@Horusiath
Apr 20 2016 14:47
@ilhadad either the message recipient is dead, was not created, or its address is wrong
@schepersk we'll talk about this probably on today's meeting
Kris Schepers
@schepersk
Apr 20 2016 14:50
@Horusiath :+1:
ilhadad
@ilhadad
Apr 20 2016 15:43
@Horusiath When I send the reply with an immutable dictionary embedded in it fails, however, when I send the reply with a null it works. I though maybe it was a message size issue but that did not work either. Any other ideas?
Bartosz Sypytkowski
@Horusiath
Apr 20 2016 15:49
@ilhadad maybe message cannot be serialized/deserialized?
ilhadad
@ilhadad
Apr 20 2016 15:50
I guess so. Is there a way to peek into this process?
Bartosz Sypytkowski
@Horusiath
Apr 20 2016 15:57
var serializer = actorSystem.Serialization.FindSerializerFor(message);
var binary = serializer.ToBinary(message);
ilhadad
@ilhadad
Apr 20 2016 15:59
Is there a way to decorate a property with an attribute that will force serialization?
ilhadad
@ilhadad
Apr 20 2016 16:40
@Horusiath Thanks for your help - we figured it out. The issue is related to the serialization/deserialize process! As it turns out if you have a dictionary of some object the object must have a default constructor. If it does not somehow the deserialization process fails. We even tried sending the message without the default constructor and that too also failed. SO... a default constructor is needed. Painful!
Bartosz Sypytkowski
@Horusiath
Apr 20 2016 16:57
@ilhadad strange, I've got a lot of messages without default constructors and I'm pretty sure it was never an issue
ilhadad
@ilhadad
Apr 20 2016 17:07
@Horusiath It also seems that the immutabledictionary cannot be sent over the wire while a regular dictionary is not a problem. Wierd. Can I use a regular dictionary?
Bartosz Sypytkowski
@Horusiath
Apr 20 2016 17:09
yes, unless you modify it after putting into a message. If you have that risk, simply do .ToDictionary() call to create a copy of it.
ilhadad
@ilhadad
Apr 20 2016 17:17
ok thanks for all your help.
morioma
@morioma
Apr 20 2016 18:29

To handle remote disconnection I did something like this

signalRSelection = Context.ActorSelection("akka.tcp://api@127.0.0.1:4545/user/signalr");
signalRSelection.Tell(message);

So, I am forcing a Context.ActorSelection before tell. I am thinking this should work although there could be performance issue.
However, this doesn't seems to work all the time. (It works the first time the remote disconnected).
Anyway to do this kind of if(disconneted){ connect(); }?
(I am aware the watch for Terminated method. However, I have trouble finding the right time to ActorSelection again, because the remote could be still not available. )

morioma
@morioma
Apr 20 2016 18:36
(I tried Cluster too, however, a bug regarding cluster broadcast group is prevent me to use it).
Vagif Abilov
@object
Apr 20 2016 18:51
I've read recommendations to be extra careful when choosing serializer for persistent actors, and it makes sense - nobody wants past events to become unreadable. So I am rethinking our persistence serializer choice - we switched to Wire after Akka.NET 1.0.7 came with a warning that JSON.NET will be obsolete, but I am becoming more in favour of plain JSON documents that we will always be able to retrieve and parse into some internal type. So I am a bit confused with these recent Akka warnings about switching to Wire. Should we really? What will be the consequences for using JSON.NET? Or should we just use a different lib to read/write JSON documents?
Bartosz Sypytkowski
@Horusiath
Apr 20 2016 19:05
@object general advise here is to have separate serializers for inter-cluster communication and for persistence, as these two things have a different priorities. When it comes to JSON.NET - it's a nightmare for case of Akka.NET. It's very slow, has big memory footprint, and it's unreliable in many cases (especially F# data structures and some weird combinations of system.collections.immutable and surrogate mechanism).
Vagif Abilov
@object
Apr 20 2016 19:10
@Horusiath so what would you recommend for persistence serializer to ensure long lifetime of encoded events? And if Json docs are OK what handles them better than JSON.NET?
Bartosz Sypytkowski
@Horusiath
Apr 20 2016 19:15
it depends on you. Some people like to use json as format for event sourcing - I personally would choose it only when it has native support from database (i.e. postgres, mongodb, eventstore). Otherwise I would go for something schema-driven, like Protocol Buffers, MS Bond or Avro. But tbh it's a matter of personal opinion.
Vagif Abilov
@object
Apr 20 2016 19:20
I see. I've been also looking at Protocol Buffers. And in case of Json ServiceStack seems to be quite fast. When it comes to language type support, I am drifting to a conclusion that we should say goodbye to fancy F# types as journal event types and instead use adapters (like some Scala Akka article suggests) to convert to representation close to serialization protocol.