aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLuke Pulverenti <luke.pulverenti@gmail.com>2016-01-02 16:54:37 -0500
committerLuke Pulverenti <luke.pulverenti@gmail.com>2016-01-02 16:54:37 -0500
commit821e8246872cfa380249bca2f79ea810f27c87d5 (patch)
treec1ba1b2c3f24e8a8f92573828fbaa08d1ada3c97
parent4bf13f7754f9797eb5adc15ece0fcb2fd94cdb04 (diff)
better caching of remote data
-rw-r--r--MediaBrowser.Api/System/SystemService.cs13
-rw-r--r--MediaBrowser.Common.Implementations/Security/PluginSecurityManager.cs60
-rw-r--r--MediaBrowser.Common.Implementations/Updates/InstallationManager.cs103
-rw-r--r--MediaBrowser.Common/Security/ISecurityManager.cs6
-rw-r--r--MediaBrowser.Model.Portable/MediaBrowser.Model.Portable.csproj3
-rw-r--r--MediaBrowser.Model.net35/MediaBrowser.Model.net35.csproj3
-rw-r--r--MediaBrowser.Model/Entities/SupporterInfo.cs15
-rw-r--r--MediaBrowser.Model/MediaBrowser.Model.csproj1
-rw-r--r--MediaBrowser.Server.Implementations/Connect/ConnectEntryPoint.cs3
-rw-r--r--MediaBrowser.Server.Implementations/Connect/ConnectManager.cs15
-rw-r--r--MediaBrowser.Server.Implementations/EntryPoints/LoadRegistrations.cs2
-rw-r--r--MediaBrowser.Server.Implementations/EntryPoints/Notifications/RemoteNotifications.cs148
-rw-r--r--MediaBrowser.Server.Implementations/MediaBrowser.Server.Implementations.csproj1
13 files changed, 79 insertions, 294 deletions
diff --git a/MediaBrowser.Api/System/SystemService.cs b/MediaBrowser.Api/System/SystemService.cs
index 539b920a7..9b6b6a7d6 100644
--- a/MediaBrowser.Api/System/SystemService.cs
+++ b/MediaBrowser.Api/System/SystemService.cs
@@ -78,12 +78,6 @@ namespace MediaBrowser.Api.System
public string Name { get; set; }
}
- [Route("/System/SupporterInfo", "GET")]
- [Authenticated]
- public class GetSupporterInfo : IReturn<SupporterInfo>
- {
- }
-
/// <summary>
/// Class SystemInfoService
/// </summary>
@@ -116,13 +110,6 @@ namespace MediaBrowser.Api.System
_security = security;
}
- public async Task<object> Get(GetSupporterInfo request)
- {
- var result = await _security.GetSupporterInfo().ConfigureAwait(false);
-
- return ToOptimizedResult(result);
- }
-
public object Post(PingSystem request)
{
return _appHost.Name;
diff --git a/MediaBrowser.Common.Implementations/Security/PluginSecurityManager.cs b/MediaBrowser.Common.Implementations/Security/PluginSecurityManager.cs
index e796dba76..d8f350207 100644
--- a/MediaBrowser.Common.Implementations/Security/PluginSecurityManager.cs
+++ b/MediaBrowser.Common.Implementations/Security/PluginSecurityManager.cs
@@ -153,66 +153,6 @@ namespace MediaBrowser.Common.Implementations.Security
}
}
- public async Task<SupporterInfo> GetSupporterInfo()
- {
- var key = SupporterKey;
-
- if (string.IsNullOrWhiteSpace(key))
- {
- return new SupporterInfo();
- }
-
- var data = new Dictionary<string, string>
- {
- { "key", key },
- };
-
- var url = MbAdmin.HttpsUrl + "/service/supporter/retrieve";
-
- using (var stream = await _httpClient.Post(url, data, CancellationToken.None).ConfigureAwait(false))
- {
- var response = _jsonSerializer.DeserializeFromStream<SuppporterInfoResponse>(stream);
-
- var info = new SupporterInfo
- {
- Email = response.email,
- PlanType = response.planType,
- SupporterKey = response.supporterKey,
- IsActiveSupporter = IsMBSupporter
- };
-
- if (!string.IsNullOrWhiteSpace(response.expDate))
- {
- DateTime parsedDate;
- if (DateTime.TryParse(response.expDate, out parsedDate))
- {
- info.ExpirationDate = parsedDate;
- }
- else
- {
- _logger.Error("Failed to parse expDate: {0}", response.expDate);
- }
- }
-
- if (!string.IsNullOrWhiteSpace(response.regDate))
- {
- DateTime parsedDate;
- if (DateTime.TryParse(response.regDate, out parsedDate))
- {
- info.RegistrationDate = parsedDate;
- }
- else
- {
- _logger.Error("Failed to parse regDate: {0}", response.regDate);
- }
- }
-
- info.IsExpiredSupporter = info.ExpirationDate.HasValue && info.ExpirationDate < DateTime.UtcNow && !string.IsNullOrWhiteSpace(info.SupporterKey);
-
- return info;
- }
- }
-
/// <summary>
/// Register an app store sale with our back-end. It will validate the transaction with the store
/// and then register the proper feature and then fill in the supporter key on success.
diff --git a/MediaBrowser.Common.Implementations/Updates/InstallationManager.cs b/MediaBrowser.Common.Implementations/Updates/InstallationManager.cs
index dc642a0a8..014275331 100644
--- a/MediaBrowser.Common.Implementations/Updates/InstallationManager.cs
+++ b/MediaBrowser.Common.Implementations/Updates/InstallationManager.cs
@@ -185,7 +185,7 @@ namespace MediaBrowser.Common.Implementations.Updates
}
}
- private Tuple<List<PackageInfo>, DateTime> _lastPackageListResult;
+ private DateTime _lastPackageUpdateTime;
/// <summary>
/// Gets all available packages.
@@ -194,40 +194,89 @@ namespace MediaBrowser.Common.Implementations.Updates
/// <returns>Task{List{PackageInfo}}.</returns>
public async Task<IEnumerable<PackageInfo>> GetAvailablePackagesWithoutRegistrationInfo(CancellationToken cancellationToken)
{
- if (_lastPackageListResult != null)
+ using (var stream = await GetCachedPackages(cancellationToken).ConfigureAwait(false))
{
- TimeSpan cacheLength;
+ var packages = _jsonSerializer.DeserializeFromStream<List<PackageInfo>>(stream).ToList();
- switch (_config.CommonConfiguration.SystemUpdateLevel)
+ if ((DateTime.UtcNow - _lastPackageUpdateTime) > GetCacheLength())
{
- case PackageVersionClass.Beta:
- cacheLength = TimeSpan.FromMinutes(30);
- break;
- case PackageVersionClass.Dev:
- cacheLength = TimeSpan.FromMinutes(3);
- break;
- default:
- cacheLength = TimeSpan.FromHours(24);
- break;
+ UpdateCachedPackages(CancellationToken.None, false);
}
- if ((DateTime.UtcNow - _lastPackageListResult.Item2) < cacheLength)
- {
- return _lastPackageListResult.Item1;
- }
+ return packages;
}
+ }
- using (var json = await _httpClient.Get(MbAdmin.HttpUrl + "service/MB3Packages.json", cancellationToken).ConfigureAwait(false))
+ private string PackageCachePath
+ {
+ get { return Path.Combine(_appPaths.CachePath, "serverpackages.json"); }
+ }
+
+ private async Task<Stream> GetCachedPackages(CancellationToken cancellationToken)
+ {
+ try
+ {
+ return _fileSystem.OpenRead(PackageCachePath);
+ }
+ catch (Exception)
{
- cancellationToken.ThrowIfCancellationRequested();
- var packages = _jsonSerializer.DeserializeFromStream<List<PackageInfo>>(json).ToList();
+ }
- packages = FilterPackages(packages).ToList();
+ await UpdateCachedPackages(cancellationToken, true).ConfigureAwait(false);
+ return _fileSystem.OpenRead(PackageCachePath);
+ }
+
+ private readonly SemaphoreSlim _updateSemaphore = new SemaphoreSlim(1, 1);
+ private async Task UpdateCachedPackages(CancellationToken cancellationToken, bool throwErrors)
+ {
+ await _updateSemaphore.WaitAsync(cancellationToken).ConfigureAwait(false);
- _lastPackageListResult = new Tuple<List<PackageInfo>, DateTime>(packages, DateTime.UtcNow);
+ try
+ {
+ if ((DateTime.UtcNow - _lastPackageUpdateTime) < GetCacheLength())
+ {
+ return;
+ }
- return _lastPackageListResult.Item1;
+ var tempFile = await _httpClient.GetTempFile(new HttpRequestOptions
+ {
+ Url = MbAdmin.HttpUrl + "service/MB3Packages.json",
+ CancellationToken = cancellationToken,
+ Progress = new Progress<Double>()
+
+ }).ConfigureAwait(false);
+
+ _fileSystem.CreateDirectory(Path.GetDirectoryName(PackageCachePath));
+
+ _fileSystem.CopyFile(tempFile, PackageCachePath, true);
+ _lastPackageUpdateTime = DateTime.UtcNow;
+ }
+ catch (Exception ex)
+ {
+ _logger.ErrorException("Error updating package cache", ex);
+
+ if (throwErrors)
+ {
+ throw;
+ }
+ }
+ finally
+ {
+ _updateSemaphore.Release();
+ }
+ }
+
+ private TimeSpan GetCacheLength()
+ {
+ switch (_config.CommonConfiguration.SystemUpdateLevel)
+ {
+ case PackageVersionClass.Beta:
+ return TimeSpan.FromMinutes(30);
+ case PackageVersionClass.Dev:
+ return TimeSpan.FromMinutes(3);
+ default:
+ return TimeSpan.FromHours(24);
}
}
@@ -554,7 +603,7 @@ namespace MediaBrowser.Common.Implementations.Updates
if (packageChecksum != Guid.Empty) // support for legacy uploads for now
{
using (var crypto = new MD5CryptoServiceProvider())
- using (var stream = new BufferedStream(_fileSystem.OpenRead(tempFile), 100000))
+ using (var stream = new BufferedStream(_fileSystem.OpenRead(tempFile), 100000))
{
var check = Guid.Parse(BitConverter.ToString(crypto.ComputeHash(stream)).Replace("-", String.Empty));
if (check != packageChecksum)
@@ -569,12 +618,12 @@ namespace MediaBrowser.Common.Implementations.Updates
// Success - move it to the real target
try
{
- _fileSystem.CreateDirectory(Path.GetDirectoryName(target));
- _fileSystem.CopyFile(tempFile, target, true);
+ _fileSystem.CreateDirectory(Path.GetDirectoryName(target));
+ _fileSystem.CopyFile(tempFile, target, true);
//If it is an archive - write out a version file so we know what it is
if (isArchive)
{
- File.WriteAllText(target + ".ver", package.versionStr);
+ File.WriteAllText(target + ".ver", package.versionStr);
}
}
catch (IOException e)
diff --git a/MediaBrowser.Common/Security/ISecurityManager.cs b/MediaBrowser.Common/Security/ISecurityManager.cs
index 729de911b..0d8934a62 100644
--- a/MediaBrowser.Common/Security/ISecurityManager.cs
+++ b/MediaBrowser.Common/Security/ISecurityManager.cs
@@ -42,12 +42,6 @@ namespace MediaBrowser.Common.Security
Task LoadAllRegistrationInfo();
/// <summary>
- /// Gets the supporter information.
- /// </summary>
- /// <returns>Task&lt;SupporterInfo&gt;.</returns>
- Task<SupporterInfo> GetSupporterInfo();
-
- /// <summary>
/// Register and app store sale with our back-end
/// </summary>
/// <param name="parameters">Json parameters to pass to admin server</param>
diff --git a/MediaBrowser.Model.Portable/MediaBrowser.Model.Portable.csproj b/MediaBrowser.Model.Portable/MediaBrowser.Model.Portable.csproj
index 40e532b79..6145983e2 100644
--- a/MediaBrowser.Model.Portable/MediaBrowser.Model.Portable.csproj
+++ b/MediaBrowser.Model.Portable/MediaBrowser.Model.Portable.csproj
@@ -608,9 +608,6 @@
<Compile Include="..\MediaBrowser.Model\Entities\SortOrder.cs">
<Link>Entities\SortOrder.cs</Link>
</Compile>
- <Compile Include="..\MediaBrowser.Model\Entities\SupporterInfo.cs">
- <Link>Entities\SupporterInfo.cs</Link>
- </Compile>
<Compile Include="..\MediaBrowser.Model\Entities\TrailerType.cs">
<Link>Entities\TrailerType.cs</Link>
</Compile>
diff --git a/MediaBrowser.Model.net35/MediaBrowser.Model.net35.csproj b/MediaBrowser.Model.net35/MediaBrowser.Model.net35.csproj
index 09a7cde9d..435c4f50b 100644
--- a/MediaBrowser.Model.net35/MediaBrowser.Model.net35.csproj
+++ b/MediaBrowser.Model.net35/MediaBrowser.Model.net35.csproj
@@ -573,9 +573,6 @@
<Compile Include="..\MediaBrowser.Model\Entities\SortOrder.cs">
<Link>Entities\SortOrder.cs</Link>
</Compile>
- <Compile Include="..\MediaBrowser.Model\Entities\SupporterInfo.cs">
- <Link>Entities\SupporterInfo.cs</Link>
- </Compile>
<Compile Include="..\MediaBrowser.Model\Entities\TrailerType.cs">
<Link>Entities\TrailerType.cs</Link>
</Compile>
diff --git a/MediaBrowser.Model/Entities/SupporterInfo.cs b/MediaBrowser.Model/Entities/SupporterInfo.cs
deleted file mode 100644
index 233d5615f..000000000
--- a/MediaBrowser.Model/Entities/SupporterInfo.cs
+++ /dev/null
@@ -1,15 +0,0 @@
-using System;
-
-namespace MediaBrowser.Model.Entities
-{
- public class SupporterInfo
- {
- public string Email { get; set; }
- public string SupporterKey { get; set; }
- public DateTime? ExpirationDate { get; set; }
- public DateTime RegistrationDate { get; set; }
- public string PlanType { get; set; }
- public bool IsActiveSupporter { get; set; }
- public bool IsExpiredSupporter { get; set; }
- }
-} \ No newline at end of file
diff --git a/MediaBrowser.Model/MediaBrowser.Model.csproj b/MediaBrowser.Model/MediaBrowser.Model.csproj
index 1386854bb..3664175d8 100644
--- a/MediaBrowser.Model/MediaBrowser.Model.csproj
+++ b/MediaBrowser.Model/MediaBrowser.Model.csproj
@@ -144,7 +144,6 @@
<Compile Include="Dto\MediaSourceType.cs" />
<Compile Include="Configuration\DynamicDayOfWeek.cs" />
<Compile Include="Entities\ExtraType.cs" />
- <Compile Include="Entities\SupporterInfo.cs" />
<Compile Include="Entities\TrailerType.cs" />
<Compile Include="Extensions\BoolHelper.cs" />
<Compile Include="Extensions\FloatHelper.cs" />
diff --git a/MediaBrowser.Server.Implementations/Connect/ConnectEntryPoint.cs b/MediaBrowser.Server.Implementations/Connect/ConnectEntryPoint.cs
index 9ad04ebbd..af81b4eea 100644
--- a/MediaBrowser.Server.Implementations/Connect/ConnectEntryPoint.cs
+++ b/MediaBrowser.Server.Implementations/Connect/ConnectEntryPoint.cs
@@ -10,6 +10,7 @@ using System.IO;
using System.Net;
using System.Text;
using System.Threading;
+using System.Threading.Tasks;
using CommonIO;
using MediaBrowser.Common.IO;
@@ -40,7 +41,7 @@ namespace MediaBrowser.Server.Implementations.Connect
public void Run()
{
- LoadCachedAddress();
+ Task.Run(() => LoadCachedAddress());
_timer = new Timer(TimerCallback, null, TimeSpan.FromSeconds(5), TimeSpan.FromHours(3));
}
diff --git a/MediaBrowser.Server.Implementations/Connect/ConnectManager.cs b/MediaBrowser.Server.Implementations/Connect/ConnectManager.cs
index f1de09d56..fdc7e9ee2 100644
--- a/MediaBrowser.Server.Implementations/Connect/ConnectManager.cs
+++ b/MediaBrowser.Server.Implementations/Connect/ConnectManager.cs
@@ -1073,11 +1073,6 @@ namespace MediaBrowser.Server.Implementations.Connect
public async Task<ConnectSupporterSummary> GetConnectSupporterSummary()
{
- if (!_securityManager.IsMBSupporter)
- {
- return new ConnectSupporterSummary();
- }
-
var url = GetConnectUrl("keyAssociation");
var options = new HttpRequestOptions
@@ -1106,11 +1101,6 @@ namespace MediaBrowser.Server.Implementations.Connect
public async Task AddConnectSupporter(string id)
{
- if (!_securityManager.IsMBSupporter)
- {
- throw new InvalidOperationException();
- }
-
var url = GetConnectUrl("keyAssociation");
var options = new HttpRequestOptions
@@ -1139,11 +1129,6 @@ namespace MediaBrowser.Server.Implementations.Connect
public async Task RemoveConnectSupporter(string id)
{
- if (!_securityManager.IsMBSupporter)
- {
- throw new InvalidOperationException();
- }
-
var url = GetConnectUrl("keyAssociation");
var options = new HttpRequestOptions
diff --git a/MediaBrowser.Server.Implementations/EntryPoints/LoadRegistrations.cs b/MediaBrowser.Server.Implementations/EntryPoints/LoadRegistrations.cs
index 27170ced9..701cf21fb 100644
--- a/MediaBrowser.Server.Implementations/EntryPoints/LoadRegistrations.cs
+++ b/MediaBrowser.Server.Implementations/EntryPoints/LoadRegistrations.cs
@@ -41,7 +41,7 @@ namespace MediaBrowser.Server.Implementations.EntryPoints
/// </summary>
public void Run()
{
- _timer = new Timer(s => LoadAllRegistrations(), null, TimeSpan.FromMilliseconds(100), TimeSpan.FromHours(24));
+ _timer = new Timer(s => LoadAllRegistrations(), null, TimeSpan.FromMilliseconds(100), TimeSpan.FromHours(12));
}
private async Task LoadAllRegistrations()
diff --git a/MediaBrowser.Server.Implementations/EntryPoints/Notifications/RemoteNotifications.cs b/MediaBrowser.Server.Implementations/EntryPoints/Notifications/RemoteNotifications.cs
deleted file mode 100644
index 9a20505a5..000000000
--- a/MediaBrowser.Server.Implementations/EntryPoints/Notifications/RemoteNotifications.cs
+++ /dev/null
@@ -1,148 +0,0 @@
-using MediaBrowser.Common.Configuration;
-using MediaBrowser.Common.IO;
-using MediaBrowser.Common.Net;
-using MediaBrowser.Controller.Library;
-using MediaBrowser.Controller.Notifications;
-using MediaBrowser.Controller.Plugins;
-using MediaBrowser.Model.Logging;
-using MediaBrowser.Model.Notifications;
-using MediaBrowser.Model.Serialization;
-using System;
-using System.Collections.Generic;
-using System.IO;
-using System.Linq;
-using System.Threading;
-using System.Threading.Tasks;
-using CommonIO;
-
-namespace MediaBrowser.Server.Implementations.EntryPoints.Notifications
-{
- public class RemoteNotifications : IServerEntryPoint
- {
- private const string Url = "http://www.mb3admin.com/admin/service/MB3ServerNotifications.json";
-
- private Timer _timer;
- private readonly IHttpClient _httpClient;
- private readonly IApplicationPaths _appPaths;
- private readonly ILogger _logger;
- private readonly IJsonSerializer _json;
- private readonly IUserManager _userManager;
- private readonly IFileSystem _fileSystem;
-
- private readonly TimeSpan _frequency = TimeSpan.FromHours(6);
- private readonly TimeSpan _maxAge = TimeSpan.FromDays(31);
-
- private readonly INotificationManager _notificationManager;
-
- public RemoteNotifications(IApplicationPaths appPaths, ILogger logger, IHttpClient httpClient, IJsonSerializer json, IUserManager userManager, IFileSystem fileSystem, INotificationManager notificationManager)
- {
- _appPaths = appPaths;
- _logger = logger;
- _httpClient = httpClient;
- _json = json;
- _userManager = userManager;
- _fileSystem = fileSystem;
- _notificationManager = notificationManager;
- }
-
- /// <summary>
- /// Runs this instance.
- /// </summary>
- public void Run()
- {
- _timer = new Timer(OnTimerFired, null, TimeSpan.FromMilliseconds(500), _frequency);
- }
-
- /// <summary>
- /// Called when [timer fired].
- /// </summary>
- /// <param name="state">The state.</param>
- private async void OnTimerFired(object state)
- {
- var dataPath = Path.Combine(_appPaths.DataPath, "remotenotifications.json");
-
- var lastRunTime = _fileSystem.FileExists(dataPath) ? _fileSystem.GetLastWriteTimeUtc(dataPath) : DateTime.MinValue;
-
- try
- {
- await DownloadNotifications(dataPath, lastRunTime).ConfigureAwait(false);
- }
- catch (Exception ex)
- {
- _logger.ErrorException("Error downloading remote notifications", ex);
- }
- }
-
- /// <summary>
- /// Downloads the notifications.
- /// </summary>
- /// <param name="dataPath">The data path.</param>
- /// <param name="lastRunTime">The last run time.</param>
- /// <returns>Task.</returns>
- private async Task DownloadNotifications(string dataPath, DateTime lastRunTime)
- {
- using (var stream = await _httpClient.Get(new HttpRequestOptions
- {
- Url = Url
-
- }).ConfigureAwait(false))
- {
- var notifications = _json.DeserializeFromStream<RemoteNotification[]>(stream);
-
- _fileSystem.WriteAllText(dataPath, string.Empty);
-
- await CreateNotifications(notifications, lastRunTime).ConfigureAwait(false);
- }
- }
-
- /// <summary>
- /// Creates the notifications.
- /// </summary>
- /// <param name="notifications">The notifications.</param>
- /// <param name="lastRunTime">The last run time.</param>
- /// <returns>Task.</returns>
- private async Task CreateNotifications(IEnumerable<RemoteNotification> notifications, DateTime lastRunTime)
- {
- // Only show notifications that are active, new since last download, and not older than max age
- var notificationList = notifications
- .Where(i => string.Equals(i.active, "1") && i.date.ToUniversalTime() > lastRunTime && (DateTime.UtcNow - i.date.ToUniversalTime()) <= _maxAge)
- .ToList();
-
- var userIds = _userManager.Users.Select(i => i.Id.ToString("N")).ToList();
-
- foreach (var notification in notificationList)
- {
- await _notificationManager.SendNotification(new NotificationRequest
- {
- Date = notification.date,
- Name = notification.name,
- Description = notification.description,
- Url = notification.url,
- UserIds = userIds
-
- }, CancellationToken.None).ConfigureAwait(false);
- }
- }
-
- public void Dispose()
- {
- if (_timer != null)
- {
- _timer.Dispose();
- _timer = null;
- }
- }
-
- private class RemoteNotification
- {
- public string id { get; set; }
- public DateTime date { get; set; }
- public string name { get; set; }
- public string description { get; set; }
- public string category { get; set; }
- public string url { get; set; }
- public object imageUrl { get; set; }
- public string active { get; set; }
- }
- }
-}
diff --git a/MediaBrowser.Server.Implementations/MediaBrowser.Server.Implementations.csproj b/MediaBrowser.Server.Implementations/MediaBrowser.Server.Implementations.csproj
index bec2abdc4..52adae14c 100644
--- a/MediaBrowser.Server.Implementations/MediaBrowser.Server.Implementations.csproj
+++ b/MediaBrowser.Server.Implementations/MediaBrowser.Server.Implementations.csproj
@@ -131,7 +131,6 @@
<Compile Include="EntryPoints\LibraryChangedNotifier.cs" />
<Compile Include="EntryPoints\LoadRegistrations.cs" />
<Compile Include="EntryPoints\Notifications\Notifications.cs" />
- <Compile Include="EntryPoints\Notifications\RemoteNotifications.cs" />
<Compile Include="EntryPoints\Notifications\WebSocketNotifier.cs" />
<Compile Include="EntryPoints\RefreshUsersMetadata.cs" />
<Compile Include="EntryPoints\UsageEntryPoint.cs" />