From 2b82f256d2807279066e9972406f00a230a54810 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 15 Mar 2017 20:08:12 +0900 Subject: [PATCH] More resilient API cancel/fail logic. --- osu.Game/Online/API/APIRequest.cs | 41 +++++++++++++++++++++++-------- 1 file changed, 31 insertions(+), 10 deletions(-) diff --git a/osu.Game/Online/API/APIRequest.cs b/osu.Game/Online/API/APIRequest.cs index 43c039eb1e..23268a9ca9 100644 --- a/osu.Game/Online/API/APIRequest.cs +++ b/osu.Game/Online/API/APIRequest.cs @@ -60,15 +60,18 @@ namespace osu.Game.Online.API private bool cancelled; + private Action pendingFailure; + public void Perform(APIAccess api) { - if (cancelled) return; + this.api = api; + + if (checkAndProcessFailure()) + return; if (startTime == null) startTime = DateTime.Now.TotalMilliseconds(); - this.api = api; - if (remainingTime <= 0) throw new TimeoutException(@"API request timeout hit"); @@ -76,10 +79,16 @@ namespace osu.Game.Online.API WebRequest.RetryCount = 0; WebRequest.Headers[@"Authorization"] = $@"Bearer {api.AccessToken}"; - WebRequest.BlockingPerform(); + if (checkAndProcessFailure()) + return; - if (WebRequest.Completed) - api.Scheduler.Add(delegate { Success?.Invoke(); }); + if (!WebRequest.Aborted) //could have been aborted by a Cancel() call + WebRequest.BlockingPerform(); + + if (checkAndProcessFailure()) + return; + + api.Scheduler.Add(delegate { Success?.Invoke(); }); } public void Cancel() => Fail(new OperationCanceledException(@"Request cancelled")); @@ -89,10 +98,22 @@ namespace osu.Game.Online.API cancelled = true; WebRequest?.Abort(); - api.Scheduler.Add(delegate - { - Failure?.Invoke(e); - }); + + pendingFailure = () => Failure?.Invoke(e); + checkAndProcessFailure(); + } + + /// + /// Checked for cancellation or error. Also queues up the Failed event if we can. + /// + /// Whether we are in a failed or cancelled state. + private bool checkAndProcessFailure() + { + if (api == null || pendingFailure == null) return cancelled; + + api.Scheduler.Add(pendingFailure); + pendingFailure = null; + return true; } }