Stop the Cachers from bombing out when the response from the 3rd party api returns an exception or invalid response. #171

This commit is contained in:
tidusjar 2016-04-21 12:10:36 +01:00
parent 54ab4854e6
commit 076a75b82f
12 changed files with 138 additions and 29 deletions

View file

@ -25,7 +25,6 @@
// ************************************************************************/ // ************************************************************************/
#endregion #endregion
using System; using System;
using System.Collections.Generic;
using System.IO; using System.IO;
using System.Xml.Serialization; using System.Xml.Serialization;
@ -34,14 +33,15 @@ using Newtonsoft.Json;
using NLog; using NLog;
using PlexRequests.Api.Interfaces; using PlexRequests.Api.Interfaces;
using PlexRequests.Helpers; using PlexRequests.Helpers.Exceptions;
using RestSharp; using RestSharp;
namespace PlexRequests.Api namespace PlexRequests.Api
{ {
public class ApiRequest : IApiRequest public class ApiRequest : IApiRequest
{ {
private JsonSerializerSettings Settings = new JsonSerializerSettings private readonly JsonSerializerSettings _settings = new JsonSerializerSettings
{ {
NullValueHandling = NullValueHandling.Ignore, NullValueHandling = NullValueHandling.Ignore,
MissingMemberHandling = MissingMemberHandling.Ignore MissingMemberHandling = MissingMemberHandling.Ignore
@ -66,7 +66,8 @@ namespace PlexRequests.Api
if (response.ErrorException != null) if (response.ErrorException != null)
{ {
var message = "Error retrieving response. Check inner details for more info."; var message = "Error retrieving response. Check inner details for more info.";
throw new ApplicationException(message, response.ErrorException); Log.Error(response.ErrorException);
throw new ApiRequestException(message, response.ErrorException);
} }
return response.Data; return response.Data;
@ -80,8 +81,9 @@ namespace PlexRequests.Api
if (response.ErrorException != null) if (response.ErrorException != null)
{ {
Log.Error(response.ErrorException);
var message = "Error retrieving response. Check inner details for more info."; var message = "Error retrieving response. Check inner details for more info.";
throw new ApplicationException(message, response.ErrorException); throw new ApiRequestException(message, response.ErrorException);
} }
return response; return response;
@ -95,8 +97,9 @@ namespace PlexRequests.Api
if (response.ErrorException != null) if (response.ErrorException != null)
{ {
Log.Error(response.ErrorException);
var message = "Error retrieving response. Check inner details for more info."; var message = "Error retrieving response. Check inner details for more info.";
throw new ApplicationException(message, response.ErrorException); throw new ApiRequestException(message, response.ErrorException);
} }
var result = DeserializeXml<T>(response.Content); var result = DeserializeXml<T>(response.Content);
@ -112,12 +115,13 @@ namespace PlexRequests.Api
Log.Trace(response.Content); Log.Trace(response.Content);
if (response.ErrorException != null) if (response.ErrorException != null)
{ {
Log.Error(response.ErrorException);
var message = "Error retrieving response. Check inner details for more info."; var message = "Error retrieving response. Check inner details for more info.";
throw new ApplicationException(message, response.ErrorException); throw new ApiRequestException(message, response.ErrorException);
} }
Log.Trace("Deserialzing Object"); Log.Trace("Deserialzing Object");
var json = JsonConvert.DeserializeObject<T>(response.Content, Settings); var json = JsonConvert.DeserializeObject<T>(response.Content, _settings);
Log.Trace("Finished Deserialzing Object"); Log.Trace("Finished Deserialzing Object");
return json; return json;
@ -133,8 +137,9 @@ namespace PlexRequests.Api
using (var sr = new StringReader(input)) using (var sr = new StringReader(input))
return (T)ser.Deserialize(sr); return (T)ser.Deserialize(sr);
} }
catch (InvalidOperationException) catch (InvalidOperationException e)
{ {
Log.Error(e);
return null; return null;
} }
} }

View file

@ -31,6 +31,7 @@ using Newtonsoft.Json.Linq;
using NLog; using NLog;
using PlexRequests.Api.Interfaces; using PlexRequests.Api.Interfaces;
using PlexRequests.Api.Models.Movie; using PlexRequests.Api.Models.Movie;
using PlexRequests.Helpers.Exceptions;
using RestSharp; using RestSharp;
@ -118,13 +119,22 @@ namespace PlexRequests.Api
public CouchPotatoMovies GetMovies(Uri baseUrl, string apiKey, string[] status) public CouchPotatoMovies GetMovies(Uri baseUrl, string apiKey, string[] status)
{ {
RestRequest request; var request = new RestRequest
request = new RestRequest { Resource = "/api/{apikey}/movie.list?status={status}" }; {
Resource = "/api/{apikey}/movie.list?status={status}"
};
request.AddUrlSegment("apikey", apiKey); request.AddUrlSegment("apikey", apiKey);
request.AddUrlSegment("status", string.Join(",", status)); request.AddUrlSegment("status", string.Join(",", status));
try
return Api.Execute<CouchPotatoMovies>(request, baseUrl); {
return Api.Execute<CouchPotatoMovies>(request, baseUrl);
}
catch (ApiRequestException) // Request error is already logged in the ApiRequest class
{
Log.Error("Error when attempting to GetMovies.");
return new CouchPotatoMovies();
}
} }
} }
} }

