示例#1
0
        private async Task WorkerAsync(
            ConcurrentQueue <SentryEvent> queue,
            SentryOptions options,
            ITransport transport,
            SemaphoreSlim inSemaphore,
            SemaphoreSlim outSemaphore,
            CancellationToken cancellation)
        {
            var shutdownTimeout   = new CancellationTokenSource();
            var shutdownRequested = false;

            try
            {
                while (!shutdownTimeout.IsCancellationRequested)
                {
                    // If the cancellation was signaled,
                    // set the latest we can keep reading off of the queue (while there's still stuff to read)
                    // No longer synchronized with outSemaphore (Enqueue will throw object disposed),
                    // run until the end of the queue or shutdownTimeout
                    if (!shutdownRequested)
                    {
                        try
                        {
                            await outSemaphore.WaitAsync(cancellation).ConfigureAwait(false);
                        }
                        // Cancellation requested, scheduled shutdown but continue in case there are more items
                        catch (OperationCanceledException)
                        {
                            if (options.ShutdownTimeout == TimeSpan.Zero)
                            {
                                options.DiagnosticLogger?.LogDebug("Exiting immediately due to 0 shutdown timeout. #{0} in queue.", queue.Count);
                                return;
                            }
                            else
                            {
                                options.DiagnosticLogger?.LogDebug("Shutdown scheduled. Stopping by: {0}. #{1} in queue.", options.ShutdownTimeout, queue.Count);
                                shutdownTimeout.CancelAfter(options.ShutdownTimeout);
                            }

                            shutdownRequested = true;
                        }
                    }

                    if (queue.TryPeek(out var @event)) // Work with the event while it's in the queue
                    {
                        try
                        {
                            var task = transport.CaptureEventAsync(@event, shutdownTimeout.Token);
                            options.DiagnosticLogger?.LogDebug("Event {0} in-flight to Sentry. #{1} in queue.", @event.EventId, queue.Count);
                            await task.ConfigureAwait(false);
                        }
                        catch (OperationCanceledException)
                        {
                            options.DiagnosticLogger?.LogInfo("Shutdown token triggered. Time to exit. #{0} in queue.", queue.Count);
                            return;
                        }
                        catch (Exception exception)
                        {
                            options.DiagnosticLogger?.LogError("Error while processing event {1}: {0}. #{2} in queue.", exception, @event.EventId, queue.Count);
                        }
                        finally
                        {
                            queue.TryDequeue(out _);
                            inSemaphore.Release();
                            OnFlushObjectReceived?.Invoke(@event, EventArgs.Empty);
                        }
                    }
                    else
                    {
                        Debug.Assert(shutdownRequested);
                        options.DiagnosticLogger?.LogInfo("Exiting the worker with an empty queue.");

                        // Empty queue. Exit.
                        return;
                    }
                }
            }
            finally
            {
                inSemaphore.Dispose();
                outSemaphore.Dispose();
            }
        }
