Example #1
0
        protected override async Task ExecuteAsync(CancellationToken stoppingToken)
        {
            if (MAX_PER_PERIOD < MAX_ACTION_CONCURRENT)
            {
                throw new Exception("The MAX_PER_PERIOD should be more or equal to MAX_ACTION_CONCURRENT");
            }

            try
            {
                while (true)
                {
                    // waiting an opportunity to run an action
                    await _semaphoreSlimAction.WaitAsync(stoppingToken);

                    // waiting the last period to end
                    await _semaphoreSlimPeriod.WaitAsync(stoppingToken);

                    var hasMoreInThisMinute = false;
                    try
                    {
                        using var cancellationTokenSource = new CancellationTokenSource(TimeSpan.FromMinutes(5));
                        using var cancellationTokenLinked = CancellationTokenSource.CreateLinkedTokenSource(stoppingToken, cancellationTokenSource.Token);

                        _logger.LogDebug("Executing");
                        hasMoreInThisMinute = await _feedService.DequeueProcessAndCheckIfContinueAsync(cancellationTokenLinked.Token);

                        _logger.LogDebug("Executed and {debugText} more items", hasMoreInThisMinute ? "has" : "hasn'nt");

                        _ = Task.Delay(PERIOD).ContinueWith(task =>
                        {
                            _logger.LogDebug("Release period sempahore");
                            _semaphoreSlimPeriod.Release(1);
                            if (!hasMoreInThisMinute)
                            {
                                _logger.LogDebug("Release action sempahore after no more items");
                                _semaphoreSlimAction.Release(1);
                            }
                        });
                    }
                    catch (Exception ex)
                    {
                        _logger.LogError("An error has occurred when processing the feed: `{exMessage}`.", ex.Message);
                    }
                    finally
                    {
                        if (hasMoreInThisMinute)
                        {
                            _logger.LogDebug("Release action sempahore");
                            _semaphoreSlimAction.Release(1);
                        }
                    }
                }
            }
            catch (Exception ex)
            {
                _logger.LogCritical("BackgroundWorker stopped by error `{exMessage}`.", ex.Message);
                throw;
            }
        }