View file

@ -26,14 +26,14 @@
#endregion #endregion
using System; using System;
using NLog;
using PlexRequests.Api.Interfaces; using PlexRequests.Api.Interfaces;
using PlexRequests.Api.Models;
using PlexRequests.Api.Models.Plex; using PlexRequests.Api.Models.Plex;
using PlexRequests.Helpers; using PlexRequests.Helpers;
using PlexRequests.Helpers.Exceptions;
using RestSharp; using RestSharp;
using System.Xml;
using System.Collections.Generic;
namespace PlexRequests.Api namespace PlexRequests.Api
{ {
@ -43,6 +43,8 @@ namespace PlexRequests.Api
{ {
Version = AssemblyHelper.GetAssemblyVersion(); Version = AssemblyHelper.GetAssemblyVersion();
} }
private static Logger Log = LogManager.GetCurrentClassLogger();
private static string Version { get; } private static string Version { get; }
public PlexAuthentication SignIn(string username, string password) public PlexAuthentication SignIn(string username, string password)
@ -148,9 +150,16 @@ namespace PlexRequests.Api
AddHeaders(ref request, authToken); AddHeaders(ref request, authToken);
var api = new ApiRequest(); var api = new ApiRequest();
var sections = api.ExecuteXml<PlexLibraries>(request, plexFullHost); try
{
return sections; return api.ExecuteXml<PlexLibraries>(request, plexFullHost);
}
catch (ApiRequestException)
{
Log.Error("There has been a API Exception when attempting to get the Plex Libraries");
return new PlexLibraries();
}
} }
public PlexSearch GetLibrary(string authToken, Uri plexFullHost, string libraryId) public PlexSearch GetLibrary(string authToken, Uri plexFullHost, string libraryId)
@ -161,13 +170,20 @@ namespace PlexRequests.Api
Resource = "library/sections/{libraryId}/all" Resource = "library/sections/{libraryId}/all"
}; };
request.AddUrlSegment("libraryId", libraryId.ToString()); request.AddUrlSegment("libraryId", libraryId);
AddHeaders(ref request, authToken); AddHeaders(ref request, authToken);
var api = new ApiRequest(); var api = new ApiRequest();
var search = api.ExecuteXml<PlexSearch>(request, plexFullHost); try
{
return search; return api.ExecuteXml<PlexSearch>(request, plexFullHost);
}
catch (ApiRequestException)
{
Log.Error("There has been a API Exception when attempting to get the Plex Library");
return new PlexSearch();
}
} }
private void AddHeaders(ref RestRequest request, string authToken) private void AddHeaders(ref RestRequest request, string authToken)

View file

