Some memory management improvements

pull/1872/head
tidusjar 7 years ago
parent 059b083359
commit 6ac9da8bed

@ -26,8 +26,7 @@ namespace Ombi.Api.Plex
/// This is for authenticating users credentials with Plex
/// <para>NOTE: Plex "Managed" users do not work</para>
/// </summary>
/// <param name="username"></param>
/// <param name="password"></param>
/// <param name="user"></param>
/// <returns></returns>
public async Task<PlexAuthentication> SignIn(UserRequest user)
{

@ -1,32 +1,23 @@
using System;
using System.IO;
using System.IO;
using System.Net.Http;
using System.Net.Http.Headers;
using System.Security.Authentication;
using System.Threading.Tasks;
using System.Xml.Serialization;
using Microsoft.Extensions.Caching.Memory;
using Newtonsoft.Json;
using Microsoft.Extensions.Logging;
using Ombi.Core.Settings;
using Ombi.Helpers;
using Ombi.Settings.Settings.Models;
namespace Ombi.Api
{
public class Api : IApi
{
public Api(ILogger<Api> log, ISettingsService<OmbiSettings> s, ICacheService cache, IOmbiHttpClient client)
public Api(ILogger<Api> log, IOmbiHttpClient client)
{
Logger = log;
_settings = s;
_cache = cache;
_client = client;
}
private ILogger<Api> Logger { get; }
private readonly ISettingsService<OmbiSettings> _settings;
private readonly ICacheService _cache;
private readonly IOmbiHttpClient _client;
private static readonly JsonSerializerSettings Settings = new JsonSerializerSettings
@ -38,41 +29,29 @@ namespace Ombi.Api
{
using (var httpRequestMessage = new HttpRequestMessage(request.HttpMethod, request.FullUri))
{
// Add the Json Body
if (request.JsonBody != null)
AddHeadersBody(request, httpRequestMessage);
var httpResponseMessage = await _client.SendAsync(httpRequestMessage);
if (!httpResponseMessage.IsSuccessStatusCode)
{
httpRequestMessage.Content = new JsonContent(request.JsonBody);
httpRequestMessage.Content.Headers.ContentType = new MediaTypeHeaderValue("application/json"); // Emby connect fails if we have the charset in the header
LogError(request, httpResponseMessage);
}
// Add headers
foreach (var header in request.Headers)
// do something with the response
var receivedString = await httpResponseMessage.Content.ReadAsStringAsync();
if (request.ContentType == ContentType.Json)
{
httpRequestMessage.Headers.Add(header.Key, header.Value);
request.OnBeforeDeserialization?.Invoke(receivedString);
return JsonConvert.DeserializeObject<T>(receivedString, Settings);
}
using (var httpResponseMessage = await _client.SendAsync(httpRequestMessage))
else
{
if (!httpResponseMessage.IsSuccessStatusCode)
{
LogError(request, httpResponseMessage);
}
// do something with the response
var data = httpResponseMessage.Content;
var receivedString = await data.ReadAsStringAsync();
if (request.ContentType == ContentType.Json)
{
request.OnBeforeDeserialization?.Invoke(receivedString);
return JsonConvert.DeserializeObject<T>(receivedString, Settings);
}
else
{
// XML
XmlSerializer serializer = new XmlSerializer(typeof(T));
StringReader reader = new StringReader(receivedString);
var value = (T)serializer.Deserialize(reader);
return value;
}
// XML
XmlSerializer serializer = new XmlSerializer(typeof(T));
StringReader reader = new StringReader(receivedString);
var value = (T)serializer.Deserialize(reader);
return value;
}
}
@ -82,30 +61,17 @@ namespace Ombi.Api
{
using (var httpRequestMessage = new HttpRequestMessage(request.HttpMethod, request.FullUri))
{
// Add the Json Body
if (request.JsonBody != null)
{
httpRequestMessage.Content = new JsonContent(request.JsonBody);
}
AddHeadersBody(request, httpRequestMessage);
// Add headers
foreach (var header in request.Headers)
var httpResponseMessage = await _client.SendAsync(httpRequestMessage);
if (!httpResponseMessage.IsSuccessStatusCode)
{
httpRequestMessage.Headers.Add(header.Key, header.Value);
LogError(request, httpResponseMessage);
}
using (var httpResponseMessage = await _client.SendAsync(httpRequestMessage))
{
if (!httpResponseMessage.IsSuccessStatusCode)
{
LogError(request, httpResponseMessage);
}
// do something with the response
var data = httpResponseMessage.Content;
// do something with the response
var data = httpResponseMessage.Content;
return await data.ReadAsStringAsync();
}
return await data.ReadAsStringAsync();
}
}
@ -114,25 +80,29 @@ namespace Ombi.Api
{
using (var httpRequestMessage = new HttpRequestMessage(request.HttpMethod, request.FullUri))
{
// Add the Json Body
if (request.JsonBody != null)
AddHeadersBody(request, httpRequestMessage);
var httpResponseMessage = await _client.SendAsync(httpRequestMessage);
if (!httpResponseMessage.IsSuccessStatusCode)
{
httpRequestMessage.Content = new JsonContent(request.JsonBody);
LogError(request, httpResponseMessage);
}
}
}
// Add headers
foreach (var header in request.Headers)
{
httpRequestMessage.Headers.Add(header.Key, header.Value);
private static void AddHeadersBody(Request request, HttpRequestMessage httpRequestMessage)
{
// Add the Json Body
if (request.JsonBody != null)
{
httpRequestMessage.Content = new JsonContent(request.JsonBody);
httpRequestMessage.Content.Headers.ContentType =
new MediaTypeHeaderValue("application/json"); // Emby connect fails if we have the charset in the header
}
}
using (var httpResponseMessage = await _client.SendAsync(httpRequestMessage))
{
if (!httpResponseMessage.IsSuccessStatusCode)
{
LogError(request, httpResponseMessage);
}
}
// Add headers
foreach (var header in request.Headers)
{
httpRequestMessage.Headers.Add(header.Key, header.Value);
}
}

@ -50,6 +50,7 @@ using Ombi.Store.Repository.Requests;
using Ombi.Updater;
using PlexContentCacher = Ombi.Schedule.Jobs.Plex;
using Ombi.Api.Telegram;
using Ombi.Schedule.Jobs.Plex.Interfaces;
using Ombi.Schedule.Jobs.SickRage;
namespace Ombi.DependencyInjection
@ -85,7 +86,7 @@ namespace Ombi.DependencyInjection
public static void RegisterApi(this IServiceCollection services)
{
services.AddTransient<IApi, Api.Api>();
services.AddSingleton<IApi, Api.Api>();
services.AddSingleton<IOmbiHttpClient, OmbiHttpClient>(); // https://blogs.msdn.microsoft.com/alazarev/2017/12/29/disposable-finalizers-and-httpclient/
services.AddTransient<IMovieDbApi, Api.TheMovieDb.TheMovieDbApi>();
services.AddTransient<IPlexApi, PlexApi>();

@ -2,6 +2,7 @@
using System.Linq;
using System.Reflection;
using Hangfire;
using Microsoft.Extensions.DependencyInjection;
namespace Ombi.Schedule
{
@ -15,8 +16,13 @@ namespace Ombi.Schedule
public override object ActivateJob(Type type)
{
var i = type.GetTypeInfo().ImplementedInterfaces.FirstOrDefault();
return _container.GetService(i);
var scopeFactory = _container.GetService<IServiceScopeFactory>();
var scope = scopeFactory.CreateScope();
var scopedContainer = scope.ServiceProvider;
var interfaceType = type.GetTypeInfo().ImplementedInterfaces.FirstOrDefault();
var implementation = scopedContainer.GetRequiredService(interfaceType);
return implementation;
}
}
}

@ -148,5 +148,24 @@ namespace Ombi.Schedule.Jobs.Emby
await _tvRepo.Save();
}
private bool _disposed;
protected virtual void Dispose(bool disposing)
{
if (_disposed)
return;
if (disposing)
{
_movieRepo?.Dispose();
}
_disposed = true;
}
public void Dispose()
{
Dispose(true);
GC.SuppressFinalize(this);
}
}
}

@ -139,6 +139,26 @@ namespace Ombi.Schedule.Jobs.Emby
return true;
}
private bool _disposed;
protected virtual void Dispose(bool disposing)
{
if (_disposed)
return;
if (disposing)
{
_settings?.Dispose();
_repo?.Dispose();
}
_disposed = true;
}
public void Dispose()
{
Dispose(true);
GC.SuppressFinalize(this);
}
}
}

