예제 #1
0
        public CrawlerPropagator(
            ITargetBlock <Submission> submissionOutput,
            ITargetBlock <CrawlerError> errorOutput)
        {
            _submissionOutput = submissionOutput;
            _errorOutput      = errorOutput;

            _input = InitInputBlock();
            _queue = new Queue <CrawlerMessage>(BufferCapacity);

            Completion = _input.Completion.ContinueWith(task =>
            {
                if (task.IsFaulted)
                {
                    _submissionOutput.Fault(task.Exception);
                    _errorOutput.Fault(task.Exception);
                }
                else
                {
                    // TODO: handle cancel
                    _submissionOutput.Complete();
                    _errorOutput.Complete();
                }
            });
        }
예제 #2
0
        /// <inheritdoc cref="ISourceBlock{TOutput}.LinkTo(ITargetBlock{TOutput}, DataflowLinkOptions)"/>
        public IDisposable LinkTo(ITargetBlock <TOutput> target, DataflowLinkOptions linkOptions)
        {
            if (target == null)
            {
                throw new ArgumentNullException(nameof(target));
            }
            linkOptions ??= new DataflowLinkOptions();

            LinkRegistration <TOutput> registration;

            lock (this.Lock)
            {
                if (this._propagatedCompletion)
                {
                    var exception = this.Completion.Exception;
                    if (exception == null)
                    {
                        target.Complete();
                    }
                    else
                    {
                        target.Fault(exception);
                    }

                    return(ActionDisposable.Nop);
                }

                registration = new LinkRegistration <TOutput>(target, linkOptions.MaxMessages, linkOptions.PropagateCompletion, this.HandleUnlink);
                this._linkManager.AddLink(registration, linkOptions.Append);
            }

            this.OfferToTargets();

            return(new ActionDisposable(registration.Unlink));
        }
예제 #3
0
        public static async Task SendAndCompleteAsync <T>(this ITargetBlock <T> target, IEnumerable <T> items, CancellationToken cancelToken = default(CancellationToken))
        {
            await Task.Yield();

            try
            {
                foreach (var item in items)
                {
                    if (target.Completion.IsFaulted)
                    {
                        throw target.Completion.Exception;
                    }

                    if (!await target.SendAsync(item, cancelToken))
                    {
                        throw new InvalidOperationException();
                    }

                    cancelToken.ThrowIfCancellationRequested();
                }

                target.Complete();
            }
            catch (Exception ex)
            {
                target.Fault(ex);
                throw;
            }
        }
예제 #4
0
        /// <summary>
        /// Adds a target block to send messages to.
        /// </summary>
        /// <returns>
        /// An object that can be used to destroy the link to the added target.
        /// </returns>
        public IDisposable AddTarget(ITargetBlock <T> targetBlock, DataflowLinkOptions options)
        {
            CancellationTokenSource cancellationTokenSource = null;

            if (options.PropagateCompletion)
            {
                cancellationTokenSource = new CancellationTokenSource();
                block.Completion.ContinueWith(t =>
                {
                    if (t.IsFaulted)
                    {
                        targetBlock.Fault(t.Exception);
                    }
                    else
                    {
                        targetBlock.Complete();
                    }
                }, cancellationTokenSource.Token);
            }

            var target = new Target(
                this, targetBlock, options.MaxMessages, cancellationTokenSource);

            TargetDictionary [targetBlock] = target;
            if (options.Append)
            {
                appendQueue.Enqueue(target);
            }
            else
            {
                prependQueue.Enqueue(target);
            }

            return(target);
        }
예제 #5
0
        /// <summary>
        /// Links an action to this block. Usefull if it's an action block.
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="target"></param>
        /// <returns></returns>
        public IFlowBlock BroadcastTo(ITargetBlock <TOut> target, bool linkToCompletion = true)
        {
            ItemProcessed += (x) =>
            {
                DataflowBlock.SendAsync(target, x).Wait();
            };
            if (linkToCompletion)
            {
                AddCompletionTask(target.Completion);
            }
            var actionBlock = this.GetProcessingBlock();

            actionBlock.Completion.ContinueWith(t =>
            {
                if (t.IsFaulted)
                {
                    target.Fault(t.Exception);
                }
                else
                {
                    target.Complete();
                }
            });
            //_lastLinkedBlock = target;
            return(this);
        }