@ -41,6 +41,8 @@ using PlexRequests.Helpers;
using RestSharp; using RestSharp;
using Newtonsoft.Json.Linq; using Newtonsoft.Json.Linq;
using PlexRequests.Helpers.Exceptions;
namespace PlexRequests.Api namespace PlexRequests.Api
{ {
public class SickrageApi : ISickRageApi public class SickrageApi : ISickRageApi
@ -218,7 +220,20 @@ namespace PlexRequests.Api
}; };
request.AddUrlSegment("apiKey", apiKey); request.AddUrlSegment("apiKey", apiKey);
return await Task.Run(() => Api.Execute<SickrageShows>(request, baseUrl)).ConfigureAwait(false); return await Task.Run(
() =>
{
try
{
return Api.Execute<SickrageShows>(request, baseUrl);
}
catch (ApiRequestException)
{
Log.Error("There has been a API exception when Getting the Sickrage shows");
return null;
}
}).ConfigureAwait(false);
} }
} }
} }

View file

@ -38,6 +38,8 @@ using PlexRequests.Helpers;
using RestSharp; using RestSharp;
using Newtonsoft.Json.Linq; using Newtonsoft.Json.Linq;
using PlexRequests.Helpers.Exceptions;
namespace PlexRequests.Api namespace PlexRequests.Api
{ {
public class SonarrApi : ISonarrApi public class SonarrApi : ISonarrApi
@ -128,8 +130,16 @@ namespace PlexRequests.Api
{ {
var request = new RestRequest { Resource = "/api/series", Method = Method.GET }; var request = new RestRequest { Resource = "/api/series", Method = Method.GET };
request.AddHeader("X-Api-Key", apiKey); request.AddHeader("X-Api-Key", apiKey);
try
{
return Api.Execute<List<Series>>(request, baseUrl); return Api.Execute<List<Series>>(request, baseUrl);
}
catch (ApiRequestException)
{
Log.Error("There has been an API exception when getting the Sonarr Series");
return null;
}
} }
} }
} }

View file