示例#2
0
        private async Task WorkerAsync()
        {
            var cancellation = _shutdownSource.Token;

            using var shutdownTimeout = new CancellationTokenSource();
            var shutdownRequested = false;

            try
            {
                while (!shutdownTimeout.IsCancellationRequested)
                {
                    // If the cancellation was signaled,
                    // set the latest we can keep reading off of the queue (while there's still stuff to read)
                    // No longer synchronized with queuedEnvelopeSemaphore (Enqueue will throw object disposed),
                    // run until the end of the queue or shutdownTimeout
                    if (!shutdownRequested)
                    {
                        try
                        {
                            await _queuedEnvelopeSemaphore.WaitAsync(cancellation).ConfigureAwait(false);
                        }
                        // Cancellation requested, scheduled shutdown but continue in case there are more items
                        catch (OperationCanceledException)
                        {
                            if (_options.ShutdownTimeout == TimeSpan.Zero)
                            {
                                _options.DiagnosticLogger?.LogDebug(
                                    "Exiting immediately due to 0 shutdown timeout. #{0} in queue.",
                                    _queue.Count
                                    );

                                return;
                            }
                            else
                            {
                                _options.DiagnosticLogger?.LogDebug(
                                    "Shutdown scheduled. Stopping by: {0}. #{1} in queue.",
                                    _options.ShutdownTimeout,
                                    _queue.Count
                                    );

                                shutdownTimeout.CancelAfter(_options.ShutdownTimeout);
                            }

                            shutdownRequested = true;
                        }
                    }

                    if (_queue.TryPeek(out var envelope)) // Work with the envelope while it's in the queue
                    {
                        try
                        {
                            var task = _transport.SendEnvelopeAsync(envelope, shutdownTimeout.Token);

                            _options.DiagnosticLogger?.LogDebug(
                                "Envelope {0} in-flight to Sentry. #{1} in queue.",
                                envelope.TryGetEventId(),
                                _queue.Count
                                );

                            await task.ConfigureAwait(false);
                        }
                        catch (OperationCanceledException)
                        {
                            _options.DiagnosticLogger?.LogInfo(
                                "Shutdown token triggered. Time to exit. #{0} in queue.",
                                _queue.Count
                                );

                            return;
                        }
                        catch (Exception exception)
                        {
                            _options.DiagnosticLogger?.LogError(
                                "Error while processing event {1}: {0}. #{2} in queue.",
                                exception,
                                envelope.TryGetEventId(),
                                _queue.Count
                                );
                        }
                        finally
                        {
                            _ = _queue.TryDequeue(out _);
                            _ = Interlocked.Decrement(ref _currentItems);
                            OnFlushObjectReceived?.Invoke(envelope, EventArgs.Empty);
                        }
                    }
                    else
                    {
                        Debug.Assert(shutdownRequested);
                        _options.DiagnosticLogger?.LogInfo("Exiting the worker with an empty queue.");

                        // Empty queue. Exit.
                        return;
                    }
                }
            }
            catch (Exception e)
            {
                _options.DiagnosticLogger?.LogFatal("Exception in the background worker.", e);
                throw;
            }
            finally
            {
                _queuedEnvelopeSemaphore.Dispose();
            }
        }
示例#3
0
        private async Task WorkerAsync(CancellationToken cancellation)
        {
            var shutdownTimeout   = new CancellationTokenSource();
            var shutdownRequested = false;

            try
            {
                while (!shutdownTimeout.IsCancellationRequested)
                {
                    if (!shutdownRequested)
                    {
                        try
                        {
                            await _queuedEventSemaphore.WaitAsync(cancellation).ConfigureAwait(false);
                        }
                        catch (OperationCanceledException)
                        {
                            if (_options.ShutdownTimeout == TimeSpan.Zero)
                            {
                                return;
                            }

                            shutdownTimeout.CancelAfter(_options.ShutdownTimeout);
                            shutdownRequested = true;
                        }
                    }

                    if (_queue.TryPeek(out var exceptionInstance))
                    {
                        try
                        {
                            var task = _excepticonExceptionInstancesService.PostExceptionInstance(exceptionInstance, _options.ApiKey);
                            await task.ConfigureAwait(false);
                        }
                        catch (OperationCanceledException)
                        {
                            return;
                        }
                        catch (Exception e)
                        {
                            Debug.WriteLine(e.Message);
                        }
                        finally
                        {
                            _queue.TryDequeue(out exceptionInstance);
                            Interlocked.Decrement(ref _currentItems);
                            OnFlushObjectReceived?.Invoke(exceptionInstance, EventArgs.Empty);
                        }
                    }
                    else
                    {
                        return;
                    }
                }
            }
            catch (Exception e)
            {
                Console.WriteLine(e);
                throw;
            }
            finally
            {
                _queuedEventSemaphore.Dispose();
            }
        }