@ -121,5 +121,26 @@ namespace Ombi.Schedule.Jobs.Emby
await _repo.AddRange(epToAdd);
}
}
private bool _disposed;
protected virtual void Dispose(bool disposing)
{
if (_disposed)
return;
if (disposing)
{
_settings?.Dispose();
_repo?.Dispose();
_avaliabilityChecker?.Dispose();
}
_disposed = true;
}
public void Dispose()
{
Dispose(true);
GC.SuppressFinalize(this);
}
}
}

@ -25,6 +25,7 @@
// ************************************************************************/
#endregion
using System;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Identity;
@ -142,5 +143,26 @@ namespace Ombi.Schedule.Jobs.Emby
}
}
}
private bool _disposed;
protected virtual void Dispose(bool disposing)
{
if (_disposed)
return;
if (disposing)
{
_userManager?.Dispose();
_embySettings?.Dispose();
_userManagementSettings?.Dispose();
}
_disposed = true;
}
public void Dispose()
{
Dispose(true);
GC.SuppressFinalize(this);
}
}
}

@ -2,7 +2,7 @@
namespace Ombi.Schedule.Jobs.Emby
{
public interface IEmbyAvaliabilityChecker
public interface IEmbyAvaliabilityChecker : IBaseJob
{
Task Start();
}

@ -2,7 +2,7 @@ using System.Threading.Tasks;
namespace Ombi.Schedule.Jobs.Emby
{
public interface IEmbyContentSync
public interface IEmbyContentSync : IBaseJob
{
Task Start();
}

@ -2,7 +2,7 @@
namespace Ombi.Schedule.Jobs.Emby
{
public interface IEmbyEpisodeSync
public interface IEmbyEpisodeSync : IBaseJob
{
Task Start();
}

@ -2,7 +2,7 @@
namespace Ombi.Schedule.Jobs.Emby
{
public interface IEmbyUserImporter
public interface IEmbyUserImporter : IBaseJob
{
Task Start();
}

@ -0,0 +1,36 @@
#region Copyright
// /************************************************************************
// Copyright (c) 2018 Jamie Rees
// File: IBaseJob.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 Ombi.Schedule
{
public interface IBaseJob : IDisposable
{
}
}

@ -2,7 +2,7 @@
namespace Ombi.Schedule.Jobs.Plex
{
public interface IPlexAvailabilityChecker
public interface IPlexAvailabilityChecker : IBaseJob
{
Task Start();
}

@ -2,7 +2,7 @@
namespace Ombi.Schedule.Jobs
{
public interface IPlexContentSync
public interface IPlexContentSync : IBaseJob
{
Task CacheContent();
}

@ -1,8 +1,9 @@
using System.Threading.Tasks;
using System;
using System.Threading.Tasks;
namespace Ombi.Schedule.Jobs.Plex
namespace Ombi.Schedule.Jobs.Plex.Interfaces
{
public interface IPlexEpisodeSync
public interface IPlexEpisodeSync : IBaseJob
{
Task Start();
}

@ -2,7 +2,7 @@
namespace Ombi.Schedule.Jobs.Plex
{
public interface IPlexUserImporter
public interface IPlexUserImporter : IBaseJob
{
Task Start();
}

@ -143,5 +143,25 @@ namespace Ombi.Schedule.Jobs.Plex
await _movieRepo.Save();
}
private bool _disposed;
protected virtual void Dispose(bool disposing)
{
if (_disposed)
return;
if (disposing)
{
_movieRepo?.Dispose();
_repo?.Dispose();
}
_disposed = true;
}
public void Dispose()
{
Dispose(true);
GC.SuppressFinalize(this);
}
}
}

@ -36,6 +36,7 @@ using Ombi.Api.Plex.Models;
using Ombi.Core.Settings;
using Ombi.Core.Settings.Models.External;
using Ombi.Helpers;
using Ombi.Schedule.Jobs.Plex.Interfaces;
using Ombi.Store.Entities;
using Ombi.Store.Repository;
@ -303,5 +304,26 @@ namespace Ombi.Schedule.Jobs.Plex
}
return plex.Enable;
}
private bool _disposed;
protected virtual void Dispose(bool disposing)
{
if (_disposed)
return;
if (disposing)
{
Plex?.Dispose();
Repo?.Dispose();
EpisodeSync?.Dispose();
}
_disposed = true;
}
public void Dispose()
{
Dispose(true);
GC.SuppressFinalize(this);
}
}
}

@ -3,12 +3,14 @@ using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Hangfire;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.Logging;
using Ombi.Api.Plex;
using Ombi.Api.Plex.Models;
using Ombi.Core.Settings;
using Ombi.Core.Settings.Models.External;
using Ombi.Helpers;
using Ombi.Schedule.Jobs.Plex.Interfaces;
using Ombi.Store.Entities;
using Ombi.Store.Repository;
@ -99,7 +101,7 @@ namespace Ombi.Schedule.Jobs.Plex
var currentPosition = 0;
var resultCount = settings.EpisodeBatchSize == 0 ? 50 : settings.EpisodeBatchSize;
var episodes = await _api.GetAllEpisodes(settings.PlexAuthToken, settings.FullUri, section.key, currentPosition, resultCount);
var currentData = _repo.GetAllEpisodes();
var currentData = _repo.GetAllEpisodes().AsNoTracking();
_log.LogInformation(LoggingEvents.PlexEpisodeCacher, $"Total Epsiodes found for {episodes.MediaContainer.librarySectionTitle} = {episodes.MediaContainer.totalSize}");
await ProcessEpsiodes(episodes, currentData);
@ -159,5 +161,25 @@ namespace Ombi.Schedule.Jobs.Plex
return true;
}
private bool _disposed;
protected virtual void Dispose(bool disposing)
{
if (_disposed)
return;
if (disposing)
{
_repo?.Dispose();
_settings?.Dispose();
}
_disposed = true;
}
public void Dispose()
{
Dispose(true);
GC.SuppressFinalize(this);
}
}
}

