App-vNext / Polly

Polly is a .NET resilience and transient-fault-handling library that allows developers to express policies such as Retry, Circuit Breaker, Timeout, Bulkhead Isolation, and Fallback in a fluent and thread-safe manner. From version 6.0.1, Polly targets .NET Standard 1.1 and 2.0+.
https://www.thepollyproject.org
BSD 3-Clause "New" or "Revised" License
13.37k stars 1.23k forks source link

Polly and Rx #134

Closed adamhathcock closed 7 years ago

adamhathcock commented 8 years ago

Reading further about things like Polly, I've been diving more into Rx and even back to actor-like frameworks like Akka.NET and Orleans.

If Polly is pushing past "transient application block" stuff, does it means it competes with (or maybe should be based on) Rx? Has this been looked at at all? Just wondering :)

I found a good post with a guy implementing Caching with Rx and HttpClient: https://asizikov.github.io/2015/07/26/rx-api-with-cache-one/

Also some other tips with Rx and HttpClient examples: http://log.paulbetts.org/rx-and-await-some-notes/

Rx already has a Timeout extension as well as some TaskScheduler.

I feel like there's some overlap here. Polly could be based on Rx and make it easier to do "real" things there are pre-implemented as Policies.

reisenberger commented 8 years ago

@adamhathcock Short answer (for now) to a big question: yes, a great idea (to do Polly.Rx.Net); yes, it has been thought about; probably not the right time to introduce Rx into the Polly project at the moment. (i'll aim to expand on this later)

adamhathcock commented 8 years ago

Thanks. I'm just trying to sort out the use cases for Polly vs other things and I remembered Rx but haven't heavily used it.

reisenberger commented 8 years ago

To come back to this in detail: a great question, and one that we have explored at AppvNext at various times.

There’s just a great opportunity out there to take the spirit of Polly and apply it to Rx to make Polly.Rx.Net (Polly functionality fully implemented in the Rx API). Just a great idea. If anyone wants to do this, or take a shot at starting it, shout. It’s not something I have time to take on at the moment (could divert, but at the expense of all the other forward functionality.) Rx has some related implementations already built in, and people in the blogosphere have explored how to implement other parts.

Should existing Polly be rewritten with Rx behind, or new Polly features in the existing API be implemented in Rx because something similar in Rx already exists? A slightly different question. One observation is that the existing API we're building on (the fixed point in the current proj at least) is imperative and very much focused on inflecting the operation of a single Action or Func at a time. Given that, not so sure it's a good fit (/makes for a readable implementation) say to fulfil functionality by generating an Rx Observable that’s only ever destined to return one result?

But a proper, Rx-focused Polly.Rx.Net? That's a great idea.


Really interested to hear more from the community also on this: is there a demand for an Rx-focused Polly?

reisenberger commented 7 years ago

Closing due to lack of activity/comment.

apobekiaris commented 6 years ago

I started integrating Polly and rx and the problem I face is that I cannot control the time between retries. For example RX has a TestScheduler which makes it very easy to move the virtual time. But when Polly has to handle an exception I have to switch back my tests to awaits and the Default.Scheduler. Any suggestions on this?

apobekiaris commented 6 years ago

a possible solution could be an overload that I could do something lie

Scheduler.Default.Sleep(TimeSpan.FromTicks(1000)

and in the RX case I could use the TestScheduler instead of the default one

reisenberger commented 6 years ago

@apobekiaris Polly does not have any internal TaskSchedulers it manages, so there isn't (in that sense) any option to change the scheduler that Polly uses.

Is the question how to unit-test (for example) a wait-and-retry policy which waits N seconds, without having the test actually take N seconds elapsed real-world time? If so: All Polly policies which interact with time use an abstracted system clock. This, and its properties, are public, so you can manipulate virtual time in tests to avoid real-world delays. See any of the tests in the codebase which manipulate SystemClock, for examples.

wassim-k commented 1 year ago

I know this is an old issue, but I found it while looking for a similar feature, and ended up writing the following extension method, hopefully someone else will find it helpful:

public static IObservable<T> WaitAndRetry<T>(
    this IObservable<T> source,
    IEnumerable<TimeSpan> durationProvider,
    bool forever = false)
{
    IEnumerator<TimeSpan>? enumerator = default;
    var reset = false;

    return source
        .Do(_ => reset = true)
        .RetryWhen(error => error.SelectMany(ex =>
        {
            if (reset || enumerator == null)
            {
                enumerator = durationProvider.GetEnumerator();
            }

            return enumerator.MoveNext() || forever
                ? Observable.Timer(enumerator.Current)
                : Observable.Throw<long>(ex);
        }));
}

Then it can be used with the help of Polly.Contrib.WaitAndRetry as follows:

observable.WaitAndRetry(Backoff.ExponentialBackoff(TimeSpan.FromSeconds(2), 5, fastFirst: true))