{"action":"created","issue":{"url":"https://api.github.com/repos/App-vNext/Polly/issues/111","repository_url":"https://api.github.com/repos/App-vNext/Polly","labels_url":"https://api.github.com/repos/App-vNext/Polly/issues/111/labels{/name}","comments_url":"https://api.github.com/repos/App-vNext/Polly/issues/111/comments","events_url":"https://api.github.com/repos/App-vNext/Polly/issues/111/events","html_url":"https://github.com/App-vNext/Polly/issues/111","id":157672426,"number":111,"title":"WaitAndRetryAsync fails to wait and retry","user":{"login":"jeroenwo","id":13014081,"avatar_url":"https://avatars.githubusercontent.com/u/13014081?v=3","gravatar_id":"","url":"https://api.github.com/users/jeroenwo","html_url":"https://github.com/jeroenwo","followers_url":"https://api.github.com/users/jeroenwo/followers","following_url":"https://api.github.com/users/jeroenwo/following{/other_user}","gists_url":"https://api.github.com/users/jeroenwo/gists{/gist_id}","starred_url":"https://api.github.com/users/jeroenwo/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/jeroenwo/subscriptions","organizations_url":"https://api.github.com/users/jeroenwo/orgs","repos_url":"https://api.github.com/users/jeroenwo/repos","events_url":"https://api.github.com/users/jeroenwo/events{/privacy}","received_events_url":"https://api.github.com/users/jeroenwo/received_events","type":"User","site_admin":false},"labels":[],"state":"open","locked":false,"assignee":null,"milestone":null,"comments":1,"created_at":"2016-05-31T13:32:25Z","updated_at":"2016-05-31T18:05:13Z","closed_at":null,"body":"Hi,\r\n\r\nI am trying to use Polly in an asynchronous fashion. I have a console application which imports data. The data is upserted async to DocumentDB.\r\n\r\nThis synchronous way works:\r\n```\r\nstatic void Main(string[] args)\r\n{\r\n    ImportDataTransiently();\r\n}\r\n\r\nprivate static void ImportDataTransiently()\r\n{\r\n    Policy\r\n        .Handle<AggregateException>()\r\n        .WaitAndRetry(5,\r\n            retryAttempt => TimeSpan.FromSeconds(Math.Pow(2, retryAttempt)),\r\n            (ex, timeSpan) =>\r\n            {\r\n                Console.WriteLine($\"Exception: {ex.Message}\");\r\n                Console.WriteLine($\"Retrying in {timeSpan.Seconds} seconds\");\r\n            })\r\n        .Execute(() => UpsertDocumentAsync(documentCollectionLink, person).Wait());\r\n}\r\n```\r\n\r\nThis does not, the exception bubbles to the Task.Run. I would have expected the exception to be caught by Polly and retried:\r\n```\r\nstatic void Main(string[] args)\r\n{\r\n    Task.Run(async () => await ImportDataTransiently()).Wait();\r\n}\r\n\r\nprivate static async Task ImportDataTransiently()\r\n{\r\n    await Policy\r\n        .Handle<AggregateException>()\r\n        .WaitAndRetryAsync(5,\r\n            retryAttempt => TimeSpan.FromSeconds(Math.Pow(2, retryAttempt)),\r\n            (ex, timeSpan) =>\r\n            {\r\n                Console.WriteLine($\"Exception: {ex.Message}\");\r\n                Console.WriteLine($\"Retrying in {timeSpan.Seconds} seconds\");\r\n            })\r\n        .ExecuteAsync(async () => await UpsertDocumentAsync(documentCollectionLink, person));\r\n}\r\n```\r\nAnd the async method:\r\n```\r\nprivate static async Task UpsertDocumentAsync(Uri documentCollectionLink, TrajectoryPerson person)\r\n{\r\n    using (var documentClient = new DocumentClient(ConfigurationData.DocumentDbUri, ConfigurationData.DocumentDbKey))\r\n    {\r\n        var response = await documentClient.UpsertDocumentAsync(documentCollectionLink, person);\r\n\r\n        Console.WriteLine($\"{person.Name}: upsert of document consumed {response.RequestCharge} request units\");\r\n    }\r\n}\r\n```\r\nWhat am I doing wrong?"},"comment":{"url":"https://api.github.com/repos/App-vNext/Polly/issues/comments/222770755","html_url":"https://github.com/App-vNext/Polly/issues/111#issuecomment-222770755","issue_url":"https://api.github.com/repos/App-vNext/Polly/issues/111","id":222770755,"user":{"login":"reisenberger","id":9608723,"avatar_url":"https://avatars.githubusercontent.com/u/9608723?v=3","gravatar_id":"","url":"https://api.github.com/users/reisenberger","html_url":"https://github.com/reisenberger","followers_url":"https://api.github.com/users/reisenberger/followers","following_url":"https://api.github.com/users/reisenberger/following{/other_user}","gists_url":"https://api.github.com/users/reisenberger/gists{/gist_id}","starred_url":"https://api.github.com/users/reisenberger/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/reisenberger/subscriptions","organizations_url":"https://api.github.com/users/reisenberger/orgs","repos_url":"https://api.github.com/users/reisenberger/repos","events_url":"https://api.github.com/users/reisenberger/events{/privacy}","received_events_url":"https://api.github.com/users/reisenberger/received_events","type":"User","site_admin":false},"created_at":"2016-05-31T18:05:13Z","updated_at":"2016-05-31T18:05:13Z","body":"Hey @jeroenwo !  I am travelling at the moment and haven't been able to test your code, but I think your code needs to take account of the different ways that `await Task` and `Task.Wait()` propagate exceptions.  \r\n\r\nWhen you wait synchronously on a `Task` (such as with `.Wait()` or `.Result`), exceptions thrown are always wrapped in an `AggregateException`.  However, when you `await` a `Task`, original exceptions are rethrown at the `await` (not wrapped in an `AggregateException`).  For a detailed discussion, see [Stephen Toub on “Task.Result” vs “await task” Exception handling](http://blogs.msdn.com/b/pfxteam/archive/2011/09/28/10217876.aspx).\r\n\r\nIn the async version of your code, you only `.Handle<AggregateException>()`.  But your inner call `documentClient.UpsertDocumentAsync(...)` is presumably throwing some other exception (for discussion let's call it a `CannotUpsertException`).  Since the policy is only declared to handle `AggregateException`s, it doesn't handle the `CannotUpsertException`, and immediately rethrows it without retries, as you are observing.  \r\n\r\nThen (in the code you posted), within `Main(...)` you eventually have a `.Wait()`, which causes the `CannotUpsertException` rethrown up the `await` call stack, to be wrapped in an `AggregateException` _at the point of that .Wait() only_ (perhaps making it look superficially as if an `AggregateException` was originally thrown all along - which I'm assuming is not the case).\r\n\r\nSo to fix: in the async version, just change `.Handle<AggregateException>()` to `.Handle<CannotUpsertException>()` (or whatever the inner work is throwing). \r\n\r\nIf you have a number of possible exceptions you want the policy to handle, use Polly's `.Or<AnotherException>()` syntax.\r\n\r\nPlease let us know if this solves the issue for you!  (Or equally if not! - as I'm travelling, I've only had the chance to run your code through the virtual machine in my head... :smiley: )"}}
{"actor":{"display_login":"reisenberger"}}