diff options
Diffstat (limited to 'MediaBrowser.Common')
18 files changed, 146 insertions, 1261 deletions
diff --git a/MediaBrowser.Common/Kernel/BaseKernel.cs b/MediaBrowser.Common/Kernel/BaseKernel.cs index eb5381e206..5b8da5d094 100644 --- a/MediaBrowser.Common/Kernel/BaseKernel.cs +++ b/MediaBrowser.Common/Kernel/BaseKernel.cs @@ -40,9 +40,6 @@ namespace MediaBrowser.Common.Kernel internal void OnConfigurationUpdated() { EventHelper.QueueEventIfNotNull(ConfigurationUpdated, this, EventArgs.Empty, Logger); - - // Notify connected clients - TcpManager.SendWebSocketMessage("ConfigurationUpdated", Configuration); } #endregion @@ -141,12 +138,6 @@ namespace MediaBrowser.Common.Kernel } /// <summary> - /// Gets a value indicating whether this instance is first run. - /// </summary> - /// <value><c>true</c> if this instance is first run; otherwise, <c>false</c>.</value> - public bool IsFirstRun { get; private set; } - - /// <summary> /// Gets or sets a value indicating whether this instance has changes that require the entire application to restart. /// </summary> /// <value><c>true</c> if this instance has pending application restart; otherwise, <c>false</c>.</value> @@ -177,12 +168,6 @@ namespace MediaBrowser.Common.Kernel public TcpManager TcpManager { get; private set; } /// <summary> - /// Gets the rest services. - /// </summary> - /// <value>The rest services.</value> - public IEnumerable<IRestfulService> RestServices { get; private set; } - - /// <summary> /// Gets the UDP server port number. /// This can't be configurable because then the user would have to configure their client to discover the server. /// </summary> @@ -280,19 +265,7 @@ namespace MediaBrowser.Common.Kernel /// Initializes the Kernel /// </summary> /// <returns>Task.</returns> - public Task Init() - { - IsFirstRun = !File.Exists(ApplicationPaths.SystemConfigurationFilePath); - - // Performs initializations that can be reloaded at anytime - return Reload(); - } - - /// <summary> - /// Performs initializations that can be reloaded at anytime - /// </summary> - /// <returns>Task.</returns> - public async Task Reload() + public async Task Init() { OnReloadBeginning(); @@ -312,8 +285,6 @@ namespace MediaBrowser.Common.Kernel // Set these to null so that they can be lazy loaded again Configuration = null; - Logger.Info("Version {0} initializing", ApplicationVersion); - await OnConfigurationLoaded().ConfigureAwait(false); FindParts(); @@ -348,7 +319,6 @@ namespace MediaBrowser.Common.Kernel /// </summary> protected virtual void FindParts() { - RestServices = ApplicationHost.GetExports<IRestfulService>(); WebSocketListeners = ApplicationHost.GetExports<IWebSocketListener>(); Plugins = ApplicationHost.GetExports<IPlugin>(); } @@ -426,18 +396,6 @@ namespace MediaBrowser.Common.Kernel } /// <summary> - /// Gets the current application version - /// </summary> - /// <value>The application version.</value> - public Version ApplicationVersion - { - get - { - return GetType().Assembly.GetName().Version; - } - } - - /// <summary> /// Performs the pending restart. /// </summary> /// <returns>Task.</returns> @@ -445,7 +403,9 @@ namespace MediaBrowser.Common.Kernel { if (HasPendingRestart) { - RestartApplication(); + Logger.Info("Restarting the application"); + + ApplicationHost.Restart(); } else { @@ -454,16 +414,6 @@ namespace MediaBrowser.Common.Kernel } /// <summary> - /// Restarts the application. - /// </summary> - protected void RestartApplication() - { - Logger.Info("Restarting the application"); - - ApplicationHost.Restart(); - } - - /// <summary> /// Gets the system status. /// </summary> /// <returns>SystemInfo.</returns> @@ -472,7 +422,7 @@ namespace MediaBrowser.Common.Kernel return new SystemInfo { HasPendingRestart = HasPendingRestart, - Version = ApplicationVersion.ToString(), + Version = ApplicationHost.ApplicationVersion.ToString(), IsNetworkDeployed = ApplicationHost.CanSelfUpdate, WebSocketPortNumber = TcpManager.WebSocketPortNumber, SupportsNativeWebSocket = TcpManager.SupportsNativeWebSocket, diff --git a/MediaBrowser.Common/Kernel/IApplicationHost.cs b/MediaBrowser.Common/Kernel/IApplicationHost.cs index 4b564581b4..af9b039bc0 100644 --- a/MediaBrowser.Common/Kernel/IApplicationHost.cs +++ b/MediaBrowser.Common/Kernel/IApplicationHost.cs @@ -22,6 +22,12 @@ namespace MediaBrowser.Common.Kernel void ReloadLogger(); /// <summary> + /// Gets the application version. + /// </summary> + /// <value>The application version.</value> + Version ApplicationVersion { get; } + + /// <summary> /// Gets the log file path. /// </summary> /// <value>The log file path.</value> @@ -34,10 +40,16 @@ namespace MediaBrowser.Common.Kernel bool CanSelfUpdate { get; } /// <summary> + /// Gets a value indicating whether this instance is first run. + /// </summary> + /// <value><c>true</c> if this instance is first run; otherwise, <c>false</c>.</value> + bool IsFirstRun { get; } + + /// <summary> /// Gets the failed assemblies. /// </summary> /// <value>The failed assemblies.</value> - IEnumerable<string> FailedAssemblies { get; } + List<string> FailedAssemblies { get; } /// <summary> /// Gets all concrete types. @@ -73,34 +85,6 @@ namespace MediaBrowser.Common.Kernel object CreateInstance(Type type); /// <summary> - /// Registers a service that other classes can use as a dependancy. - /// </summary> - /// <typeparam name="T"></typeparam> - /// <param name="obj">The obj.</param> - void RegisterSingleInstance<T>(T obj) where T : class; - - /// <summary> - /// Registers the single instance. - /// </summary> - /// <typeparam name="T"></typeparam> - /// <param name="func">The func.</param> - void RegisterSingleInstance<T>(Func<T> func) where T : class; - - /// <summary> - /// Registers the specified func. - /// </summary> - /// <typeparam name="T"></typeparam> - /// <param name="func">The func.</param> - void Register<T>(Func<T> func) where T : class; - - /// <summary> - /// Registers the specified service type. - /// </summary> - /// <param name="serviceType">Type of the service.</param> - /// <param name="implementation">Type of the implementation.</param> - void Register(Type serviceType, Type implementation); - - /// <summary> /// Resolves this instance. /// </summary> /// <typeparam name="T"></typeparam> diff --git a/MediaBrowser.Common/Kernel/IKernel.cs b/MediaBrowser.Common/Kernel/IKernel.cs index fb629a24df..06c2e7b64c 100644 --- a/MediaBrowser.Common/Kernel/IKernel.cs +++ b/MediaBrowser.Common/Kernel/IKernel.cs @@ -38,12 +38,6 @@ namespace MediaBrowser.Common.Kernel Task Init(); /// <summary> - /// Reloads this instance. - /// </summary> - /// <returns>Task.</returns> - Task Reload(); - - /// <summary> /// Gets or sets a value indicating whether this instance has pending kernel reload. /// </summary> /// <value><c>true</c> if this instance has pending kernel reload; otherwise, <c>false</c>.</value> @@ -107,12 +101,6 @@ namespace MediaBrowser.Common.Kernel string HttpServerUrlPrefix { get; } /// <summary> - /// Gets a value indicating whether this instance is first run. - /// </summary> - /// <value><c>true</c> if this instance is first run; otherwise, <c>false</c>.</value> - bool IsFirstRun { get; } - - /// <summary> /// Gets the TCP manager. /// </summary> /// <value>The TCP manager.</value> @@ -140,12 +128,6 @@ namespace MediaBrowser.Common.Kernel event EventHandler<EventArgs> ConfigurationUpdated; /// <summary> - /// Gets the rest services. - /// </summary> - /// <value>The rest services.</value> - IEnumerable<IRestfulService> RestServices { get; } - - /// <summary> /// Notifies the pending restart. /// </summary> void NotifyPendingRestart(); diff --git a/MediaBrowser.Common/Kernel/TcpManager.cs b/MediaBrowser.Common/Kernel/TcpManager.cs index 1c76b42f96..2dfed501af 100644 --- a/MediaBrowser.Common/Kernel/TcpManager.cs +++ b/MediaBrowser.Common/Kernel/TcpManager.cs @@ -39,7 +39,7 @@ namespace MediaBrowser.Common.Kernel /// </summary> /// <value>The json serializer.</value> private readonly IJsonSerializer _jsonSerializer; - + /// <summary> /// This subscribes to HttpListener requests and finds the appropriate BaseHandler to process it /// </summary> @@ -133,7 +133,7 @@ namespace MediaBrowser.Common.Kernel _applicationHost = applicationHost; _networkManager = networkManager; - if (kernel.IsFirstRun) + if (applicationHost.IsFirstRun) { RegisterServerWithAdministratorAccess(); } @@ -215,7 +215,7 @@ namespace MediaBrowser.Common.Kernel /// <param name="e">The <see cref="WebSocketConnectEventArgs" /> instance containing the event data.</param> void HttpServer_WebSocketConnected(object sender, WebSocketConnectEventArgs e) { - var connection = new WebSocketConnection(e.WebSocket, e.Endpoint, ProcessWebSocketMessageReceived, _jsonSerializer, _logger); + var connection = new WebSocketConnection(e.WebSocket, e.Endpoint, _jsonSerializer, _logger) { OnReceive = ProcessWebSocketMessageReceived }; _webSocketConnections.Add(connection); } diff --git a/MediaBrowser.Common/MediaBrowser.Common.csproj b/MediaBrowser.Common/MediaBrowser.Common.csproj index bc3678a5e2..333c20beb7 100644 --- a/MediaBrowser.Common/MediaBrowser.Common.csproj +++ b/MediaBrowser.Common/MediaBrowser.Common.csproj @@ -95,8 +95,6 @@ <Compile Include="Kernel\IApplicationHost.cs" /> <Compile Include="Kernel\IKernel.cs" /> <Compile Include="Kernel\TcpManager.cs" /> - <Compile Include="Net\BaseRestService.cs" /> - <Compile Include="Net\Handlers\BaseActionHandler.cs" /> <Compile Include="Net\Handlers\IHttpServerHandler.cs" /> <Compile Include="Net\Handlers\StaticFileHandler.cs" /> <Compile Include="Net\IHttpClient.cs" /> @@ -122,6 +120,8 @@ <DesignTime>True</DesignTime> <DependentUpon>Resources.resx</DependentUpon> </Compile> + <Compile Include="ScheduledTasks\IScheduledTask.cs" /> + <Compile Include="ScheduledTasks\IScheduledTaskWorker.cs" /> <Compile Include="ScheduledTasks\ITaskManager.cs" /> <Compile Include="ScheduledTasks\ITaskTrigger.cs" /> <Compile Include="ScheduledTasks\ScheduledTaskHelpers.cs" /> @@ -130,13 +130,10 @@ <Compile Include="Kernel\BaseKernel.cs" /> <Compile Include="Kernel\KernelContext.cs" /> <Compile Include="Net\Handlers\BaseHandler.cs" /> - <Compile Include="Net\Handlers\BaseSerializationHandler.cs" /> <Compile Include="Plugins\BasePlugin.cs" /> <Compile Include="Properties\AssemblyInfo.cs" /> - <Compile Include="ScheduledTasks\BaseScheduledTask.cs" /> <Compile Include="ScheduledTasks\DailyTrigger.cs" /> <Compile Include="ScheduledTasks\IntervalTrigger.cs" /> - <Compile Include="ScheduledTasks\IScheduledTask.cs" /> <Compile Include="ScheduledTasks\WeeklyTrigger.cs" /> </ItemGroup> <ItemGroup> diff --git a/MediaBrowser.Common/Net/BaseRestService.cs b/MediaBrowser.Common/Net/BaseRestService.cs deleted file mode 100644 index a7e95fca2f..0000000000 --- a/MediaBrowser.Common/Net/BaseRestService.cs +++ /dev/null @@ -1,458 +0,0 @@ -using MediaBrowser.Common.Extensions; -using MediaBrowser.Common.IO; -using MediaBrowser.Common.Kernel; -using MediaBrowser.Model.Logging; -using ServiceStack.Common; -using ServiceStack.Common.Web; -using ServiceStack.ServiceHost; -using ServiceStack.ServiceInterface; -using ServiceStack.WebHost.Endpoints; -using System; -using System.Globalization; -using System.IO; -using System.Linq; -using System.Net; -using System.Threading.Tasks; - -namespace MediaBrowser.Common.Net -{ - /// <summary> - /// Class BaseRestService - /// </summary> - public class BaseRestService : Service, IRestfulService - { - /// <summary> - /// Gets or sets the kernel. - /// </summary> - /// <value>The kernel.</value> - public IKernel Kernel { get; set; } - - /// <summary> - /// Gets or sets the logger. - /// </summary> - /// <value>The logger.</value> - public ILogger Logger { get; set; } - - /// <summary> - /// Gets a value indicating whether this instance is range request. - /// </summary> - /// <value><c>true</c> if this instance is range request; otherwise, <c>false</c>.</value> - protected bool IsRangeRequest - { - get - { - return Request.Headers.AllKeys.Contains("Range"); - } - } - - /// <summary> - /// Adds the routes. - /// </summary> - /// <param name="appHost">The app host.</param> - public virtual void Configure(IAppHost appHost) - { - } - - /// <summary> - /// To the optimized result. - /// </summary> - /// <typeparam name="T"></typeparam> - /// <param name="result">The result.</param> - /// <returns>System.Object.</returns> - /// <exception cref="System.ArgumentNullException">result</exception> - protected object ToOptimizedResult<T>(T result) - where T : class - { - if (result == null) - { - throw new ArgumentNullException("result"); - } - - Response.AddHeader("Vary", "Accept-Encoding"); - - return RequestContext.ToOptimizedResult(result); - } - - /// <summary> - /// To the optimized result using cache. - /// </summary> - /// <typeparam name="T"></typeparam> - /// <param name="cacheKey">The cache key.</param> - /// <param name="lastDateModified">The last date modified.</param> - /// <param name="cacheDuration">Duration of the cache.</param> - /// <param name="factoryFn">The factory fn.</param> - /// <returns>System.Object.</returns> - /// <exception cref="System.ArgumentNullException">cacheKey</exception> - protected object ToOptimizedResultUsingCache<T>(Guid cacheKey, DateTime lastDateModified, TimeSpan? cacheDuration, Func<T> factoryFn) - where T : class - { - if (cacheKey == Guid.Empty) - { - throw new ArgumentNullException("cacheKey"); - } - if (factoryFn == null) - { - throw new ArgumentNullException("factoryFn"); - } - - var key = cacheKey.ToString("N"); - - var result = PreProcessCachedResult(cacheKey, key, lastDateModified, cacheDuration, string.Empty); - - if (result != null) - { - return result; - } - - return ToOptimizedResult(factoryFn()); - } - - /// <summary> - /// To the cached result. - /// </summary> - /// <typeparam name="T"></typeparam> - /// <param name="cacheKey">The cache key.</param> - /// <param name="lastDateModified">The last date modified.</param> - /// <param name="cacheDuration">Duration of the cache.</param> - /// <param name="factoryFn">The factory fn.</param> - /// <param name="contentType">Type of the content.</param> - /// <returns>System.Object.</returns> - /// <exception cref="System.ArgumentNullException">cacheKey</exception> - protected object ToCachedResult<T>(Guid cacheKey, DateTime lastDateModified, TimeSpan? cacheDuration, Func<T> factoryFn, string contentType) - where T : class - { - if (cacheKey == Guid.Empty) - { - throw new ArgumentNullException("cacheKey"); - } - if (factoryFn == null) - { - throw new ArgumentNullException("factoryFn"); - } - - var key = cacheKey.ToString("N"); - - var result = PreProcessCachedResult(cacheKey, key, lastDateModified, cacheDuration, contentType); - - if (result != null) - { - return result; - } - - return factoryFn(); - } - - /// <summary> - /// To the static file result. - /// </summary> - /// <param name="path">The path.</param> - /// <returns>System.Object.</returns> - /// <exception cref="System.ArgumentNullException">path</exception> - protected object ToStaticFileResult(string path) - { - if (string.IsNullOrEmpty(path)) - { - throw new ArgumentNullException("path"); - } - - var dateModified = File.GetLastWriteTimeUtc(path); - - var cacheKey = path + dateModified.Ticks; - - return ToStaticResult(cacheKey.GetMD5(), dateModified, null, MimeTypes.GetMimeType(path), () => Task.FromResult(GetFileStream(path))); - } - - /// <summary> - /// Gets the file stream. - /// </summary> - /// <param name="path">The path.</param> - /// <returns>Stream.</returns> - private Stream GetFileStream(string path) - { - return new FileStream(path, FileMode.Open, FileAccess.Read, FileShare.Read, StreamDefaults.DefaultFileStreamBufferSize, FileOptions.Asynchronous); - } - - /// <summary> - /// To the static result. - /// </summary> - /// <param name="cacheKey">The cache key.</param> - /// <param name="lastDateModified">The last date modified.</param> - /// <param name="cacheDuration">Duration of the cache.</param> - /// <param name="contentType">Type of the content.</param> - /// <param name="factoryFn">The factory fn.</param> - /// <returns>System.Object.</returns> - /// <exception cref="System.ArgumentNullException">cacheKey</exception> - protected object ToStaticResult(Guid cacheKey, DateTime? lastDateModified, TimeSpan? cacheDuration, string contentType, Func<Task<Stream>> factoryFn) - { - if (cacheKey == Guid.Empty) - { - throw new ArgumentNullException("cacheKey"); - } - if (factoryFn == null) - { - throw new ArgumentNullException("factoryFn"); - } - - var key = cacheKey.ToString("N"); - - var result = PreProcessCachedResult(cacheKey, key, lastDateModified, cacheDuration, contentType); - - if (result != null) - { - return result; - } - - var compress = ShouldCompressResponse(contentType); - - if (compress) - { - Response.AddHeader("Vary", "Accept-Encoding"); - } - - return ToStaticResult(contentType, factoryFn, compress).Result; - } - - /// <summary> - /// Shoulds the compress response. - /// </summary> - /// <param name="contentType">Type of the content.</param> - /// <returns><c>true</c> if XXXX, <c>false</c> otherwise</returns> - private bool ShouldCompressResponse(string contentType) - { - // It will take some work to support compression with byte range requests - if (IsRangeRequest) - { - return false; - } - - // Don't compress media - if (contentType.StartsWith("audio/", StringComparison.OrdinalIgnoreCase) || contentType.StartsWith("video/", StringComparison.OrdinalIgnoreCase)) - { - return false; - } - - // Don't compress images - if (contentType.StartsWith("image/", StringComparison.OrdinalIgnoreCase)) - { - return false; - } - - if (contentType.StartsWith("font/", StringComparison.OrdinalIgnoreCase)) - { - return false; - } - if (contentType.StartsWith("application/", StringComparison.OrdinalIgnoreCase)) - { - return false; - } - - return true; - } - - /// <summary> - /// To the static result. - /// </summary> - /// <param name="contentType">Type of the content.</param> - /// <param name="factoryFn">The factory fn.</param> - /// <param name="compress">if set to <c>true</c> [compress].</param> - /// <returns>System.Object.</returns> - private async Task<object> ToStaticResult(string contentType, Func<Task<Stream>> factoryFn, bool compress) - { - if (!compress || string.IsNullOrEmpty(RequestContext.CompressionType)) - { - Response.ContentType = contentType; - - var stream = await factoryFn().ConfigureAwait(false); - - return new StreamWriter(stream); - } - - string content; - - using (var stream = await factoryFn().ConfigureAwait(false)) - { - using (var reader = new StreamReader(stream)) - { - content = await reader.ReadToEndAsync().ConfigureAwait(false); - } - } - - var contents = content.Compress(RequestContext.CompressionType); - - return new CompressedResult(contents, RequestContext.CompressionType, contentType); - } - - /// <summary> - /// Pres the process optimized result. - /// </summary> - /// <param name="cacheKey">The cache key.</param> - /// <param name="cacheKeyString">The cache key string.</param> - /// <param name="lastDateModified">The last date modified.</param> - /// <param name="cacheDuration">Duration of the cache.</param> - /// <param name="contentType">Type of the content.</param> - /// <returns>System.Object.</returns> - private object PreProcessCachedResult(Guid cacheKey, string cacheKeyString, DateTime? lastDateModified, TimeSpan? cacheDuration, string contentType) - { - Response.AddHeader("ETag", cacheKeyString); - - if (IsNotModified(cacheKey, lastDateModified, cacheDuration)) - { - AddAgeHeader(lastDateModified); - AddExpiresHeader(cacheKeyString, cacheDuration); - //ctx.Response.SendChunked = false; - - if (!string.IsNullOrEmpty(contentType)) - { - Response.ContentType = contentType; - } - - return new HttpResult(new byte[] { }, HttpStatusCode.NotModified); - } - - SetCachingHeaders(cacheKeyString, lastDateModified, cacheDuration); - - return null; - } - - /// <summary> - /// Determines whether [is not modified] [the specified cache key]. - /// </summary> - /// <param name="cacheKey">The cache key.</param> - /// <param name="lastDateModified">The last date modified.</param> - /// <param name="cacheDuration">Duration of the cache.</param> - /// <returns><c>true</c> if [is not modified] [the specified cache key]; otherwise, <c>false</c>.</returns> - private bool IsNotModified(Guid? cacheKey, DateTime? lastDateModified, TimeSpan? cacheDuration) - { - var isNotModified = true; - - if (Request.Headers.AllKeys.Contains("If-Modified-Since")) - { - DateTime ifModifiedSince; - - if (DateTime.TryParse(Request.Headers["If-Modified-Since"], out ifModifiedSince)) - { - isNotModified = IsNotModified(ifModifiedSince.ToUniversalTime(), cacheDuration, lastDateModified); - } - } - - // Validate If-None-Match - if (isNotModified && (cacheKey.HasValue || !string.IsNullOrEmpty(Request.Headers["If-None-Match"]))) - { - Guid ifNoneMatch; - - if (Guid.TryParse(Request.Headers["If-None-Match"] ?? string.Empty, out ifNoneMatch)) - { - if (cacheKey.HasValue && cacheKey.Value == ifNoneMatch) - { - return true; - } - } - } - - return false; - } - - /// <summary> - /// Determines whether [is not modified] [the specified if modified since]. - /// </summary> - /// <param name="ifModifiedSince">If modified since.</param> - /// <param name="cacheDuration">Duration of the cache.</param> - /// <param name="dateModified">The date modified.</param> - /// <returns><c>true</c> if [is not modified] [the specified if modified since]; otherwise, <c>false</c>.</returns> - private bool IsNotModified(DateTime ifModifiedSince, TimeSpan? cacheDuration, DateTime? dateModified) - { - if (dateModified.HasValue) - { - var lastModified = NormalizeDateForComparison(dateModified.Value); - ifModifiedSince = NormalizeDateForComparison(ifModifiedSince); - - return lastModified <= ifModifiedSince; - } - - if (cacheDuration.HasValue) - { - var cacheExpirationDate = ifModifiedSince.Add(cacheDuration.Value); - - if (DateTime.UtcNow < cacheExpirationDate) - { - return true; - } - } - - return false; - } - - - /// <summary> - /// When the browser sends the IfModifiedDate, it's precision is limited to seconds, so this will account for that - /// </summary> - /// <param name="date">The date.</param> - /// <returns>DateTime.</returns> - private DateTime NormalizeDateForComparison(DateTime date) - { - return new DateTime(date.Year, date.Month, date.Day, date.Hour, date.Minute, date.Second, date.Kind); - } - - /// <summary> - /// Sets the caching headers. - /// </summary> - /// <param name="cacheKey">The cache key.</param> - /// <param name="lastDateModified">The last date modified.</param> - /// <param name="cacheDuration">Duration of the cache.</param> - private void SetCachingHeaders(string cacheKey, DateTime? lastDateModified, TimeSpan? cacheDuration) - { - // Don't specify both last modified and Etag, unless caching unconditionally. They are redundant - // https://developers.google.com/speed/docs/best-practices/caching#LeverageBrowserCaching - if (lastDateModified.HasValue && (string.IsNullOrEmpty(cacheKey) || cacheDuration.HasValue)) - { - AddAgeHeader(lastDateModified); - Response.AddHeader("LastModified", lastDateModified.Value.ToString("r")); - } - - if (cacheDuration.HasValue) - { - Response.AddHeader("Cache-Control", "public, max-age=" + Convert.ToInt32(cacheDuration.Value.TotalSeconds)); - } - else if (!string.IsNullOrEmpty(cacheKey)) - { - Response.AddHeader("Cache-Control", "public"); - } - else - { - Response.AddHeader("Cache-Control", "no-cache, no-store, must-revalidate"); - Response.AddHeader("pragma", "no-cache, no-store, must-revalidate"); - } - - AddExpiresHeader(cacheKey, cacheDuration); - } - - /// <summary> - /// Adds the expires header. - /// </summary> - /// <param name="cacheKey">The cache key.</param> - /// <param name="cacheDuration">Duration of the cache.</param> - private void AddExpiresHeader(string cacheKey, TimeSpan? cacheDuration) - { - if (cacheDuration.HasValue) - { - Response.AddHeader("Expires", DateTime.UtcNow.Add(cacheDuration.Value).ToString("r")); - } - else if (string.IsNullOrEmpty(cacheKey)) - { - Response.AddHeader("Expires", "-1"); - } - } - - /// <summary> - /// Adds the age header. - /// </summary> - /// <param name="lastDateModified">The last date modified.</param> - private void AddAgeHeader(DateTime? lastDateModified) - { - if (lastDateModified.HasValue) - { - Response.AddHeader("Age", Convert.ToInt64((DateTime.UtcNow - lastDateModified.Value).TotalSeconds).ToString(CultureInfo.InvariantCulture)); - } - } - } -} diff --git a/MediaBrowser.Common/Net/Handlers/BaseActionHandler.cs b/MediaBrowser.Common/Net/Handlers/BaseActionHandler.cs deleted file mode 100644 index 72df88519b..0000000000 --- a/MediaBrowser.Common/Net/Handlers/BaseActionHandler.cs +++ /dev/null @@ -1,31 +0,0 @@ -using MediaBrowser.Common.Kernel; -using MediaBrowser.Model.Entities; -using System.Threading.Tasks; - -namespace MediaBrowser.Common.Net.Handlers -{ - /// <summary> - /// Class BaseActionHandler - /// </summary> - /// <typeparam name="TKernelType">The type of the T kernel type.</typeparam> - public abstract class BaseActionHandler<TKernelType> : BaseSerializationHandler<TKernelType, EmptyRequestResult> - where TKernelType : IKernel - { - /// <summary> - /// Gets the object to serialize. - /// </summary> - /// <returns>Task{EmptyRequestResult}.</returns> - protected override async Task<EmptyRequestResult> GetObjectToSerialize() - { - await ExecuteAction(); - - return new EmptyRequestResult(); - } - - /// <summary> - /// Performs the action. - /// </summary> - /// <returns>Task.</returns> - protected abstract Task ExecuteAction(); - } -} diff --git a/MediaBrowser.Common/Net/Handlers/BaseSerializationHandler.cs b/MediaBrowser.Common/Net/Handlers/BaseSerializationHandler.cs deleted file mode 100644 index a00152d784..0000000000 --- a/MediaBrowser.Common/Net/Handlers/BaseSerializationHandler.cs +++ /dev/null @@ -1,133 +0,0 @@ -using MediaBrowser.Common.Extensions; -using MediaBrowser.Common.Kernel; -using System; -using System.IO; -using System.Threading.Tasks; - -namespace MediaBrowser.Common.Net.Handlers -{ - /// <summary> - /// Class BaseSerializationHandler - /// </summary> - /// <typeparam name="TKernelType">The type of the T kernel type.</typeparam> - /// <typeparam name="T"></typeparam> - public abstract class BaseSerializationHandler<TKernelType, T> : BaseHandler<TKernelType> - where TKernelType : IKernel - where T : class - { - /// <summary> - /// Gets the serialization format. - /// </summary> - /// <value>The serialization format.</value> - public SerializationFormat SerializationFormat - { - get - { - var format = QueryString["dataformat"]; - - if (string.IsNullOrEmpty(format)) - { - return SerializationFormat.Json; - } - - return (SerializationFormat)Enum.Parse(typeof(SerializationFormat), format, true); - } - } - - /// <summary> - /// Gets the type of the content. - /// </summary> - /// <value>The type of the content.</value> - protected string ContentType - { - get - { - switch (SerializationFormat) - { - case SerializationFormat.Protobuf: - return "application/x-protobuf"; - default: - return MimeTypes.JsonMimeType; - } - } - } - - /// <summary> - /// Gets the response info. - /// </summary> - /// <returns>Task{ResponseInfo}.</returns> - protected override Task<ResponseInfo> GetResponseInfo() - { - return Task.FromResult(new ResponseInfo - { - ContentType = ContentType - }); - } - - /// <summary> - /// Called when [processing request]. - /// </summary> - /// <param name="responseInfo">The response info.</param> - /// <returns>Task.</returns> - protected override async Task OnProcessingRequest(ResponseInfo responseInfo) - { - _objectToSerialize = await GetObjectToSerialize().ConfigureAwait(false); - - if (_objectToSerialize == null) - { - throw new ResourceNotFoundException(); - } - - await base.OnProcessingRequest(responseInfo).ConfigureAwait(false); - } - - /// <summary> - /// The _object to serialize - /// </summary> - private T _objectToSerialize; - - /// <summary> - /// Gets the object to serialize. - /// </summary> - /// <returns>Task{`0}.</returns> - protected abstract Task<T> GetObjectToSerialize(); - - /// <summary> - /// Writes the response to output stream. - /// </summary> - /// <param name="stream">The stream.</param> - /// <param name="responseInfo">The response info.</param> - /// <param name="contentLength">Length of the content.</param> - /// <returns>Task.</returns> - protected override Task WriteResponseToOutputStream(Stream stream, ResponseInfo responseInfo, long? contentLength) - { - return Task.Run(() => - { - //switch (SerializationFormat) - //{ - // case SerializationFormat.Protobuf: - // Kernel.ProtobufSerializer.SerializeToStream(_objectToSerialize, stream); - // break; - // default: - // JsonSerializer.SerializeToStream(_objectToSerialize, stream); - // break; - //} - }); - } - } - - /// <summary> - /// Enum SerializationFormat - /// </summary> - public enum SerializationFormat - { - /// <summary> - /// The json - /// </summary> - Json, - /// <summary> - /// The protobuf - /// </summary> - Protobuf - } -} diff --git a/MediaBrowser.Common/Net/IHttpClient.cs b/MediaBrowser.Common/Net/IHttpClient.cs index ef0dd69b70..d02f08572d 100644 --- a/MediaBrowser.Common/Net/IHttpClient.cs +++ b/MediaBrowser.Common/Net/IHttpClient.cs @@ -6,6 +6,9 @@ using System.Threading.Tasks; namespace MediaBrowser.Common.Net { + /// <summary> + /// Interface IHttpClient + /// </summary> public interface IHttpClient : IDisposable { /// <summary> @@ -52,10 +55,5 @@ namespace MediaBrowser.Common.Net /// <returns>Task{MemoryStream}.</returns> /// <exception cref="MediaBrowser.Model.Net.HttpException"></exception> Task<MemoryStream> GetMemoryStream(string url, SemaphoreSlim resourcePool, CancellationToken cancellationToken); - - /// <summary> - /// Performs application-defined tasks associated with freeing, releasing, or resetting unmanaged resources. - /// </summary> - void Dispose(); } }
\ No newline at end of file diff --git a/MediaBrowser.Common/Net/IHttpServer.cs b/MediaBrowser.Common/Net/IHttpServer.cs index a640fb2626..45da18e1b8 100644 --- a/MediaBrowser.Common/Net/IHttpServer.cs +++ b/MediaBrowser.Common/Net/IHttpServer.cs @@ -1,4 +1,5 @@ using System; +using System.Collections.Generic; namespace MediaBrowser.Common.Net { @@ -40,5 +41,10 @@ namespace MediaBrowser.Common.Net /// Occurs when [web socket connected]. /// </summary> event EventHandler<WebSocketConnectEventArgs> WebSocketConnected; + + /// <summary> + /// Inits this instance. + /// </summary> + void Init(IEnumerable<IRestfulService> services); } }
\ No newline at end of file diff --git a/MediaBrowser.Common/Net/IRestfulService.cs b/MediaBrowser.Common/Net/IRestfulService.cs index 7fc6bb61ec..36055cd8a3 100644 --- a/MediaBrowser.Common/Net/IRestfulService.cs +++ b/MediaBrowser.Common/Net/IRestfulService.cs @@ -1,5 +1,4 @@ using ServiceStack.ServiceHost; -using ServiceStack.WebHost.Endpoints; using System; namespace MediaBrowser.Common.Net @@ -9,6 +8,5 @@ namespace MediaBrowser.Common.Net /// </summary> public interface IRestfulService : IService, IRequiresRequestContext, IDisposable { - void Configure(IAppHost appHost); } } diff --git a/MediaBrowser.Common/Net/WebSocketConnection.cs b/MediaBrowser.Common/Net/WebSocketConnection.cs index 36d649e3b1..1ad0e8f06f 100644 --- a/MediaBrowser.Common/Net/WebSocketConnection.cs +++ b/MediaBrowser.Common/Net/WebSocketConnection.cs @@ -41,17 +41,22 @@ namespace MediaBrowser.Common.Net /// The _json serializer /// </summary> private readonly IJsonSerializer _jsonSerializer; - + + /// <summary> + /// Gets or sets the receive action. + /// </summary> + /// <value>The receive action.</value> + public Action<WebSocketMessageInfo> OnReceive { get; set; } + /// <summary> /// Initializes a new instance of the <see cref="WebSocketConnection" /> class. /// </summary> /// <param name="socket">The socket.</param> /// <param name="remoteEndPoint">The remote end point.</param> - /// <param name="receiveAction">The receive action.</param> /// <param name="jsonSerializer">The json serializer.</param> /// <param name="logger">The logger.</param> /// <exception cref="System.ArgumentNullException">socket</exception> - public WebSocketConnection(IWebSocket socket, string remoteEndPoint, Action<WebSocketMessageInfo> receiveAction, IJsonSerializer jsonSerializer, ILogger logger) + public WebSocketConnection(IWebSocket socket, string remoteEndPoint, IJsonSerializer jsonSerializer, ILogger logger) { if (socket == null) { @@ -61,10 +66,6 @@ namespace MediaBrowser.Common.Net { throw new ArgumentNullException("remoteEndPoint"); } - if (receiveAction == null) - { - throw new ArgumentNullException("receiveAction"); - } if (jsonSerializer == null) { throw new ArgumentNullException("jsonSerializer"); @@ -76,7 +77,7 @@ namespace MediaBrowser.Common.Net _jsonSerializer = jsonSerializer; _socket = socket; - _socket.OnReceiveDelegate = info => OnReceive(info, receiveAction); + _socket.OnReceiveDelegate = OnReceiveInternal; RemoteEndPoint = remoteEndPoint; _logger = logger; } @@ -85,21 +86,24 @@ namespace MediaBrowser.Common.Net /// Called when [receive]. /// </summary> /// <param name="bytes">The bytes.</param> - /// <param name="callback">The callback.</param> - private void OnReceive(byte[] bytes, Action<WebSocketMessageInfo> callback) + private void OnReceiveInternal(byte[] bytes) { + if (OnReceive == null) + { + return; + } try { WebSocketMessageInfo info; using (var memoryStream = new MemoryStream(bytes)) { - info = _jsonSerializer.DeserializeFromStream<WebSocketMessageInfo>(memoryStream); + info = (WebSocketMessageInfo)_jsonSerializer.DeserializeFromStream(memoryStream, typeof(WebSocketMessageInfo)); } info.Connection = this; - callback(info); + OnReceive(info); } catch (Exception ex) { diff --git a/MediaBrowser.Common/Plugins/BasePlugin.cs b/MediaBrowser.Common/Plugins/BasePlugin.cs index dad3867fcb..72c83a5cee 100644 --- a/MediaBrowser.Common/Plugins/BasePlugin.cs +++ b/MediaBrowser.Common/Plugins/BasePlugin.cs @@ -1,12 +1,12 @@ using MediaBrowser.Common.Kernel; using MediaBrowser.Model.Logging; using MediaBrowser.Model.Plugins; +using MediaBrowser.Model.Serialization; using System; using System.IO; using System.Reflection; using System.Runtime.InteropServices; using System.Threading; -using MediaBrowser.Model.Serialization; namespace MediaBrowser.Common.Plugins { @@ -393,9 +393,6 @@ namespace MediaBrowser.Common.Plugins { XmlSerializer.SerializeToFile(Configuration, ConfigurationFilePath); } - - // Notify connected UI's - Kernel.TcpManager.SendWebSocketMessage("PluginConfigurationUpdated-" + Name, Configuration); } /// <summary> diff --git a/MediaBrowser.Common/ScheduledTasks/BaseScheduledTask.cs b/MediaBrowser.Common/ScheduledTasks/BaseScheduledTask.cs deleted file mode 100644 index 09ceaa9aee..0000000000 --- a/MediaBrowser.Common/ScheduledTasks/BaseScheduledTask.cs +++ /dev/null @@ -1,424 +0,0 @@ -using MediaBrowser.Common.Extensions; -using MediaBrowser.Common.Kernel; -using MediaBrowser.Model.Logging; -using MediaBrowser.Model.Tasks; -using System; -using System.Collections.Generic; -using System.IO; -using System.Linq; -using System.Threading; -using System.Threading.Tasks; - -namespace MediaBrowser.Common.ScheduledTasks -{ - /// <summary> - /// Represents a task that can be executed at a scheduled time - /// </summary> - /// <typeparam name="TKernelType">The type of the T kernel type.</typeparam> - public abstract class BaseScheduledTask<TKernelType> : IScheduledTask - where TKernelType : class, IKernel - { - /// <summary> - /// Gets the kernel. - /// </summary> - /// <value>The kernel.</value> - protected TKernelType Kernel { get; private set; } - - /// <summary> - /// Gets the logger. - /// </summary> - /// <value>The logger.</value> - protected ILogger Logger { get; private set; } - - /// <summary> - /// Gets the task manager. - /// </summary> - /// <value>The task manager.</value> - protected ITaskManager TaskManager { get; private set; } - - /// <summary> - /// Initializes a new instance of the <see cref="BaseScheduledTask{TKernelType}" /> class. - /// </summary> - /// <param name="kernel">The kernel.</param> - /// <param name="taskManager">The task manager.</param> - /// <param name="logger">The logger.</param> - /// <exception cref="System.ArgumentNullException">kernel</exception> - protected BaseScheduledTask(TKernelType kernel, ITaskManager taskManager, ILogger logger) - { - if (kernel == null) - { - throw new ArgumentNullException("kernel"); - } - if (taskManager == null) - { - throw new ArgumentNullException("taskManager"); - } - if (logger == null) - { - throw new ArgumentNullException("logger"); - } - - Kernel = kernel; - TaskManager = taskManager; - Logger = logger; - - ReloadTriggerEvents(true); - } - - /// <summary> - /// The _last execution result - /// </summary> - private TaskResult _lastExecutionResult; - /// <summary> - /// The _last execution resultinitialized - /// </summary> - private bool _lastExecutionResultinitialized; - /// <summary> - /// The _last execution result sync lock - /// </summary> - private object _lastExecutionResultSyncLock = new object(); - /// <summary> - /// Gets the last execution result. - /// </summary> - /// <value>The last execution result.</value> - public TaskResult LastExecutionResult - { - get - { - LazyInitializer.EnsureInitialized(ref _lastExecutionResult, ref _lastExecutionResultinitialized, ref _lastExecutionResultSyncLock, () => - { - try - { - return TaskManager.GetLastExecutionResult(this); - } - catch (IOException) - { - // File doesn't exist. No biggie - return null; - } - }); - - return _lastExecutionResult; - } - private set - { - _lastExecutionResult = value; - - _lastExecutionResultinitialized = value != null; - } - } - - /// <summary> - /// Gets the current cancellation token - /// </summary> - /// <value>The current cancellation token source.</value> - private CancellationTokenSource CurrentCancellationTokenSource { get; set; } - - /// <summary> - /// Gets or sets the current execution start time. - /// </summary> - /// <value>The current execution start time.</value> - private DateTime CurrentExecutionStartTime { get; set; } - - /// <summary> - /// Gets the state. - /// </summary> - /// <value>The state.</value> - public TaskState State - { - get - { - if (CurrentCancellationTokenSource != null) - { - return CurrentCancellationTokenSource.IsCancellationRequested - ? TaskState.Cancelling - : TaskState.Running; - } - - return TaskState.Idle; - } - } - - /// <summary> - /// Gets the current progress. - /// </summary> - /// <value>The current progress.</value> - public double? CurrentProgress { get; private set; } - - /// <summary> - /// The _triggers - /// </summary> - private IEnumerable<ITaskTrigger> _triggers; - /// <summary> - /// The _triggers initialized - /// </summary> - private bool _triggersInitialized; - /// <summary> - /// The _triggers sync lock - /// </summary> - private object _triggersSyncLock = new object(); - /// <summary> - /// Gets the triggers that define when the task will run - /// </summary> - /// <value>The triggers.</value> - /// <exception cref="System.ArgumentNullException">value</exception> - public IEnumerable<ITaskTrigger> Triggers - { - get - { - LazyInitializer.EnsureInitialized(ref _triggers, ref _triggersInitialized, ref _triggersSyncLock, () => TaskManager.LoadTriggers(this)); - - return _triggers; - } - set - { - if (value == null) - { - throw new ArgumentNullException("value"); - } - - // Cleanup current triggers - if (_triggers != null) - { - DisposeTriggers(); - } - - _triggers = value.ToList(); - - _triggersInitialized = true; - - ReloadTriggerEvents(false); - - TaskManager.SaveTriggers(this, _triggers); - } - } - - /// <summary> - /// Creates the triggers that define when the task will run - /// </summary> - /// <returns>IEnumerable{BaseTaskTrigger}.</returns> - public abstract IEnumerable<ITaskTrigger> GetDefaultTriggers(); - - /// <summary> - /// Returns the task to be executed - /// </summary> - /// <param name="cancellationToken">The cancellation token.</param> - /// <param name="progress">The progress.</param> - /// <returns>Task.</returns> - protected abstract Task ExecuteInternal(CancellationToken cancellationToken, IProgress<double> progress); - - /// <summary> - /// Gets the name of the task - /// </summary> - /// <value>The name.</value> - public abstract string Name { get; } - - /// <summary> - /// Gets the description. - /// </summary> - /// <value>The description.</value> - public abstract string Description { get; } - - /// <summary> - /// Gets the category. - /// </summary> - /// <value>The category.</value> - public virtual string Category - { - get { return "Application"; } - } - - /// <summary> - /// The _id - /// </summary> - private Guid? _id; - - /// <summary> - /// Gets the unique id. - /// </summary> - /// <value>The unique id.</value> - public Guid Id - { - get - { - if (!_id.HasValue) - { - _id = GetType().FullName.GetMD5(); - } - - return _id.Value; - } - } - - /// <summary> - /// Reloads the trigger events. - /// </summary> - /// <param name="isApplicationStartup">if set to <c>true</c> [is application startup].</param> - private void ReloadTriggerEvents(bool isApplicationStartup) - { - foreach (var trigger in Triggers) - { - trigger.Stop(); - - trigger.Triggered -= trigger_Triggered; - trigger.Triggered += trigger_Triggered; - trigger.Start(isApplicationStartup); - } - } - - /// <summary> - /// Handles the Triggered event of the trigger control. - /// </summary> - /// <param name="sender">The source of the event.</param> - /// <param name="e">The <see cref="EventArgs" /> instance containing the event data.</param> - async void trigger_Triggered(object sender, EventArgs e) - { - var trigger = (ITaskTrigger)sender; - - Logger.Info("{0} fired for task: {1}", trigger.GetType().Name, Name); - - trigger.Stop(); - - TaskManager.QueueScheduledTask(this); - - await Task.Delay(1000).ConfigureAwait(false); - - trigger.Start(false); - } - - /// <summary> - /// Executes the task - /// </summary> - /// <returns>Task.</returns> - /// <exception cref="System.InvalidOperationException">Cannot execute a Task that is already running</exception> - public async Task Execute() - { - // Cancel the current execution, if any - if (CurrentCancellationTokenSource != null) - { - throw new InvalidOperationException("Cannot execute a Task that is already running"); - } - - CurrentCancellationTokenSource = new CancellationTokenSource(); - - Logger.Info("Executing {0}", Name); - - var progress = new Progress<double>(); - - progress.ProgressChanged += progress_ProgressChanged; - - TaskCompletionStatus status; - CurrentExecutionStartTime = DateTime.UtcNow; - - Kernel.TcpManager.SendWebSocketMessage("ScheduledTaskBeginExecute", Name); - - try - { - await Task.Run(async () => await ExecuteInternal(CurrentCancellationTokenSource.Token, progress).ConfigureAwait(false)).ConfigureAwait(false); - - status = TaskCompletionStatus.Completed; - } - catch (OperationCanceledException) - { - status = TaskCompletionStatus.Cancelled; - } - catch (Exception ex) - { - Logger.ErrorException("Error", ex); - - status = TaskCompletionStatus.Failed; - } - - var startTime = CurrentExecutionStartTime; - var endTime = DateTime.UtcNow; - - Kernel.TcpManager.SendWebSocketMessage("ScheduledTaskEndExecute", LastExecutionResult); - - progress.ProgressChanged -= progress_ProgressChanged; - CurrentCancellationTokenSource.Dispose(); - CurrentCancellationTokenSource = null; - CurrentProgress = null; - - TaskManager.OnTaskCompleted(this, startTime, endTime, status); - } - - /// <summary> - /// Progress_s the progress changed. - /// </summary> - /// <param name="sender">The sender.</param> - /// <param name="e">The e.</param> - void progress_ProgressChanged(object sender, double e) - { - CurrentProgress = e; - } - - /// <summary> - /// Stops the task if it is currently executing - /// </summary> - /// <exception cref="System.InvalidOperationException">Cannot cancel a Task unless it is in the Running state.</exception> - public void Cancel() - { - if (State != TaskState.Running) - { - throw new InvalidOperationException("Cannot cancel a Task unless it is in the Running state."); - } - - CancelIfRunning(); - } - - /// <summary> - /// Cancels if running. - /// </summary> - public void CancelIfRunning() - { - if (State == TaskState.Running) - { - Logger.Info("Attempting to cancel Scheduled Task {0}", Name); - CurrentCancellationTokenSource.Cancel(); - } - } - - /// <summary> - /// Performs application-defined tasks associated with freeing, releasing, or resetting unmanaged resources. - /// </summary> - public void Dispose() - { - Dispose(true); - GC.SuppressFinalize(this); - } - - /// <summary> - /// Releases unmanaged and - optionally - managed resources. - /// </summary> - /// <param name="dispose"><c>true</c> to release both managed and unmanaged resources; <c>false</c> to release only unmanaged resources.</param> - protected virtual void Dispose(bool dispose) - { - if (dispose) - { - DisposeTriggers(); - - if (State == TaskState.Running) - { - TaskManager.OnTaskCompleted(this, CurrentExecutionStartTime, DateTime.UtcNow, TaskCompletionStatus.Aborted); - } - - if (CurrentCancellationTokenSource != null) - { - CurrentCancellationTokenSource.Dispose(); - } - } - } - - /// <summary> - /// Disposes each trigger - /// </summary> - private void DisposeTriggers() - { - foreach (var trigger in Triggers) - { - trigger.Triggered -= trigger_Triggered; - trigger.Stop(); - } - } - } -} diff --git a/MediaBrowser.Common/ScheduledTasks/IScheduledTask.cs b/MediaBrowser.Common/ScheduledTasks/IScheduledTask.cs index 6f3a3857fe..351e96c7d5 100644 --- a/MediaBrowser.Common/ScheduledTasks/IScheduledTask.cs +++ b/MediaBrowser.Common/ScheduledTasks/IScheduledTask.cs @@ -1,40 +1,16 @@ -using MediaBrowser.Model.Tasks; -using System; +using System; using System.Collections.Generic; +using System.Threading; using System.Threading.Tasks; namespace MediaBrowser.Common.ScheduledTasks { /// <summary> - /// Interface IScheduledTask + /// Interface IScheduledTaskWorker /// </summary> - public interface IScheduledTask : IDisposable + public interface IScheduledTask { /// <summary> - /// Gets the triggers. - /// </summary> - /// <value>The triggers.</value> - IEnumerable<ITaskTrigger> Triggers { get; set; } - - /// <summary> - /// Gets the last execution result. - /// </summary> - /// <value>The last execution result.</value> - TaskResult LastExecutionResult { get; } - - /// <summary> - /// Gets the state. - /// </summary> - /// <value>The state.</value> - TaskState State { get; } - - /// <summary> - /// Gets the current progress. - /// </summary> - /// <value>The current progress.</value> - double? CurrentProgress { get; } - - /// <summary> /// Gets the name of the task /// </summary> /// <value>The name.</value> @@ -53,28 +29,12 @@ namespace MediaBrowser.Common.ScheduledTasks string Category { get; } /// <summary> - /// Gets the unique id. - /// </summary> - /// <value>The unique id.</value> - Guid Id { get; } - - /// <summary> /// Executes the task /// </summary> + /// <param name="cancellationToken">The cancellation token.</param> + /// <param name="progress">The progress.</param> /// <returns>Task.</returns> - /// <exception cref="System.InvalidOperationException">Cannot execute a Task that is already running</exception> - Task Execute(); - - /// <summary> - /// Stops the task if it is currently executing - /// </summary> - /// <exception cref="System.InvalidOperationException">Cannot cancel a Task unless it is in the Running state.</exception> - void Cancel(); - - /// <summary> - /// Cancels if running. - /// </summary> - void CancelIfRunning(); + Task Execute(CancellationToken cancellationToken, IProgress<double> progress); /// <summary> /// Gets the default triggers. @@ -82,4 +42,4 @@ namespace MediaBrowser.Common.ScheduledTasks /// <returns>IEnumerable{BaseTaskTrigger}.</returns> IEnumerable<ITaskTrigger> GetDefaultTriggers(); } -}
\ No newline at end of file +} diff --git a/MediaBrowser.Common/ScheduledTasks/IScheduledTaskWorker.cs b/MediaBrowser.Common/ScheduledTasks/IScheduledTaskWorker.cs new file mode 100644 index 0000000000..31cb4bcb89 --- /dev/null +++ b/MediaBrowser.Common/ScheduledTasks/IScheduledTaskWorker.cs @@ -0,0 +1,86 @@ +using MediaBrowser.Model.Tasks; +using System; +using System.Collections.Generic; +using System.Threading.Tasks; + +namespace MediaBrowser.Common.ScheduledTasks +{ + /// <summary> + /// Interface IScheduledTaskWorker + /// </summary> + public interface IScheduledTaskWorker : IDisposable + { + /// <summary> + /// Gets or sets the scheduled task. + /// </summary> + /// <value>The scheduled task.</value> + IScheduledTask ScheduledTask { get; } + + /// <summary> + /// Gets the last execution result. + /// </summary> + /// <value>The last execution result.</value> + TaskResult LastExecutionResult { get; } + + /// <summary> + /// Gets the name. + /// </summary> + /// <value>The name.</value> + string Name { get; } + + /// <summary> + /// Gets the description. + /// </summary> + /// <value>The description.</value> + string Description { get; } + + /// <summary> + /// Gets the category. + /// </summary> + /// <value>The category.</value> + string Category { get; } + + /// <summary> + /// Gets the state. + /// </summary> + /// <value>The state.</value> + TaskState State { get; } + + /// <summary> + /// Gets the current progress. + /// </summary> + /// <value>The current progress.</value> + double? CurrentProgress { get; } + + /// <summary> + /// Gets the triggers that define when the task will run + /// </summary> + /// <value>The triggers.</value> + /// <exception cref="System.ArgumentNullException">value</exception> + IEnumerable<ITaskTrigger> Triggers { get; set; } + + /// <summary> + /// Gets the unique id. + /// </summary> + /// <value>The unique id.</value> + Guid Id { get; } + + /// <summary> + /// Executes the task + /// </summary> + /// <returns>Task.</returns> + /// <exception cref="System.InvalidOperationException">Cannot execute a Task that is already running</exception> + Task Execute(); + + /// <summary> + /// Stops the task if it is currently executing + /// </summary> + /// <exception cref="System.InvalidOperationException">Cannot cancel a Task unless it is in the Running state.</exception> + void Cancel(); + + /// <summary> + /// Cancels if running. + /// </summary> + void CancelIfRunning(); + } +}
\ No newline at end of file diff --git a/MediaBrowser.Common/ScheduledTasks/ITaskManager.cs b/MediaBrowser.Common/ScheduledTasks/ITaskManager.cs index 42d7020e60..d06f1f1946 100644 --- a/MediaBrowser.Common/ScheduledTasks/ITaskManager.cs +++ b/MediaBrowser.Common/ScheduledTasks/ITaskManager.cs @@ -1,5 +1,4 @@ -using MediaBrowser.Model.Tasks; -using System; +using System; using System.Collections.Generic; namespace MediaBrowser.Common.ScheduledTasks @@ -10,7 +9,7 @@ namespace MediaBrowser.Common.ScheduledTasks /// Gets the list of Scheduled Tasks /// </summary> /// <value>The scheduled tasks.</value> - IScheduledTask[] ScheduledTasks { get; } + IScheduledTaskWorker[] ScheduledTasks { get; } /// <summary> /// Cancels if running and queue. @@ -37,35 +36,5 @@ namespace MediaBrowser.Common.ScheduledTasks /// </summary> /// <param name="tasks">The tasks.</param> void AddTasks(IEnumerable<IScheduledTask> tasks); - - /// <summary> - /// Called when [task completed]. - /// </summary> - /// <param name="task">The task.</param> - /// <param name="startTime">The start time.</param> - /// <param name="endTime">The end time.</param> - /// <param name="status">The status.</param> - void OnTaskCompleted(IScheduledTask task, DateTime startTime, DateTime endTime, TaskCompletionStatus status); - - /// <summary> - /// Gets the last execution result. - /// </summary> - /// <param name="task">The task.</param> - /// <returns>TaskResult.</returns> - TaskResult GetLastExecutionResult(IScheduledTask task); - - /// <summary> - /// Loads the triggers. - /// </summary> - /// <param name="task">The task.</param> - /// <returns>IEnumerable{BaseTaskTrigger}.</returns> - IEnumerable<ITaskTrigger> LoadTriggers(IScheduledTask task); - - /// <summary> - /// Saves the triggers. - /// </summary> - /// <param name="task">The task.</param> - /// <param name="triggers">The triggers.</param> - void SaveTriggers(IScheduledTask task, IEnumerable<ITaskTrigger> triggers); } }
\ No newline at end of file diff --git a/MediaBrowser.Common/ScheduledTasks/ScheduledTaskHelpers.cs b/MediaBrowser.Common/ScheduledTasks/ScheduledTaskHelpers.cs index 2c3d21a4b0..ebfc94591e 100644 --- a/MediaBrowser.Common/ScheduledTasks/ScheduledTaskHelpers.cs +++ b/MediaBrowser.Common/ScheduledTasks/ScheduledTaskHelpers.cs @@ -14,7 +14,7 @@ namespace MediaBrowser.Common.ScheduledTasks /// </summary> /// <param name="task">The task.</param> /// <returns>TaskInfo.</returns> - public static TaskInfo GetTaskInfo(IScheduledTask task) + public static TaskInfo GetTaskInfo(IScheduledTaskWorker task) { return new TaskInfo { |
