Browse Source

Merge pull request #2025 from softworkz/AsyncStreamInterface

Async stream handling: Use interface instead of Func<Stream,Task>
Luke 8 years ago
parent
commit
02a4b90f65

+ 2 - 2
MediaBrowser.Api/Playback/Progressive/BaseProgressiveStreamingService.cs

@@ -370,9 +370,9 @@ namespace MediaBrowser.Api.Playback.Progressive
                     outputHeaders[item.Key] = item.Value;
                 }
 
-                Func<Stream, Task> streamWriter = stream => new ProgressiveFileCopier(FileSystem, job, Logger).StreamFile(outputPath, stream, CancellationToken.None);
+                var streamSource = new ProgressiveFileCopier(FileSystem, outputPath, outputHeaders, job, Logger, CancellationToken.None);
 
-                return ResultFactory.GetAsyncStreamWriter(streamWriter, outputHeaders);
+                return ResultFactory.GetAsyncStreamWriter(streamSource);
             }
             finally
             {

+ 20 - 3
MediaBrowser.Api/Playback/Progressive/ProgressiveStreamWriter.cs

@@ -4,28 +4,45 @@ using System.IO;
 using System.Threading;
 using System.Threading.Tasks;
 using CommonIO;
+using MediaBrowser.Controller.Net;
+using System.Collections.Generic;
+using ServiceStack.Web;
 
 namespace MediaBrowser.Api.Playback.Progressive
 {
-    public class ProgressiveFileCopier
+    public class ProgressiveFileCopier : IAsyncStreamSource, IHasOptions
     {
         private readonly IFileSystem _fileSystem;
         private readonly TranscodingJob _job;
         private readonly ILogger _logger;
+        private readonly string _path;
+        private readonly CancellationToken _cancellationToken;
+        private readonly Dictionary<string, string> _outputHeaders;
 
         // 256k
         private const int BufferSize = 81920;
 
         private long _bytesWritten = 0;
 
-        public ProgressiveFileCopier(IFileSystem fileSystem, TranscodingJob job, ILogger logger)
+        public ProgressiveFileCopier(IFileSystem fileSystem, string path, Dictionary<string, string> outputHeaders, TranscodingJob job, ILogger logger, CancellationToken cancellationToken)
         {
             _fileSystem = fileSystem;
+            _path = path;
+            _outputHeaders = outputHeaders;
             _job = job;
             _logger = logger;
+            _cancellationToken = cancellationToken;
         }
 
-        public async Task StreamFile(string path, Stream outputStream, CancellationToken cancellationToken)
+        public IDictionary<string, string> Options
+        {
+            get
+            {
+                return _outputHeaders;
+            }
+        }
+
+        public async Task WriteToAsync(Stream outputStream)
         {
             try
             {

+ 1 - 0
MediaBrowser.Controller/MediaBrowser.Controller.csproj

@@ -236,6 +236,7 @@
     <Compile Include="Net\IAuthorizationContext.cs" />
     <Compile Include="Net\IAuthService.cs" />
     <Compile Include="Net\IHasAuthorization.cs" />
+    <Compile Include="Net\IAsyncStreamSource.cs" />
     <Compile Include="Net\IHasResultFactory.cs" />
     <Compile Include="Net\IHasSession.cs" />
     <Compile Include="Net\IHttpResultFactory.cs" />

+ 18 - 0
MediaBrowser.Controller/Net/IAsyncStreamSource.cs

@@ -0,0 +1,18 @@
+using ServiceStack.Web;
+using System.IO;
+using System.Threading.Tasks;
+
+namespace MediaBrowser.Controller.Net
+{
+    /// <summary>
+    /// Interface IAsyncStreamSource
+    /// Enables asynchronous writing to http resonse streams
+    /// </summary>
+    public interface IAsyncStreamSource
+    {
+        /// <summary>
+        /// Asynchronously write to the response stream.
+        /// </summary>
+        Task WriteToAsync(Stream responseStream);
+    }
+}

+ 1 - 1
MediaBrowser.Controller/Net/IHttpResultFactory.cs

@@ -28,7 +28,7 @@ namespace MediaBrowser.Controller.Net
         /// <returns>System.Object.</returns>
         object GetResult(object content, string contentType, IDictionary<string,string> responseHeaders = null);
 
-        object GetAsyncStreamWriter(Func<Stream,Task> streamWriter, IDictionary<string, string> responseHeaders = null);
+        object GetAsyncStreamWriter(IAsyncStreamSource streamSource);
 
         /// <summary>
         /// Gets the optimized result.

+ 19 - 16
MediaBrowser.Server.Implementations/HttpServer/AsyncStreamWriterFunc.cs → MediaBrowser.Server.Implementations/HttpServer/AsyncStreamWriter.cs

@@ -4,38 +4,41 @@ using System.IO;
 using System.Threading.Tasks;
 using ServiceStack;
 using ServiceStack.Web;
+using MediaBrowser.Controller.Net;
 
 namespace MediaBrowser.Server.Implementations.HttpServer
 {
-    public class AsyncStreamWriterFunc : IStreamWriter, IAsyncStreamWriter, IHasOptions
+    public class AsyncStreamWriter : IStreamWriter, IAsyncStreamWriter, IHasOptions
     {
         /// <summary>
         /// Gets or sets the source stream.
         /// </summary>
         /// <value>The source stream.</value>
-        private Func<Stream, Task> Writer { get; set; }
-
-        /// <summary>
-        /// Gets the options.
-        /// </summary>
-        /// <value>The options.</value>
-        public IDictionary<string, string> Options { get; private set; }
+        private IAsyncStreamSource _source;
 
         public Action OnComplete { get; set; }
         public Action OnError { get; set; }
 
         /// <summary>
-        /// Initializes a new instance of the <see cref="StreamWriter" /> class.
+        /// Initializes a new instance of the <see cref="AsyncStreamWriter" /> class.
         /// </summary>
-        public AsyncStreamWriterFunc(Func<Stream, Task> writer, IDictionary<string, string> headers)
+        public AsyncStreamWriter(IAsyncStreamSource source)
         {
-            Writer = writer;
+            _source = source;
+        }
 
-            if (headers == null)
+        public IDictionary<string, string> Options
+        {
+            get
             {
-                headers = new Dictionary<string, string>(StringComparer.OrdinalIgnoreCase);
+                var hasOptions = _source as IHasOptions;
+                if (hasOptions != null)
+                {
+                    return hasOptions.Options;
+                }
+
+                return new Dictionary<string, string>(StringComparer.OrdinalIgnoreCase);
             }
-            Options = headers;
         }
 
         /// <summary>
@@ -44,13 +47,13 @@ namespace MediaBrowser.Server.Implementations.HttpServer
         /// <param name="responseStream">The response stream.</param>
         public void WriteTo(Stream responseStream)
         {
-            var task = Writer(responseStream);
+            var task = _source.WriteToAsync(responseStream);
             Task.WaitAll(task);
         }
 
         public async Task WriteToAsync(Stream responseStream)
         {
-            await Writer(responseStream).ConfigureAwait(false);
+            await _source.WriteToAsync(responseStream).ConfigureAwait(false);
         }
     }
 }

+ 2 - 2
MediaBrowser.Server.Implementations/HttpServer/HttpResultFactory.cs

@@ -704,9 +704,9 @@ namespace MediaBrowser.Server.Implementations.HttpServer
             throw error;
         }
 
-        public object GetAsyncStreamWriter(Func<Stream, Task> streamWriter, IDictionary<string, string> responseHeaders = null)
+        public object GetAsyncStreamWriter(IAsyncStreamSource streamSource)
         {
-            return new AsyncStreamWriterFunc(streamWriter, responseHeaders);
+            return new AsyncStreamWriter(streamSource);
         }
     }
 }

+ 1 - 1
MediaBrowser.Server.Implementations/MediaBrowser.Server.Implementations.csproj

@@ -156,7 +156,7 @@
     <Compile Include="EntryPoints\ServerEventNotifier.cs" />
     <Compile Include="EntryPoints\UserDataChangeNotifier.cs" />
     <Compile Include="FileOrganization\OrganizerScheduledTask.cs" />
-    <Compile Include="HttpServer\AsyncStreamWriterFunc.cs" />
+    <Compile Include="HttpServer\AsyncStreamWriter.cs" />
     <Compile Include="HttpServer\IHttpListener.cs" />
     <Compile Include="HttpServer\Security\AuthorizationContext.cs" />
     <Compile Include="HttpServer\ContainerAdapter.cs" />