From bef36f37a5587615acbf802ee4fd6540203bcc81 Mon Sep 17 00:00:00 2001 From: Flutterish Date: Wed, 2 Feb 2022 13:40:03 +0100 Subject: [PATCH] log unhandled net errors --- .../API/APIRuleset.cs | 16 +++---- .../API/APIUser.cs | 13 +++-- .../API/RurusettoAPI.cs | 47 ++++++++++++++----- .../RulesetDownloadManager.cs | 6 +-- .../RulesetIdentityManager.cs | 8 +++- .../UI/Info/InfoTab.cs | 16 +++---- .../UI/Listing/DrawableListingEntry.cs | 6 +-- .../UI/Overlay/RurusettoOverlayHeader.cs | 4 +- .../UI/Users/DrawableRurusettoUser.cs | 2 +- .../UI/Users/UserTab.cs | 6 +-- 10 files changed, 76 insertions(+), 48 deletions(-) diff --git a/osu.Game.Rulesets.RurusettoAddon/API/APIRuleset.cs b/osu.Game.Rulesets.RurusettoAddon/API/APIRuleset.cs index 8f5c87b..e746745 100644 --- a/osu.Game.Rulesets.RurusettoAddon/API/APIRuleset.cs +++ b/osu.Game.Rulesets.RurusettoAddon/API/APIRuleset.cs @@ -100,7 +100,7 @@ static Drawable createDefault () { FillMode = FillMode.Fit, Texture = logo } ); - }, () => { + }, e => { failure?.Invoke( createDefault() ); } ); } @@ -109,7 +109,7 @@ static Drawable createDefault () { } } - public void RequestDetail ( Action success, Action? failure = null ) { + public void RequestDetail ( Action success, Action? failure = null ) { if ( Source == Source.Web && !string.IsNullOrWhiteSpace( Slug ) && API != null ) { API.RequestRulesetDetail( Slug, success, failure ); // TODO this on failures @@ -139,7 +139,7 @@ public void RequestDetail ( Action success, Action? failure = nul } } - public void RequestSubpages ( Action> success, Action? failure = null ) { + public void RequestSubpages ( Action> success, Action? failure = null ) { if ( Source == Source.Web && API != null && !string.IsNullOrWhiteSpace( Slug ) ) { API.RequestSubpageListing( Slug, success, failure ); } @@ -163,18 +163,18 @@ public void FlushSubpages () { // NOTE this doesnt refresh changlog and main } } - public void RequestSubpage ( string subpageSlug, Action success, Action? failure = null ) { + public void RequestSubpage ( string subpageSlug, Action success, Action? failure = null ) { if ( Source == Source.Web && API != null && !string.IsNullOrWhiteSpace( Slug ) && !string.IsNullOrWhiteSpace( subpageSlug ) ) { API.RequestSubpage( Slug, subpageSlug, success, failure ); } else { - failure?.Invoke(); + failure?.Invoke( null ); } } - public void RequestDarkCover ( Action success, Action? failure = null ) { + public void RequestDarkCover ( Action success, Action? failure = null ) { if ( API is null ) { - failure?.Invoke(); + failure?.Invoke( null ); } else { RequestDetail( detail => { @@ -213,7 +213,7 @@ public IEnumerable GenerateTags ( RulesetDetail detail, bool large } public override string ToString () - => $"{Name}"; + => $"{Name} [Source {Source}] [{(Source is Source.Web ? $"Slug {Slug}" : $"Path {LocalPath}")}]"; } public enum Source { diff --git a/osu.Game.Rulesets.RurusettoAddon/API/APIUser.cs b/osu.Game.Rulesets.RurusettoAddon/API/APIUser.cs index 740cd73..17d1735 100644 --- a/osu.Game.Rulesets.RurusettoAddon/API/APIUser.cs +++ b/osu.Game.Rulesets.RurusettoAddon/API/APIUser.cs @@ -27,7 +27,7 @@ public static APIUser Local ( RurusettoAPI API ) { public bool HasProfile { get; private set; } - public void RequestDetail ( Action success, Action? failure = null ) { + public void RequestDetail ( Action success, Action? failure = null ) { if ( Source == Source.Web && API != null ) { API.RequestUserProfile( ID, success, failure ); } @@ -36,11 +36,11 @@ public void RequestDetail ( Action success, Action? failure = null } } - public void RequestProfilePicture ( Action success, Action? failure = null ) { - void requestDefault () { + public void RequestProfilePicture ( Action success, Action? failure = null ) { + void requestDefault ( Exception? e = null ) { if ( API != null ) { - API.RequestImage( StaticAPIResource.DefaultProfileImage, success, failure: () => { - failure?.Invoke(); + API.RequestImage( StaticAPIResource.DefaultProfileImage, success, failure: e => { + failure?.Invoke( e ); } ); } } @@ -59,5 +59,8 @@ void requestDefault () { requestDefault(); } } + + public override string ToString () + => Source is Source.Web ? $"User with ID = {ID}" : $"Local user"; } } diff --git a/osu.Game.Rulesets.RurusettoAddon/API/RurusettoAPI.cs b/osu.Game.Rulesets.RurusettoAddon/API/RurusettoAPI.cs index db3d5c9..be934e5 100644 --- a/osu.Game.Rulesets.RurusettoAddon/API/RurusettoAPI.cs +++ b/osu.Game.Rulesets.RurusettoAddon/API/RurusettoAPI.cs @@ -2,6 +2,7 @@ using osu.Framework.Bindables; using osu.Framework.Graphics; using osu.Framework.Graphics.Textures; +using osu.Framework.Logging; using SixLabors.ImageSharp; using SixLabors.ImageSharp.PixelFormats; using System; @@ -23,10 +24,10 @@ public RurusettoAPI () { Address.ValueChanged += _ => FlushAllCaches(); } - private async void queue ( Task task, Action? success = null, Action? failure = null, Action? cancelled = null ) { + private async void queue ( Task task, Action? success = null, Action? failure = null, Action? cancelled = null ) { if ( task.Status == TaskStatus.RanToCompletion ) { if ( task.Result is null ) - failure?.Invoke(); + failure?.Invoke( task.Exception ); else success?.Invoke( task.Result ); } @@ -39,15 +40,15 @@ private async void queue ( Task task, Action? success = null, Action? if ( address != Address.Value ) cancelled?.Invoke(); else if ( value is null ) - failure?.Invoke(); + failure?.Invoke( null ); else success?.Invoke( value ); } ); } - catch ( Exception ) { + catch ( Exception e ) { Schedule( () => { if ( address == Address.Value ) - failure?.Invoke(); + failure?.Invoke( e ); else cancelled?.Invoke(); } ); @@ -55,8 +56,18 @@ private async void queue ( Task task, Action? success = null, Action? } } + public void LogFailure ( string message, Exception? exception = null ) { + message = $"Unhandled Rurusetto Addon Error: `{message}` - API Address: `{Address.Value}`"; + if ( exception is null ) + Logger.Log( message, LoggingTarget.Network, LogLevel.Error ); + else + Logger.Error( exception, message, LoggingTarget.Network ); + } + private Task?>? listingCache = null; - public void RequestRulesetListing ( Action>? success = null, Action? failure = null, Action? cancelled = null ) { + public void RequestRulesetListing ( Action>? success = null, Action? failure = null, Action? cancelled = null ) { + failure ??= e => LogFailure( $"Could not retrieve ruleset listing", e ); + queue( listingCache ??= requestRulesetListing(), success, failure, cancelled ); } private async Task?> requestRulesetListing () { @@ -68,7 +79,9 @@ public void FlushRulesetListingCache () { } private Dictionary> rulesetDetailCache = new(); - public void RequestRulesetDetail ( string slug, Action? success = null, Action? failure = null ) { + public void RequestRulesetDetail ( string slug, Action? success = null, Action? failure = null ) { + failure ??= e => LogFailure( $"Could not retrieve ruleset detail for {slug}", e ); + if ( !rulesetDetailCache.TryGetValue( slug, out var detail ) ) { rulesetDetailCache.Add( slug, detail = requestRulesetDetail( slug ) ); } @@ -87,7 +100,9 @@ public void FlushRulesetDetailCache () { } private Dictionary?>> subpageListingCache = new(); - public void RequestSubpageListing ( string slug, Action>? success = null, Action? failure = null ) { + public void RequestSubpageListing ( string slug, Action>? success = null, Action? failure = null ) { + failure ??= e => LogFailure( $"Could not retrieve subpage listing for {slug}", e ); + if ( !subpageListingCache.TryGetValue( slug, out var listing ) ) { subpageListingCache.TryAdd( slug, listing = requestSubpageListing( slug ) ); } @@ -106,7 +121,9 @@ public void FlushSubpageListingCache () { } private Dictionary> subpageCache = new(); - public void RequestSubpage ( string rulesetSlug, string subpageSlug, Action? success = null, Action? failure = null ) { + public void RequestSubpage ( string rulesetSlug, string subpageSlug, Action? success = null, Action? failure = null ) { + failure ??= e => LogFailure( $"Could not retrieve subpage {subpageSlug} for ruleset {rulesetSlug}", e ); + if ( !subpageCache.TryGetValue( $"{rulesetSlug}/{subpageSlug}", out var listing ) ) { subpageCache.TryAdd( $"{rulesetSlug}/{subpageSlug}", listing = requestSubpage( rulesetSlug, subpageSlug ) ); } @@ -130,7 +147,9 @@ public void FlushSubpageCache () { } private Dictionary> userCache = new(); - public void RequestUserProfile ( int id, Action? success = null, Action? failure = null ) { + public void RequestUserProfile ( int id, Action? success = null, Action? failure = null ) { + failure ??= e => LogFailure( $"Could not retrieve user profile with ID = {id}", e ); + if ( !userCache.TryGetValue( id, out var user ) ) { userCache.TryAdd( id, user = requestUserProfile( id ) ); } @@ -149,7 +168,9 @@ public void FlushUserProfileCache () { } private Dictionary> mediaTextureCache = new(); - public void RequestImage ( string uri, Action? success = null, Action? failure = null ) { + public void RequestImage ( string uri, Action? success = null, Action? failure = null ) { + failure ??= e => LogFailure( $"Could not retrieve image at `{uri}`", e ); + if ( !mediaTextureCache.TryGetValue( uri, out var task ) ) { mediaTextureCache.TryAdd( uri, task = requestImage( uri ) ); } @@ -176,7 +197,9 @@ public void FlushImageCache () { mediaTextureCache.Clear(); } - public void RequestImage ( StaticAPIResource resource, Action? success = null, Action? failure = null ) { + public void RequestImage ( StaticAPIResource resource, Action? success = null, Action? failure = null ) { + failure ??= e => LogFailure( $"Could not retrieve static resource {resource} at {resource.GetURI()}", e ); + RequestImage( resource.GetURI(), success, failure ); } public void FlushImageCache ( StaticAPIResource resource ) { diff --git a/osu.Game.Rulesets.RurusettoAddon/RulesetDownloadManager.cs b/osu.Game.Rulesets.RurusettoAddon/RulesetDownloadManager.cs index 3f99bc8..8cce3eb 100644 --- a/osu.Game.Rulesets.RurusettoAddon/RulesetDownloadManager.cs +++ b/osu.Game.Rulesets.RurusettoAddon/RulesetDownloadManager.cs @@ -63,7 +63,7 @@ public void CheckAvailability ( APIRuleset ruleset ) { availability.Value |= Availability.AvailableOnline; else availability.Value |= Availability.NotAvailableOnline; - }, failure: () => { + }, failure: _ => { availability.Value |= Availability.NotAvailableOnline; } ); @@ -124,10 +124,10 @@ private void createDownloadTask ( APIRuleset ruleset, TaskType type, DownloadSta tasks[ ruleset ] = task with { Source = filename }; GetStateBindable( ruleset ).Value = finishedState; - }, failure: () => { + }, failure: e => { if ( wasTaskCancelled( ruleset, task ) ) return; tasks.Remove( ruleset ); - // TODO report this + API.LogFailure( $"Download manager could not retrieve detail for {ruleset}", e ); } ); } diff --git a/osu.Game.Rulesets.RurusettoAddon/RulesetIdentityManager.cs b/osu.Game.Rulesets.RurusettoAddon/RulesetIdentityManager.cs index 3f9329b..499bab4 100644 --- a/osu.Game.Rulesets.RurusettoAddon/RulesetIdentityManager.cs +++ b/osu.Game.Rulesets.RurusettoAddon/RulesetIdentityManager.cs @@ -82,8 +82,12 @@ private async Task getIdentities () { listing = result; hasWeb = true; task.SetResult(); - }, failure: () => task.SetResult(), /* TODO report this */ - cancelled: () => task.SetResult() + + }, failure: e => { + API.LogFailure( $"Identity manager could not retrieve ruleset listing", e ); + task.SetResult(); + }, + cancelled: () => task.SetResult() ); await task.Task; diff --git a/osu.Game.Rulesets.RurusettoAddon/UI/Info/InfoTab.cs b/osu.Game.Rulesets.RurusettoAddon/UI/Info/InfoTab.cs index d6e8b18..3b636ee 100644 --- a/osu.Game.Rulesets.RurusettoAddon/UI/Info/InfoTab.cs +++ b/osu.Game.Rulesets.RurusettoAddon/UI/Info/InfoTab.cs @@ -196,12 +196,12 @@ protected override void LoadContent () { if ( !isCoverLoaded ) { cover.Texture = texture; } - }, failure: () => { /* TODO report this */ } ); + } ); ruleset.RequestDarkCover( texture => { isCoverLoaded = true; cover.Texture = texture; - }, failure: () => { /* TODO report this */ } ); + } ); loadHeader(); } @@ -236,7 +236,7 @@ void addDefaultSubpages () { subpageTabControl.Current.Value = main; Overlay.FinishLoadiong( this ); - }, failure: () => { + }, failure: e => { addDefaultSubpages(); info.Add( new RequestFailedDrawable { @@ -280,7 +280,7 @@ void loadCurrentPage () { markdown.Text = subpage.Content ?? ""; Overlay.FinishLoadiong( this ); - }, failure: () => { + }, failure: e => { content.Insert( -1, new Container { Padding = new MarginPadding { Horizontal = -32 }, AutoSizeAxes = Axes.Y, @@ -325,8 +325,8 @@ void loadMainPage () { }, true ); Overlay.FinishLoadiong( this ); - }, failure: () => { - // TODO report this + }, failure: e => { + API.LogFailure( $"Could not retrieve detail for {ruleset}", e ); Overlay.FinishLoadiong( this ); } ); } @@ -371,8 +371,8 @@ void loadHeader () { } ); Overlay.FinishLoadiong( this ); - }, failure: () => { - // TODO report this + }, failure: e => { + API.LogFailure( $"Could not retrieve detail for {ruleset}", e ); Overlay.FinishLoadiong( this ); } ); } diff --git a/osu.Game.Rulesets.RurusettoAddon/UI/Listing/DrawableListingEntry.cs b/osu.Game.Rulesets.RurusettoAddon/UI/Listing/DrawableListingEntry.cs index 1137f64..2013040 100644 --- a/osu.Game.Rulesets.RurusettoAddon/UI/Listing/DrawableListingEntry.cs +++ b/osu.Game.Rulesets.RurusettoAddon/UI/Listing/DrawableListingEntry.cs @@ -187,16 +187,16 @@ private void load ( OverlayColourProvider colours, LocalisationManager localisat if ( !isCoverLoaded ) { cover.Texture = texture; } - }, failure: () => { /* TODO report this */ } ); + } ); Ruleset.RequestDarkCover( texture => { cover.Texture = texture; isCoverLoaded = true; - }, failure: () => { /* TODO report this */ } ); + } ); Ruleset.RequestDetail( detail => { Tags.AddRange( Ruleset.GenerateTags( detail ) ); - }, failure: () => { /* TODO report this */ } ); + } ); Add( new HoverClickSounds() ); } diff --git a/osu.Game.Rulesets.RurusettoAddon/UI/Overlay/RurusettoOverlayHeader.cs b/osu.Game.Rulesets.RurusettoAddon/UI/Overlay/RurusettoOverlayHeader.cs index e4bb27f..66cc033 100644 --- a/osu.Game.Rulesets.RurusettoAddon/UI/Overlay/RurusettoOverlayHeader.cs +++ b/osu.Game.Rulesets.RurusettoAddon/UI/Overlay/RurusettoOverlayHeader.cs @@ -29,7 +29,7 @@ public RurusettoOverlayHeader () { ruleset.RequestDarkCover( texture => { background.SetCover( texture ); - }, failure: () => { /* TODO report this */ } ); + } ); } else if ( v.NewValue is APIUser user ) { TabControl.AddItem( selectedTab = $"user" ); @@ -41,7 +41,7 @@ public RurusettoOverlayHeader () { TabControl.AddItem( selectedTab = $"{detail.Username} (user)" ); Current.Value = selectedTab; } - }, failure: () => { /* TODO report this */ } ); + } ); } else { Current.Value = listingText; diff --git a/osu.Game.Rulesets.RurusettoAddon/UI/Users/DrawableRurusettoUser.cs b/osu.Game.Rulesets.RurusettoAddon/UI/Users/DrawableRurusettoUser.cs index 0be7ef2..2267cb4 100644 --- a/osu.Game.Rulesets.RurusettoAddon/UI/Users/DrawableRurusettoUser.cs +++ b/osu.Game.Rulesets.RurusettoAddon/UI/Users/DrawableRurusettoUser.cs @@ -168,7 +168,7 @@ protected override void LoadComplete () { this.profile = profile; usernameText = profile.Username ?? ""; username.Text = profile.Username ?? Localisation.Strings.UserUnknown; - }, failure: () => { /* TODO report this */ } ); + } ); user.RequestProfilePicture( texture => { pfp.Texture = texture; diff --git a/osu.Game.Rulesets.RurusettoAddon/UI/Users/UserTab.cs b/osu.Game.Rulesets.RurusettoAddon/UI/Users/UserTab.cs index fe50051..fcda16c 100644 --- a/osu.Game.Rulesets.RurusettoAddon/UI/Users/UserTab.cs +++ b/osu.Game.Rulesets.RurusettoAddon/UI/Users/UserTab.cs @@ -11,11 +11,9 @@ protected override void LoadContent () { Add( new DrawableRurusettoUser( User, false ) { Height = 80 } ); User.RequestDetail( profile => { - OnContentLoaded(); - }, failure: () => { - // TODO report this - + }, failure: e => { + API.LogFailure( $"Could not retrieve profile for {User}", e ); OnContentLoaded(); } ); }