by

Where communities thrive


  • Join over 1.5M+ people
  • Join over 100K+ communities
  • Free without limits
  • Create your own community
People
Activity
  • Jul 05 18:52
    KarolKalbarczyk commented #3234
  • Jul 03 20:21
    Arkatufus edited #4500
  • Jul 03 20:20
    Arkatufus opened #4500
  • Jul 03 18:12
    ismaelhamed opened #4499
  • Jul 03 17:40
    ismaelhamed opened #4498
  • Jul 02 19:33
    Danthar commented #4487
  • Jul 02 19:27
    Danthar closed #4494
  • Jul 02 19:27
    Danthar commented #4494
  • Jul 02 16:12
    Arkatufus commented #4265
  • Jul 02 15:18
    ismaelhamed edited #4497
  • Jul 02 15:16
    ismaelhamed edited #4497
  • Jul 02 15:15
    ismaelhamed opened #4497
  • Jul 02 15:07
    ismaelhamed commented #4482
  • Jul 02 08:02
    glikoz commented #4495
  • Jul 02 08:02
    glikoz commented #4495
  • Jul 01 13:26
    Aaronontheweb closed #4495
  • Jul 01 13:26
    Aaronontheweb commented #4495
  • Jul 01 13:20
    Aaronontheweb commented #4496
  • Jul 01 13:20
    Aaronontheweb milestoned #4496
  • Jul 01 13:20
    Aaronontheweb labeled #4496
Aaron Stannard
@Aaronontheweb
I have an example of what I usually do here...
// pipe the result of our markets to ourselves
            _exchangeFeedClient.HttpClient.Markets.GetProducts(cts.Token).ContinueWith<object>(tr =>
            {
                if (tr.IsCanceled || tr.IsFaulted)
                    return new Status.Failure(tr.Exception);
                return tr.Result;
            }).PipeTo(Self);
I have a catch-all continuation
that I use to handle any case
success or failure
and then my actor who receives this...
Receive<Status.Failure>(s =>
            {
                _currentRetryPolicy = _currentRetryPolicy.Retry(); // update the retry data
                _log.Warning(
                    "Request for list of exchange trade products timed out from {0}. Retrying in {1} seconds with {2} attempts remaining.",
                    _exchangeFeedClient.Endpoints.RestEndpointUri, _currentRetryPolicy.CurrentRetryInterval,
                    _currentRetryPolicy.RemainingAttempts);
                AcquireProductsFeed(_currentRetryPolicy.CurrentRetryInterval);
            }, failure => _currentRetryPolicy.CanRetry);

            Receive<Status.Failure>(s =>
            {
                _log.Error("ERROR: unable to contact exchange at {0} after {1} attempts. Aborting.",
                    _exchangeFeed.HttpClient.Endpoints.RestEndpointUri, _retryPolicyProvider.MaxNrOfAttempts);
                _currentRetryPolicy.Retry(); // throw a HopelessOperation exception on purpose
            }, failure => !_currentRetryPolicy.CanRetry);

            // Received data from the exchange API.
            Receive<ApiResult<IEnumerable<Product>>>(products =>
            {
                if (products.Status == HttpStatusCode.OK)
                {
                    _tradeProducts.AddRange(products.Result);
                    _log.Info("Received products from exchange: {0}", string.Join(",", _tradeProducts.Select(x => x.id)));
                    BecomePublishing();
                }
                else if (_currentRetryPolicy.CanRetry
                ) // something went wrong with our web request, but we have retry attempts remaining
                {
                    _currentRetryPolicy = _currentRetryPolicy.Retry(); // update the retry data
                    _log.Warning(
                        "Received error with our HTTP request ({0}): {1}. Retrying in {2} with {3} attempts left.",
                        products.Status, products.Message,
                        _currentRetryPolicy.CurrentRetryInterval, _currentRetryPolicy.RemainingAttempts);
                    AcquireProductsFeed(_currentRetryPolicy.CurrentRetryInterval);
                }
                else // web request failed, no retry attempts remaining
                {
                    _log.Error(
                        "ERROR: unable to contact exchange at {0} after {1} attempts. HTTP Status: {2}, Message: {3}. Aborting.",
                        _exchangeFeed.HttpClient.Endpoints.RestEndpointUri,
                        _retryPolicyProvider.MaxNrOfAttempts, products.Status, products.Message);
                    _currentRetryPolicy.Retry(); // throw a HopelessOperation exception on purpose
                }
            });