예제 #6
0
        IDisposable ISourceBlock <T> .LinkTo(ITargetBlock <T> target, DataflowLinkOptions?linkOptions)
        {
            if (target == null)
            {
                throw new ArgumentNullException(nameof(target));
            }
            linkOptions ??= new DataflowLinkOptions();

            LinkRegistration <T> registration;

            lock (this.CompletionLock)
            {
                if (this.Completion.IsCompleted)
                {
                    var exception = this.Completion.Exception;
                    if (exception == null)
                    {
                        target.Complete();
                    }
                    else
                    {
                        target.Fault(exception);
                    }

                    return(ActionDisposable.Nop);
                }

                registration = new LinkRegistration <T>(target, linkOptions.MaxMessages, linkOptions.PropagateCompletion, this.HandleUnlink);
                this._linkManager.AddLink(registration, linkOptions.Append);
            }

            this._resetEvent.Set();

            return(new ActionDisposable(registration.Unlink));
        }
예제 #7
0
 /// <summary>
 /// Watches the task, and shuts down the dataflow block (via <see cref="IDataflowBlock.Fault"/> or <see cref="IDataflowBlock.Complete"/>) when the task completes.
 /// </summary>
 /// <param name="task">The task to watch. May not be <c>null</c>.</param>
 public void ObserveTaskForCompletion(Task task)
 {
     task.ContinueWith(_ =>
     {
         if (task.IsFaulted)
         {
             _block.Fault(task.Exception.InnerException);
         }
         else
         {
             _block.Complete();
         }
     }, TaskScheduler.Default);
 }
예제 #8
0
 /// <summary>
 /// Runs when any of <see cref="_innerBlock"/> or <see cref="_outputBlock"/> faults
 /// </summary>
 /// <param name="faultedTask">Completion property of the faulted DataflowBlock</param>
 private void OnAnyBlockFaulted(Task faultedTask)
 {
     // When one of the two DataflowBlocks faults, the faulted state is propagated to the following
     // DataflowBlocks, but not to the preceding DataflowBlocks. In this case we therefore fault all DataflowBlocks
     // that are not yet in a faulted state to ensure that all DataflowBlocks are completed and release their resources.
     if (!_innerBlock.Completion.IsFaulted)
     {
         _innerBlock.Fault(faultedTask.Exception);
     }
     if (!_outputBlock.Completion.IsFaulted)
     {
         _outputBlock.Fault(faultedTask.Exception);
     }
 }
예제 #9
0
 private static void LinkDataflowBlocks <TBlock>(ISourceBlock <TBlock> source, ITargetBlock <TBlock> target)
 {
     source.LinkTo(target);
     source.Completion.ContinueWith(t =>
     {
         if (t.IsFaulted)
         {
             target.Fault(t.Exception);
         }
         else
         {
             target.Complete();
         }
     });
 }
예제 #10
0
 public static void DeriveCompletionOrFaultFrom <TData>(this ITargetBlock <TData> target, IEnumerable <ISourceBlock <TData> > sources)
 {
     Task.WhenAll(sources.Select(x => x.Completion))
     .ContinueWith(x =>
     {
         if (x.IsFaulted)
         {
             target.Fault(x.Exception);
         }
         else
         {
             target.Complete();
         }
     });
 }
예제 #11
0
 public async void Fault(Exception exception)
 {
     if (_target != null)
     {
         _target.Fault(exception);
     }
     //if (_source != null)
     //    _source.Fault(exception);
     if (_target != null)
     {
         await _target.Completion;
     }
     //if (_source != null)
     //    await _source.Completion;
     Dispose();
 }
 public static async Task WriteToBlockAsync <T>(this IAsyncEnumerable <T> enumerable,
                                                ITargetBlock <T> block, CancellationToken token = default)
 {
     try
     {
         await foreach (var item in enumerable.WithCancellation(token).ConfigureAwait(false))
         {
             await block.SendAsync(item, token).ConfigureAwait(false);
         }
         block.Complete();
     }
     catch (Exception ex)
     {
         block.Fault(ex);
     }
 }
            private async Task ReadAheadAsync()
            {
                Assumes.NotNull(this.readAheadElements);
                try
                {
                    while (await this.enumerator.MoveNextAsync().ConfigureAwait(false))
                    {
                        await this.readAheadElements.SendAsync(this.enumerator.Current, this.cancellationTokenSource.Token).ConfigureAwait(false);
                    }

                    this.readAheadElements.Complete();
                }
                catch (Exception ex)
                {
                    ITargetBlock <T> target = this.readAheadElements;
                    target.Fault(ex);
                }
            }
            private async Task ReadAheadAsync()
            {
                Assumes.NotNull(this.readAheadElements);
                try
                {
                    while (await this.enumerator.MoveNextAsync().ConfigureAwait(false))
                    {
                        await this.readAheadElements.SendAsync(this.enumerator.Current, this.cancellationTokenSource.Token).ConfigureAwait(false);
                    }

                    this.readAheadElements.Complete();
                }
#pragma warning disable CA1031 // Do not catch general exception types
                catch (Exception ex)
#pragma warning restore CA1031 // Do not catch general exception types
                {
                    ITargetBlock <T> target = this.readAheadElements;
                    target.Fault(ex);
                }
            }