@ -169,5 +169,26 @@ namespace Ombi.Schedule.Jobs.Plex
}
return result.Succeeded;
}
private bool _disposed;
protected virtual void Dispose(bool disposing)
{
if (_disposed)
return;
if (disposing)
{
_userManager?.Dispose();
_plexSettings?.Dispose();
_userManagementSettings?.Dispose();
}
_disposed = true;
}
public void Dispose()
{
Dispose(true);
GC.SuppressFinalize(this);
}
}
}

@ -1,8 +1,9 @@
using System.Threading.Tasks;
using System;
using System.Threading.Tasks;
namespace Ombi.Core.Settings
{
public interface ISettingsService<T>
public interface ISettingsService<T> : IDisposable
{
T GetSettings();
Task<T> GetSettingsAsync();

@ -155,5 +155,24 @@ namespace Ombi.Settings.Settings
return settings.Content;
//return _protector.Unprotect(settings.Content);
}
private bool _disposed;
protected virtual void Dispose(bool disposing)
{
if (_disposed)
return;
if (disposing)
{
Repo?.Dispose();
}
_disposed = true;
}
public void Dispose()
{
Dispose(true);
GC.SuppressFinalize(this);
}
}
}

@ -18,7 +18,6 @@ namespace Ombi.Store.Context
_created = true;
Database.Migrate();
}
public DbSet<NotificationTemplates> NotificationTemplates { get; set; }

