示例#1
0
        private async Task <IState> PerformJob(BackgroundProcessContext context, IStorageConnection connection, string jobId)
        {
            try
            {
                var jobData = connection.GetJobData(jobId);
                if (jobData == null)
                {
                    // Job expired just after moving to a processing state. This is an
                    // unreal scenario, but shit happens. Returning null instead of throwing
                    // an exception and rescuing from en-queueing a poisoned jobId back
                    // to a queue.
                    return(null);
                }

                jobData.EnsureLoaded();

                var backgroundJob = new BackgroundJob(jobId, jobData.Job, jobData.CreatedAt);

                var jobToken       = new ServerJobCancellationToken(connection, jobId, context.ServerId, _workerId, context.CancellationToken);
                var performContext = new PerformContext(connection, backgroundJob, jobToken);

                var latency  = (DateTime.UtcNow - jobData.CreatedAt).TotalMilliseconds;
                var duration = Stopwatch.StartNew();

                var result = await _performer.PerformAsync(performContext).ConfigureAwait(false);

                duration.Stop();

                // SHOULD BE: return new SucceededState(result, (long)latency, duration.ElapsedMilliseconds);
                return(CreateSucceededState(result, (long)latency, duration.ElapsedMilliseconds));
            }
            catch (JobAbortedException)
            {
                // Background job performance was aborted due to a
                // state change, so it's idenfifier should be removed
                // from a queue.
                return(null);
            }
            catch (JobPerformanceException ex)
            {
                return(new FailedState(ex.InnerException)
                {
                    Reason = ex.Message
                });
            }
            catch (Exception ex)
            {
                if (ex is OperationCanceledException && context.IsShutdownRequested)
                {
                    throw;
                }

                return(new FailedState(ex)
                {
                    Reason = "An exception occurred during processing of a background job."
                });
            }
        }
示例#2
0
        public void CheckAllCancellationTokens_DoesNotAbortCancellationToken_IfNothingChanged()
        {
            var token = CreateToken();

            Assert.False(token.ShutdownToken.IsCancellationRequested);
            ServerJobCancellationToken.CheckAllCancellationTokens(ServerId, _connection.Object, _cts.Token);

            Assert.False(token.IsAborted);
            token.ShutdownToken.ThrowIfCancellationRequested(); // does not throw
        }
示例#3
0
        public void CheckAllCancellationTokens_DoesNotPerformChecks_WhenShutdownTokenWasNotInitialized()
        {
            _stateData.Name = "NotProcessing";
            var token = CreateToken();

            ServerJobCancellationToken.CheckAllCancellationTokens(ServerId, _connection.Object, _cts.Token);

            Assert.False(token.IsAborted);
            _connection.Verify(x => x.GetStateData(It.IsAny <string>()), Times.Never);
        }
示例#4
0
        public void CheckAllCancellationTokens_DoesNotAbortJobsFromOtherServers()
        {
            _stateData.Name = "NotProcessing";
            var token = CreateToken();

            Assert.False(token.ShutdownToken.IsCancellationRequested);
            ServerJobCancellationToken.CheckAllCancellationTokens("another-id", _connection.Object, _cts.Token);

            token.ShutdownToken.ThrowIfCancellationRequested();
            Assert.False(token.IsAborted);
        }
        public ServerJobCancellationWatcherFacts()
        {
            _checkInterval = Timeout.InfiniteTimeSpan;

            _context = new BackgroundProcessContextMock();
            _context.StoppingTokenSource.Cancel();

            _connection = new Mock <IStorageConnection>();
            _context.Storage.Setup(x => x.GetConnection()).Returns(_connection.Object);

            ServerJobCancellationToken.AddServer(_context.ServerId);
        }
示例#6
0
        public void CheckAllCancellationTokens_AbortsCancellationToken_IfWorkerIdWasChanged()
        {
            _stateData.Data["WorkerId"] = "999";
            var token = CreateToken();

            Assert.False(token.ShutdownToken.IsCancellationRequested);
            ServerJobCancellationToken.CheckAllCancellationTokens(ServerId, _connection.Object, _cts.Token);

            Assert.Throws <OperationCanceledException>(
                () => token.ShutdownToken.ThrowIfCancellationRequested());
            Assert.True(token.IsAborted);
        }
示例#7
0
        public void CheckAllCancellationTokens_AbortsCancellationToken_IfJobIsNotInProcessingState()
        {
            _stateData.Name = "NotProcessing";
            var token = CreateToken();

            Assert.False(token.ShutdownToken.IsCancellationRequested);
            ServerJobCancellationToken.CheckAllCancellationTokens(ServerId, _connection.Object, _cts.Token);

            Assert.Throws <OperationCanceledException>(
                () => token.ShutdownToken.ThrowIfCancellationRequested());
            Assert.True(token.IsAborted);
        }
示例#8
0
        public void CheckAllCancellationTokens_AbortsCancellationToken_IfStateDataDoesNotExist()
        {
            _connection.Setup(x => x.GetStateData(It.IsAny <string>())).Returns((StateData)null);
            var token = CreateToken();

            Assert.False(token.ShutdownToken.IsCancellationRequested);
            ServerJobCancellationToken.CheckAllCancellationTokens(ServerId, _connection.Object, _cts.Token);

            Assert.Throws <OperationCanceledException>(
                () => token.ShutdownToken.ThrowIfCancellationRequested());
            Assert.True(token.IsAborted);
        }
        public void Execute_DelegatesCancellationToServerJobCancellationToken()
        {
            var token = new ServerJobCancellationToken(_connection.Object, "job-id", _context.ServerId, "1", _context.StoppedTokenSource.Token);

            Assert.False(token.ShutdownToken.IsCancellationRequested);

            _connection.Setup(x => x.GetStateData(It.IsAny <string>())).Returns((StateData)null);
            var watchdog = new ServerJobCancellationWatcher(_checkInterval);

            watchdog.Execute(_context.Object);

            _connection.Verify(x => x.GetStateData("job-id"));
            _connection.Verify(x => x.Dispose(), Times.Once);
            Assert.True(token.IsAborted);
        }
示例#10
0
        public void CheckAllCancellationTokens_PerformsAdditionalChecks_WhenPriorOnesDidNotLeadToAbort()
        {
            var token = CreateToken();

            Assert.False(token.ShutdownToken.IsCancellationRequested);

            ServerJobCancellationToken.CheckAllCancellationTokens(ServerId, _connection.Object, _cts.Token);
            Assert.False(token.IsAborted);

            _stateData.Name = "NotProcessing";
            ServerJobCancellationToken.CheckAllCancellationTokens(ServerId, _connection.Object, _cts.Token);

            Assert.True(token.IsAborted);
            _connection.Verify(x => x.GetStateData(It.IsAny <string>()), Times.Exactly(2));
        }
示例#11
0
        public ServerJobCancellationTokenFacts()
        {
            _stateData = new StateData
            {
                Name = ProcessingState.StateName,
                Data = new Dictionary <string, string>
                {
                    { "ServerId", ServerId },
                    { "WorkerId", WorkerId },
                }
            };

            _connection = new Mock <IStorageConnection>();
            _connection.Setup(x => x.GetStateData(JobId)).Returns(_stateData);

            _cts         = new CancellationTokenSource();
            _shutdownCts = new CancellationTokenSource();

            ServerJobCancellationToken.AddServer(ServerId);
        }
 public void Dispose()
 {
     ServerJobCancellationToken.RemoveServer(_context.ServerId);
 }