예제 #1
0
        public void PushReceiveMetrics(ReceiveMetrics receiveMetrics)
        {
            Task.Run(() =>
            {
                IObserver <ReceiveMetrics>[] observers;
                lock (receiveMetricsObserverLock)
                {
                    observers = receiveMetricsObservers.ToArray();
                }

                foreach (var observer in observers)
                {
                    observer.OnNext(receiveMetrics);
                }
            }).Fork();
        }
예제 #2
0
        async Task ReceiveTask(string path)
        {
            var receiver = new MessageReceiver(this.Settings.ConnectionString, path, this.Settings.ReceiveMode);

            receiver.PrefetchCount = Settings.PrefetchCount;
            var  semaphore     = new DynamicSemaphoreSlim(this.Settings.MaxInflightReceives.Value + 1);
            var  done          = new SemaphoreSlim(1); done.Wait();
            var  sw            = Stopwatch.StartNew();
            long totalReceives = 0;
            await Task.Delay(TimeSpan.FromMilliseconds(Settings.WorkDuration));

            this.Settings.MaxInflightReceives.Changing += (a, e) => AdjustSemaphore(e, semaphore);

            for (int j = 0; j < Settings.MessageCount && !this.CancellationToken.IsCancellationRequested; j++)
            {
                var receiveMetrics = new ReceiveMetrics()
                {
                    Tick = sw.ElapsedTicks
                };

                var nsec = sw.ElapsedTicks;
                await semaphore.WaitAsync().ConfigureAwait(false);

                receiveMetrics.GateLockDuration100ns = sw.ElapsedTicks - nsec;

                if (Settings.ReceiveBatchCount <= 1)
                {
                    nsec = sw.ElapsedTicks;
                    // we're going to unblock the receives after 10 seconds if there's no pending message
                    receiver.ReceiveAsync(TimeSpan.FromSeconds(10)).ContinueWith(async(t) =>
                    {
                        receiveMetrics.ReceiveDuration100ns = sw.ElapsedTicks - nsec;
                        if (t.IsFaulted || t.IsCanceled || t.Result == null)
                        {
                            if (t.Exception?.GetType() == typeof(ServerBusyException))
                            {
                                receiveMetrics.BusyErrors = 1;
                                if (!this.CancellationToken.IsCancellationRequested)
                                {
                                    await Task.Delay(3000, this.CancellationToken).ConfigureAwait(false);
                                }
                            }
                            else
                            {
                                receiveMetrics.Errors = 1;
                            }
                            Metrics.PushReceiveMetrics(receiveMetrics);
                            semaphore.Release();
                            if (Interlocked.Increment(ref totalReceives) >= Settings.MessageCount)
                            {
                                done.Release();
                            }
                        }
                        else
                        {
                            receiveMetrics.Receives = receiveMetrics.Messages = 1;
                            nsec = sw.ElapsedTicks;

                            // simulate work by introducing a delay, if needed
                            if (Settings.WorkDuration > 0)
                            {
                                await Task.Delay(TimeSpan.FromMilliseconds(Settings.WorkDuration));
                            }
                            receiver.CompleteAsync(t.Result.SystemProperties.LockToken).ContinueWith(async(t1) =>
                            {
                                receiveMetrics.CompleteDuration100ns = sw.ElapsedTicks - nsec;
                                if (t1.IsFaulted)
                                {
                                    if (t1.Exception?.GetType() == typeof(ServerBusyException))
                                    {
                                        receiveMetrics.BusyErrors = 1;
                                        if (!this.CancellationToken.IsCancellationRequested)
                                        {
                                            await Task.Delay(3000, this.CancellationToken).ConfigureAwait(false);
                                        }
                                    }
                                    else
                                    {
                                        receiveMetrics.Errors = 1;
                                    }
                                }
                                else
                                {
                                    receiveMetrics.Completions = receiveMetrics.CompleteCalls = 1;
                                }
                                Metrics.PushReceiveMetrics(receiveMetrics);
                                semaphore.Release();
                                if (Interlocked.Increment(ref totalReceives) >= Settings.MessageCount)
                                {
                                    done.Release();
                                }
                            }).Fork();
                        };
                    }).Fork();
                }
                else
                {
                    nsec = sw.ElapsedTicks;
                    // we're going to unblock the receives after 10 seconds if there's no pending message
                    receiver.ReceiveAsync(Settings.ReceiveBatchCount, TimeSpan.FromSeconds(10)).ContinueWith(async(t) =>
                    {
                        receiveMetrics.ReceiveDuration100ns = sw.ElapsedTicks - nsec;
                        if (t.IsFaulted || t.IsCanceled || t.Result == null)
                        {
                            if (t.Exception?.GetType() == typeof(ServerBusyException))
                            {
                                receiveMetrics.BusyErrors = 1;
                                if (!this.CancellationToken.IsCancellationRequested)
                                {
                                    await Task.Delay(3000, this.CancellationToken).ConfigureAwait(false);
                                }
                            }
                            else
                            {
                                receiveMetrics.Errors = 1;
                            }
                            Metrics.PushReceiveMetrics(receiveMetrics);
                            semaphore.Release();
                            if (Interlocked.Increment(ref totalReceives) >= Settings.MessageCount)
                            {
                                done.Release();
                            }
                        }
                        else
                        {
                            receiveMetrics.Messages = t.Result.Count;
                            receiveMetrics.Receives = 1;
                            nsec = sw.ElapsedTicks;
                            if (Settings.ReceiveMode == ReceiveMode.PeekLock)
                            {
                                if (Settings.WorkDuration > 0)
                                {
                                    // handle completes singly
                                    for (int i = 0; i < t.Result.Count; i++)
                                    {
                                        await Task.Delay(TimeSpan.FromMilliseconds(Settings.WorkDuration));
                                        await receiver.CompleteAsync(t.Result[i].SystemProperties.LockToken).ContinueWith(async(t1) =>
                                        {
                                            receiveMetrics.CompleteDuration100ns = sw.ElapsedTicks - nsec;
                                            if (t1.IsFaulted)
                                            {
                                                if (t1.Exception?.GetType() == typeof(ServerBusyException))
                                                {
                                                    receiveMetrics.BusyErrors = 1;
                                                    if (!this.CancellationToken.IsCancellationRequested)
                                                    {
                                                        await Task.Delay(3000, this.CancellationToken).ConfigureAwait(false);
                                                    }
                                                }
                                                else
                                                {
                                                    receiveMetrics.Errors = 1;
                                                }
                                            }
                                            else
                                            {
                                                receiveMetrics.CompleteCalls = 1;
                                                receiveMetrics.Completions   = 1;
                                            }
                                            Metrics.PushReceiveMetrics(receiveMetrics);
                                            semaphore.Release();
                                            if (Interlocked.Increment(ref totalReceives) >= Settings.MessageCount)
                                            {
                                                done.Release();
                                            }
                                        });
                                    }
                                }
                                else
                                {
                                    // batch complete
                                    await receiver.CompleteAsync(t.Result.Select((m) => { return(m.SystemProperties.LockToken); })).ContinueWith(async(t1) =>
                                    {
                                        receiveMetrics.CompleteDuration100ns = sw.ElapsedTicks - nsec;
                                        if (t1.IsFaulted)
                                        {
                                            if (t1.Exception?.GetType() == typeof(ServerBusyException))
                                            {
                                                receiveMetrics.BusyErrors = 1;
                                                if (!this.CancellationToken.IsCancellationRequested)
                                                {
                                                    await Task.Delay(3000, this.CancellationToken).ConfigureAwait(false);
                                                }
                                            }
                                            else
                                            {
                                                receiveMetrics.Errors = 1;
                                            }
                                        }
                                        else
                                        {
                                            receiveMetrics.CompleteCalls = 1;
                                            receiveMetrics.Completions   = t.Result.Count;
                                        }
                                        Metrics.PushReceiveMetrics(receiveMetrics);
                                        semaphore.Release();

                                        // count all the messages
                                        for (int k = 0; k < t.Result.Count; k++)
                                        {
                                            if (Interlocked.Increment(ref totalReceives) >= Settings.MessageCount)
                                            {
                                                done.Release();
                                            }
                                        }
                                    });
                                }
                            }
                            else
                            {
                                if (Settings.WorkDuration > 0)
                                {
                                    await Task.Delay(TimeSpan.FromMilliseconds(Settings.WorkDuration));
                                }
                                Metrics.PushReceiveMetrics(receiveMetrics);
                                semaphore.Release();
                                if (Interlocked.Increment(ref totalReceives) >= Settings.MessageCount)
                                {
                                    done.Release();
                                }
                            }
                        };
                    }).Fork();
                }
            }
            await done.WaitAsync();
        }