@ -25,6 +25,7 @@
// ************************************************************************/
#endregion
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
@ -109,5 +110,24 @@ namespace Ombi.Store.Repository
Db.EmbyEpisode.AddRange(content);
await Db.SaveChangesAsync();
}
private bool _disposed;
protected virtual void Dispose(bool disposing)
{
if (_disposed)
return;
if (disposing)
{
Db?.Dispose();
}
_disposed = true;
}
public void Dispose()
{
Dispose(true);
GC.SuppressFinalize(this);
}
}
}

@ -1,11 +1,12 @@
using System.Collections.Generic;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Ombi.Store.Entities;
namespace Ombi.Store.Repository
{
public interface IEmbyContentRepository
public interface IEmbyContentRepository : IDisposable
{
Task<EmbyContent> Add(EmbyContent content);
Task AddRange(IEnumerable<EmbyContent> content);

@ -8,7 +8,7 @@ using Ombi.Store.Entities;
namespace Ombi.Store.Repository
{
public interface IRepository<T> where T : Entity
public interface IRepository<T> : IDisposable where T : Entity
{
Task<T> Find(object key);
IQueryable<T> GetAll();

@ -1,10 +1,11 @@
using System.Collections.Generic;
using System;
using System.Collections.Generic;
using System.Threading.Tasks;
using Ombi.Store.Entities;
namespace Ombi.Store.Repository
{
public interface ISettingsRepository
public interface ISettingsRepository : IDisposable
{
/// <summary>
/// Inserts the specified entity.

@ -71,5 +71,27 @@ namespace Ombi.Store.Repository
{
return source.Include(navigationPropertyPath);
}
private bool _disposed;
// Protected implementation of Dispose pattern.
protected virtual void Dispose(bool disposing)
{
if (_disposed)
return;
if (disposing)
{
_ctx?.Dispose();
}
_disposed = true;
}
public void Dispose()
{
Dispose(true);
GC.SuppressFinalize(this);
}
}
}

@ -89,5 +89,24 @@ namespace Ombi.Store.Repository
{
return $"{entity}Json";
}
private bool _disposed;
protected virtual void Dispose(bool disposing)
{
if (_disposed)
return;
if (disposing)
{
Db?.Dispose();
}
_disposed = true;
}
public void Dispose()
{
Dispose(true);
GC.SuppressFinalize(this);
}
}
}
Loading…
Cancel
Save