예제 #15
0
        public async Task PostList(ITargetBlock <Core.Entities.BankAccount> target)
        {
            Diag.ThreadPrint("PostList - start");

            var transform = new TransformBlock <BankAccount, Core.Entities.BankAccount>(ef =>
                                                                                        mapper.Map <Core.Entities.BankAccount>(ef), new ExecutionDataflowBlockOptions()
            {
                MaxDegreeOfParallelism = 4
            });

            transform.LinkTo(target);

            await Task.Run(() =>
            {
                Diag.ThreadPrint("PostList - task start");

                using (FinanceEntities context = factory.CreateContext())
                {
                    (from b in context.BankAccounts.Include(a => a.Bank)
                     select b).AsParallel().ForAll(ef => transform.Post(ef));
                    //await transform.Completion;
                    transform.Completion.ContinueWith(t =>
                    {
                        if (t.IsFaulted)
                        {
                            target.Fault(t.Exception);
                        }
                        else
                        {
                            Diag.ThreadPrint("PostList - task set target complete");
                            target.Complete();
                        }
                    });
                    transform.Complete();
                }
                Diag.ThreadPrint("PostList - task end");
            }).ConfigureAwait(false);

            Diag.ThreadPrint("PostList - end");
        }
예제 #16
0
        private async Task ReadMessageAsync(ITargetBlock <string> target)
        {
            string message = null;
            var    buffer  = new byte[1024 * 4];
            var    segment = new ArraySegment <byte>(buffer);

            using (var memoryStream = new MemoryStream())
            {
                try
                {
                    WebSocketReceiveResult receiveResult;

                    do
                    {
                        receiveResult = await _socket.ReceiveAsync(segment, CancellationToken.None);

                        if (receiveResult.CloseStatus.HasValue)
                        {
                            target.Complete();
                        }

                        if (receiveResult.Count == 0)
                        {
                            continue;
                        }

                        await memoryStream.WriteAsync(segment.Array, segment.Offset, receiveResult.Count);
                    } while (!receiveResult.EndOfMessage || memoryStream.Length == 0);

                    message = Encoding.UTF8.GetString(memoryStream.ToArray());
                }
                catch (Exception x)
                {
                    target.Fault(x);
                }
            }

            await target.SendAsync(message);
        }
예제 #17
0
        public static void PostAndComplete <T>(this ITargetBlock <T> target, IEnumerable <T> items, CancellationToken cancelToken = default(CancellationToken))
        {
            try
            {
                foreach (var item in items)
                {
                    if (!target.Post(item))
                    {
                        throw new InvalidOperationException();
                    }

                    cancelToken.ThrowIfCancellationRequested();
                }

                target.Complete();
            }
            catch (Exception ex)
            {
                target.Fault(ex);
                throw;
            }
        }
예제 #18
0
        /// <summary>
        /// Links this block to a target block.
        ///
        /// The target block receives all items accepted by the provided listener.
        ///
        /// Completion of this block can optionally be propagated to the target block.
        /// </summary>
        public void LinkTo(ITargetBlock <TOutput> target, bool propagateCompletion = true)
        {
            Contract.Requires(target != null);

            m_targetBlock = target;

            if (propagateCompletion)
            {
                Completion.ContinueWith(t =>
                {
                    if (t.IsFaulted)
                    {
                        Verbose("Propagating fault completion");
                        m_targetBlock.Fault(t.Exception.InnerException);
                    }
                    else
                    {
                        Verbose("Propagating completion");
                        m_targetBlock.Complete();
                    }
                });
            }
        }
 void IDataflowBlock.Fault(Exception exception) => consumer.Fault(exception);
예제 #20
0
 public void OnError(Exception ex)
 {
     target.Fault(ex);
 }
