Hi there,
I've just started using Polly (with Xamarin) and the contept is quite good, but I haven't seem to get it working they way I would like it to work.
What I want is:
The retrying and logging part works great, but the method doesn't carry on executing after the retries. So the method never returns the result (null) and the UI never gets confirmation.
Am I doing something wrong?
My code: http://pastebin.com/KUwY25L5
Hey @Mittchel. Thanks for your interest in Polly! Great to hear about the usage within Xamarin - love to hear more details about the context within xamarin, if you can share :smile:
A Polly retry policy will absorb handled exceptions and make a retry, for the number of retries you have configured. _After_ the number of configured retries are exhausted, the policy _stops_ absorbing exceptions and rethrows the final (one-too-many) exception. Rethrowing allows calling code to observe that last exception.
Reading your sample code, assuming _eventService.GetEventsWithError() is throwing more than 5 exceptions in a row, the 6th exception will get rethrown from within .ExecuteAsync(). Since you don't have any try/catch, this will get passed back up the call chain to whatever called GetEventsErrorRemoteAsync(). Likely, that exception being thrown back up the call stack beyond GetEventsErrorRemoteAsync() is causing your UI never to update.
Two ways you could avoid this. Either:
try { } catch { } around the call to .ExecuteAsync(), to catch the final exception; [or].ExecuteAndCaptureAsync() instead of .ExecuteAsync(). .ExecuteAndCaptureAsync() traps any final exception for you, and captures the overall outcome of policy execution into a PolicyResult instance. You can extract either (on success) the TResult from this, or (on failure, if interested) the FinalException.Let us know if that solves the issue for you! - or if any other questions.
Thanks!
Hey @reisenberger thanks for the amazing in-depth comment. I really appreciate it and you gave me something to work on.
You are right about the exception getting lost when its thrown up to the caller. I just wanted to update my post, but you beat me to it.
I'm currently doing a demo application with full stack resiliency including some amazing libraries like Polly.
The odd thing though is when I put a breakpoint on the events variable it actualy never hits. You sure this is also about the exception thats thrown on different thread?
Hey @Mittchel . Not sure the exact place you mean, in 'breakpoint on the events variable', but: It is the policy's operating code (invoked behind .ExecuteAsync()) which will rethrow the final exception.
Assuming private async Task<List<EventDto>> GetEventsErrorRemoteAsync() is being called with an await, the exception should bubble further up the call stack until something catches it (or not!). If GetEventsErrorRemoteAsync() isn't being called with an await, the exception would get placed in the returning Task and the task placed in an IsFaulted state (which could cause it to seem to disappear, if not checked for).
You could also possibly fall foul of an invalid cast, at (ApiException)exception (though a cast exception would be thrown if you did). If you're confident the only exceptions you expect to receive / want to handle in the policy are ApiException, you could .Handle<ApiException>() at line 15, to preclude the invalid cast possibility.
@reisenberger Gotcha!
Problem I'm facing is that I'm using Akavache with this. Akavache uses ReactiveUI, but I'm not really sure how to bubble up the Exception in a nice way.
Right. I've not used Akavache or ReactiveUI, so may not be able to help there. In general, there are standard ways to turn Task<T> into an RX Observable<T>, which will also cause any exception thrown within the Task to be emitted by the Observable: see http://www.introtorx.com/Content/v1.0.10621.0/04_CreatingObservableSequences.html#FromTask !
But that link may be irrelevant to your needs, as the libraries you're using should be covering it. Looking at the http://reactiveui.net/ front page, they seem to show ways of capturing exceptions thrown by the delegates you execute with ReactiveCommand.
Added extra diagrams to the wiki covering the full lifecycle of a retry request, including what happens when all trys expire.
Most helpful comment
Hey @Mittchel. Thanks for your interest in Polly! Great to hear about the usage within Xamarin - love to hear more details about the context within xamarin, if you can share :smile:
A Polly retry policy will absorb handled exceptions and make a retry, for the number of retries you have configured. _After_ the number of configured retries are exhausted, the policy _stops_ absorbing exceptions and rethrows the final (one-too-many) exception. Rethrowing allows calling code to observe that last exception.
Reading your sample code, assuming
_eventService.GetEventsWithError()is throwing more than 5 exceptions in a row, the 6th exception will get rethrown from within.ExecuteAsync(). Since you don't have anytry/catch, this will get passed back up the call chain to whatever calledGetEventsErrorRemoteAsync(). Likely, that exception being thrown back up the call stack beyondGetEventsErrorRemoteAsync()is causing your UI never to update.Two ways you could avoid this. Either:
try { } catch { }around the call to.ExecuteAsync(), to catch the final exception; [or].ExecuteAndCaptureAsync()instead of.ExecuteAsync()..ExecuteAndCaptureAsync()traps any final exception for you, and captures the overall outcome of policy execution into aPolicyResultinstance. You can extract either (on success) theTResultfrom this, or (on failure, if interested) theFinalException.Let us know if that solves the issue for you! - or if any other questions.
Thanks!