@ -50,7 +50,7 @@ namespace PlexRequests.Api
return results.Results; return results.Results;
} }
[Obsolete("Should use TheTvDbApi for TV")] [Obsolete("Should use TvMaze for TV")]
public async Task<List<SearchTv>> SearchTv(string searchTerm) public async Task<List<SearchTv>> SearchTv(string searchTerm)
{ {
var results = await Client.SearchTvShow(searchTerm); var results = await Client.SearchTvShow(searchTerm);
@ -74,7 +74,7 @@ namespace PlexRequests.Api
return movies; return movies;
} }
[Obsolete("Should use TheTvDbApi for TV")] [Obsolete("Should use TvMaze for TV")]
public async Task<TvShow> GetTvShowInformation(int tmdbId) public async Task<TvShow> GetTvShowInformation(int tmdbId)
{ {
var show = await Client.GetTvShow(tmdbId); var show = await Client.GetTvShow(tmdbId);

View file

@ -24,12 +24,15 @@
// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
// ************************************************************************/ // ************************************************************************/
#endregion #endregion
using System;
using PlexRequests.Api.Models.Tv; using PlexRequests.Api.Models.Tv;
using RestSharp; using RestSharp;
namespace PlexRequests.Api namespace PlexRequests.Api
{ {
[Obsolete("Use TVMazeAPP")]
public class TheTvDbApi : TvBase public class TheTvDbApi : TvBase
{ {
public TheTvDbApi() public TheTvDbApi()

View file

@ -0,0 +1,42 @@
#region Copyright
// /************************************************************************
// Copyright (c) 2016 Jamie Rees
// File: ApplicationSettingsException.cs
// Created By: Jamie Rees
//
// Permission is hereby granted, free of charge, to any person obtaining
// a copy of this software and associated documentation files (the
// "Software"), to deal in the Software without restriction, including
// without limitation the rights to use, copy, modify, merge, publish,
// distribute, sublicense, and/or sell copies of the Software, and to
// permit persons to whom the Software is furnished to do so, subject to
// the following conditions:
//
// The above copyright notice and this permission notice shall be
// included in all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
// ************************************************************************/
#endregion
using System;
namespace PlexRequests.Helpers.Exceptions
{
public class ApiRequestException : Exception
{
public ApiRequestException(string message) : base(message)
{
}
public ApiRequestException(string message, Exception innerException) : base(message, innerException)
{
}
}
}

View file

@ -53,6 +53,7 @@
<Compile Include="AssemblyHelper.cs" /> <Compile Include="AssemblyHelper.cs" />
<Compile Include="ByteConverterHelper.cs" /> <Compile Include="ByteConverterHelper.cs" />
<Compile Include="DateTimeHelper.cs" /> <Compile Include="DateTimeHelper.cs" />
<Compile Include="Exceptions\ApiRequestException.cs" />
<Compile Include="Exceptions\ApplicationSettingsException.cs" /> <Compile Include="Exceptions\ApplicationSettingsException.cs" />
<Compile Include="HtmlRemover.cs" /> <Compile Include="HtmlRemover.cs" />
<Compile Include="ICacheProvider.cs" /> <Compile Include="ICacheProvider.cs" />

View file

@ -45,6 +45,7 @@ using PlexRequests.Store.Repository;
using PlexRequests.UI.Models; using PlexRequests.UI.Models;
using PlexRequests.UI.Modules; using PlexRequests.UI.Modules;
using PlexRequests.Helpers; using PlexRequests.Helpers;
using PlexRequests.UI.Helpers;
namespace PlexRequests.UI.Tests namespace PlexRequests.UI.Tests
{ {
@ -121,7 +122,13 @@ namespace PlexRequests.UI.Tests
with.Dependency(PushoverApi.Object); with.Dependency(PushoverApi.Object);
with.Dependency(NotificationService.Object); with.Dependency(NotificationService.Object);
with.Dependency(HeadphonesSettings.Object); with.Dependency(HeadphonesSettings.Object);
with.Dependencies(Cache.Object); with.Dependency(Cache.Object);
with.ApplicationStartup(
(container, pipelines) =>
{
var loc = ServiceLocator.Instance;
loc.SetContainer(container);
});
with.RootPathProvider<TestRootPathProvider>(); with.RootPathProvider<TestRootPathProvider>();
with.RequestStartup((container, pipelines, context) => with.RequestStartup((container, pipelines, context) =>
{ {

View file

@ -77,6 +77,9 @@ namespace PlexRequests.UI.Tests
with.RootPathProvider<TestRootPathProvider>(); with.RootPathProvider<TestRootPathProvider>();
}); });
var loc = ServiceLocator.Instance;
loc.SetContainer(TinyIoCContainer.Current);
bootstrapper.WithSession(new Dictionary<string, object>()); bootstrapper.WithSession(new Dictionary<string, object>());
var browser = new Browser(bootstrapper); var browser = new Browser(bootstrapper);

View file

@ -49,7 +49,6 @@ using PlexRequests.Store;
using PlexRequests.UI.Helpers; using PlexRequests.UI.Helpers;
using PlexRequests.UI.Models; using PlexRequests.UI.Models;
using System.Threading.Tasks; using System.Threading.Tasks;
using TMDbLib.Objects.Search;
using PlexRequests.Api.Models.Tv; using PlexRequests.Api.Models.Tv;
using TMDbLib.Objects.General; using TMDbLib.Objects.General;
@ -71,7 +70,6 @@ namespace PlexRequests.UI.Modules
CpService = cpSettings; CpService = cpSettings;
PrService = prSettings; PrService = prSettings;
MovieApi = new TheMovieDbApi(); MovieApi = new TheMovieDbApi();
TvApi = new TheTvDbApi();
Cache = cache; Cache = cache;
Checker = checker; Checker = checker;
CpCacher = cpCacher; CpCacher = cpCacher;
@ -108,7 +106,6 @@ namespace PlexRequests.UI.Modules
private INotificationService NotificationService { get; } private INotificationService NotificationService { get; }
private ICouchPotatoApi CouchPotatoApi { get; } private ICouchPotatoApi CouchPotatoApi { get; }
private ISonarrApi SonarrApi { get; } private ISonarrApi SonarrApi { get; }
private TheTvDbApi TvApi { get; }
private ISickRageApi SickrageApi { get; } private ISickRageApi SickrageApi { get; }
private IRequestService RequestService { get; } private IRequestService RequestService { get; }
private ICacheProvider Cache { get; } private ICacheProvider Cache { get; }