예제 #21
0
 public void Fault(Exception ex)
 {
     compHelper.Fault(ex);
     source.Fault(ex);
     target.Fault(ex);
 }
예제 #22
0
 /// <summary>
 /// Causes the <see cref="IDataflowBlock"/> to complete in a Faulted state.
 /// </summary>
 /// <param name="exception">The <see cref="Exception"/> that caused the faulting.</param>
 /// <seealso cref="IDataflowBlock"/>
 public void Fault(Exception exception)
 {
     _target.Fault(exception);
 }
예제 #23
0
 public void Fault(Exception exception)
 {
     targetBlock.Fault(exception);
 }
예제 #24
0
 public void Fault(Exception exception)
 {
     _targetBroadcastBlock.Fault(exception);
 }
 public void Fault(Exception exception)
 {
     _originalTargetBlock.Fault(exception);
 }
예제 #26
0
 public void Fault(Exception exception)
 {
     _bufferBlock.Fault(exception);
 }
예제 #27
0
        private async Task ReadMessageAsync(ITargetBlock <string> target)
        {
            while (!_socket.CloseStatus.HasValue)
            {
                string message;
                byte[] buffer  = new byte[1024 * 4];
                var    segment = new ArraySegment <byte>(buffer);

                using (var memoryStream = new MemoryStream())
                {
                    try
                    {
                        WebSocketReceiveResult receiveResult;

                        do
                        {
                            receiveResult = await _socket.ReceiveAsync(segment, CancellationToken.None);

                            if (receiveResult.CloseStatus.HasValue)
                            {
                                target.Complete();
                            }

                            if (receiveResult.Count == 0)
                            {
                                continue;
                            }

                            await memoryStream.WriteAsync(segment.Array, segment.Offset, receiveResult.Count);
                        } while (!receiveResult.EndOfMessage || memoryStream.Length == 0);

                        message = Encoding.UTF8.GetString(memoryStream.ToArray());
                    }
                    catch (WebSocketException wx)
                    {
                        WebSocketCloseStatus closeStatus;

                        switch (wx.WebSocketErrorCode)
                        {
                        case WebSocketError.ConnectionClosedPrematurely:
                        case WebSocketError.HeaderError:
                        case WebSocketError.UnsupportedProtocol:
                        case WebSocketError.UnsupportedVersion:
                        case WebSocketError.NotAWebSocket:
                            closeStatus = WebSocketCloseStatus.ProtocolError;
                            break;

                        case WebSocketError.InvalidMessageType:
                            closeStatus = WebSocketCloseStatus.InvalidMessageType;
                            break;

                        default:
                            closeStatus = WebSocketCloseStatus.InternalServerError;
                            break;
                        }

                        await Complete(closeStatus, $"Closing socket connection due to {wx.WebSocketErrorCode}.");

                        break;
                    }
                    catch (Exception x)
                    {
                        target.Fault(x);
                        continue;
                    }
                }

                await target.SendAsync(message);
            }
        }
예제 #28
0
 public void Fault(Exception error)
 {
     m_target.Fault(error);
 }
예제 #29
0
 public void Fault(Exception exception)
 {
     _input.Fault(exception);
 }
예제 #30
0
 public void OnError(Exception error)
 {
     _block.Fault(error);
 }
        public async Task PostList(ITargetBlock<Core.Entities.BankAccount> target)
        {
            Diag.ThreadPrint("PostList - start");

            var transform = new TransformBlock<BankAccount, Core.Entities.BankAccount>(ef =>
                 mapper.Map<Core.Entities.BankAccount>(ef), new ExecutionDataflowBlockOptions() { MaxDegreeOfParallelism = 4 });

            transform.LinkTo(target);

            await Task.Run(() => 
            {
                Diag.ThreadPrint("PostList - task start");

                using (FinanceEntities context = factory.CreateContext())
                {
                    (from b in context.BankAccounts.Include(a => a.Bank)
                     select b).AsParallel().ForAll(ef => transform.Post(ef));
                    //await transform.Completion;
                    transform.Completion.ContinueWith(t =>
                    {
                        if (t.IsFaulted) target.Fault(t.Exception);
                        else
                        {
                            Diag.ThreadPrint("PostList - task set target complete");
                            target.Complete();
                        }
                    });
                    transform.Complete();
                }
                Diag.ThreadPrint("PostList - task end");
            }).ConfigureAwait(false);

            Diag.ThreadPrint("PostList - end");
        }