AcquireProductsFeed(_currentRetryPolicy.CurrentRetryInterval); causes me to re-run the task that failed
and the _currentRetryPolicy thing is just a strategy class I wrote that implements various retry strategies
the implementation I'm using here is an exponential-backoff type approach
I wrote that stuff by hand but you can use a library like Polly to get that for free
Aaron Stannard
@Aaronontheweb
@goodisontoffee if you call the normal Persist method
the actor will complete its persistence operation before the next message from the mailbox can be processed
if you call PersistAsync
it will behave as you've described
Dave New
@davenewza
@Aaronontheweb thank you. checking it out
Aaron Stannard
@Aaronontheweb
but even if you call multiple PersistAsync calls in a row
all of your events will still be persisted in order
because the journal itself is implemented as an actor
and it will receive the messages in its own mailbox in that order
Stephen Newman
@goodisontoffee
Just Persist being called, I'll try to confirm but I can't share the code so I'll have to make something that also exhibits what I'm seeing. At which point the example will work properly ;)
So Persist blocks new message consumption until the persistence is complete.
Aaron Stannard
@Aaronontheweb
under the covers
the actor is just stashing messages until it gets an acknowledgement that the persist operation has completed
and then it invokes the callback
so it's not literally blocking a thread
Andrey Leskov
@andreyleskov

Hi all, trying to build client to remote akka system using association. Using test:

public class AssociationErrorTest
    {
        public class EchoActor : ReceiveActor
        {
            public EchoActor(){Receive<object>(m => Sender.Tell(m));}
        }

        [Fact]
        public async Task Test_association()
        {
            var server = ActorSystem.Create("server", @"akka { actor.provider = ""Akka.Remote.RemoteActorRefProvider, Akka.Remote""
                                                               remote.dot-netty.tcp { port = 10001 
                                                                                      hostname = localhost}}");
            var serverActor = server.ActorOf<EchoActor>(nameof(EchoActor));
            var client = ActorSystem.Create("client", @"akka{ actor.provider = ""Akka.Remote.RemoteActorRefProvider, Akka.Remote""
                                                                remote.dot-netty.tcp { port = 0
                                                                                       hostname = localhost}}");
            var remoteActorRef = await client.ActorSelection(@"akka.tcp://server@localhost:10001/user/EchoActor").ResolveOne(TimeSpan.FromSeconds(5));
            await remoteActorRef.Ask<string>("Hello");
        }
    }

if I run it as single test, all is OK . But if I run it with bunch of test, actor selection hangs. Got error from internals:

17-10-05 17:50:08.366 [DBG TH193] Src:[remoting
 "Associated [akka.tcp://server@localhost:10001] <- akka.tcp://client@localhost:5703"

17-10-05 17:50:08.375 [DBG TH201] Src:[endpointWriter#116268940]
 "Associated [akka.tcp://client@localhost:5703] -> akka.tcp://server@localhost:10001"

17-10-05 17:50:08.375 [DBG TH201] Src:[endpointWriter#116268940]
 Drained buffer with maxWriteCount: 50, fullBackoffCount: 1,smallBackoffCount: 0, noBackoffCount: 0,adaptiveBackoff: 1000

17-10-05 17:50:08.388 [DBG TH201] Src:[client)
 Resolve of path sequence [/"temp/N"] failed

looks like client system cannot locate temp actor during Ask()
Can anybody suggest reasons? May be I need some additional configuration ?

Aaron Stannard
@Aaronontheweb
@andreyleskov dollars to donuts
issue is either going to be a static variable that is shared among the actor system instances and this test is running with AppDomains turned off
or one of the remote actor systems is replying to an actor who has since terminated
Andrey Leskov
@andreyleskov
sounds reasonable, but in test above I don't use anything static
may be something inside akka system itself?
Aaron Stannard
@Aaronontheweb
yeah that's what I meant
the name counter we use for naming temporary actors
might be one
Andrey Leskov
@andreyleskov
ooh
you are right
I see letter for temp actor always increasing ))
ok, will run such tests in separate domains
Stijn Herreman
@stijnherreman
I'm having trouble doing more than one transition in an FSM. Not sure if it's a problem with the FSM code or if it's a problem with the unit tests. Simple and full reproducible example at https://stackoverflow.com/questions/46588702/why-does-this-fsm-only-succeed-at-one-state-transition if anyone wants to take a look.
Andrey Leskov
@andreyleskov
thank you a lot for blazing fast answer ! @Aaronontheweb
Stijn Herreman
@stijnherreman
(Is it OK to ask for support here, by the way?)
Aaron Stannard
@Aaronontheweb
@stijnherreman yep, good to ask but it's always good to use StackOverflow so other people can find the answer when they google later
I left an answer on the SO thread
but you need to add a handler for the Done state
otherwise that state is undefined by the FSM
Stijn Herreman
@stijnherreman
@Aaronontheweb thanks! I was stuck on this for a couple of hours already, trying a bunch of different things.
Aaron Stannard
@Aaronontheweb
did that suggestion work?
Stijn Herreman
@stijnherreman
Yes, see the comment to your answer
Aaron Stannard
@Aaronontheweb
ah nice