Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Passing exception and retry count to execution (general: pass mutable data between onRetry and Execute) #38

Closed
YoniH opened this issue Jun 23, 2015 · 4 comments

Comments

@YoniH
Copy link

YoniH commented Jun 23, 2015

Hi,

In policy execution, I need to access the retry number and the exception that was thrown.

I managed to do this only with class members, as in this console app:

class Program
{
    private static Exception mException;
    private static int mRetryCount;

    static void Main(string[] args)
    {
        var policy = Policy.Handle<DivideByZeroException>().Retry((exception, retryCount, context) =>
        {
            mException = exception;
            mRetryCount = retryCount;
        });

        policy.Execute(DoSomething);
    }

    private static void DoSomething()
    {
        Console.WriteLine("Try number {0}", mRetryCount);
        Console.WriteLine("Exception was {0}", mException);
        Console.WriteLine();

        int x = 0;
        var y = 2/x;
    }
}

However, is there a way to do this only with Polly, without class members?

@YoniH
Copy link
Author

YoniH commented Jun 24, 2015

After some more experimenting with the library, I want to try to be more accurate. What I want to do is this:

  1. On every retry, I want to calculate some numeric value based on the exception and maybe the retry count.
  2. This number should be passed as argument to the execution function.

Currently the way I'm doing it is something like this:

class Program
{
    static void Main(string[] args)
    {
        var someNumber = new Integer();

        var policy = Policy.Handle<DivideByZeroException>().Retry(3, (exception, retryCount, context) =>
        {
            (context["someNumber"] as Integer).Value = 17; //Instead of 17, the value would be calculated based on the exception
        });

        policy.Execute(() => DoSomething(someNumber), new Dictionary<string, object>{{"someNumber", someNumber}});
    }

    private static void DoSomething(Integer numberArgument)
    {
        Console.WriteLine("The number is {0}", numberArgument.Value);
        Console.WriteLine();

        int x = 0;
        var y = 2/x;
    }

    class Integer
    {
        public int Value { get; set; }
    }
}

This seems a bit cumbersome. Is there a better way to do that?

@savehansson
Copy link

Any news on this?

@reisenberger reisenberger changed the title Passing exception and retry count to execution Passing exception and retry count to execution (general: pass mutuable data between onRetry and Execute) Jan 24, 2016
@reisenberger
Copy link
Member

@YoniH @hawkunsh An AppvNext team has taken over stewardship of Polly, and are now looking at historic issues such as this. I'll comment in case still useful to you or others.

The ContextualPolicy was added way back #1, and had as intention to pass static (read-only) data from a particular .Execute() call to the onRetry delegate of a policy. It looks as if context was made a read-only collection as the focus was on capturing static data for logging; perhaps also to avoid getting in to issues of thread-safety. As you have discovered, although you cannot manipulate the contents of the collection, you can exchange mutable data by manipulating a property on some fixed instance held in the collection.

The general case of your request would be a mechanism within Polly for passing mutable data between control delegates (such as onRetry) and Execute delegates. At present, there is no mechanism within Polly to do this. We could look at this for the future (for example relaxing the read-only constraint on the context collection), but would need time to evaluate the thread-safety aspects. Effectively, it would pass responsibility for managing the thread-safety of context to the library user (it may be as simple as that). Alternatively, if we were not targeting .NET3.5, we could possibly move context to an inherently thread-safe collection such as ConcurrentDictionary.

@YoniH asked if there was any better way to do this than the example presented. My only observation is that, as the example already implicitly closes over someNumber for the Execute delegate, one could implicitly close over someNumber for the onRetry delegate as well (bypassing using the Polly context at all) (although this is probably only practical if policy declaration, and usage, are adjacent, as in the example).

class Program
{
    static void Main(string[] args)
    {
        int someNumber = 0;

        var policy = Policy.Handle<DivideByZeroException>().Retry(3, (exception, retryCount) =>
        {
            someNumber = 17; //Instead of 17, the value would be calculated based on the exception
        });

        policy.Execute(() => DoSomething(someNumber));
    }

    private static void DoSomething(Integer numberArgument)
    {
        Console.WriteLine("The number is {0}", numberArgument.Value);
        Console.WriteLine();

        int x = 0;
        var y = 2/x;
    }
}

Hope that this helps.

We'll leave this issue open, as a general prompt of the possibility to pass mutable data between onRetry and Execute.

Others interested, please +1 if this is an important feature for you

@reisenberger reisenberger changed the title Passing exception and retry count to execution (general: pass mutuable data between onRetry and Execute) Passing exception and retry count to execution (general: pass mutable data between onRetry and Execute) Jan 24, 2016
@reisenberger reisenberger added this to the v5.1 milestone May 2, 2017
@reisenberger
Copy link
Member

The ability to do this is now delivered in Polly v5.1. Polly's Context flowing with the execution becomes mutable, to allow what @YoniH and @hawkunsh requested.

See http://www.thepollyproject.org/2017/05/04/putting-the-context-into-polly/ for details. Shout if any questions/suggestions.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

4 participants