public async Task PutsServiceIntoSleepingStateWhenDequeueReturnsNoMessage() { // Arrange var cts = new CancellationTokenSource(); var runner = new TestableJobRunner(TimeSpan.FromSeconds(5), skipDispatch: true); var dequeueTcs = runner.MockQueue .Setup(q => q.Dequeue(JobRunner.DefaultInvisibilityPeriod, cts.Token)) .WaitsForSignal(); RunnerStatus statusAtLastHeartBeat = RunnerStatus.Working; runner.Heartbeat += (_, __) => statusAtLastHeartBeat = runner.Status; dequeueTcs.SetResult(null); // Act, run the task to the sleep var task = runner.Run(cts.Token); // Assert Assert.Equal(RunnerStatus.Sleeping, runner.Status); Assert.Equal(RunnerStatus.Sleeping, statusAtLastHeartBeat); // Abort the waiting threads runner.VirtualClock.Advance(TimeSpan.FromMinutes(10)); cts.Cancel(); try { await task; } catch (TaskCanceledException) { } }
public async Task PutsServiceInDequeingStateUntilQueueReturnsMessage() { // Arrange var runner = new TestableJobRunner(TimeSpan.FromSeconds(5), skipDispatch: true); var cts = new CancellationTokenSource(); var dequeueTcs = runner.MockQueue .Setup(q => q.Dequeue(JobRunner.DefaultInvisibilityPeriod, cts.Token)) .WaitsForSignal(); RunnerStatus statusAtHeartBeat = RunnerStatus.Working; runner.Heartbeat += (_, __) => statusAtHeartBeat = runner.Status; // Act var task = runner.Run(cts.Token); // Assert Assert.Equal(RunnerStatus.Dequeuing, runner.Status); Assert.Equal(RunnerStatus.Dequeuing, statusAtHeartBeat); // Abort the waiting threads dequeueTcs.SetException(new OperationCanceledException()); cts.Cancel(); try { await task; } catch (TaskCanceledException) { } }
public async Task DispatchesRequestIfOneIsReceived() { // Arrange var cts = new CancellationTokenSource(); var runner = new TestableJobRunner(TimeSpan.FromSeconds(5), skipDispatch: true); var dequeueTcs = runner.MockQueue .Setup(q => q.Dequeue(JobRunner.DefaultInvisibilityPeriod, cts.Token)) .WaitsForSignal(); var request = TestHelpers.CreateInvocation(Guid.NewGuid(), "test", "test", new Dictionary <string, string>()); // Act var task = runner.Run(cts.Token); dequeueTcs.SetResult(request); cts.Cancel(); runner.DispatchTCS.TrySetResult(null); // Abort the waiting threads try { await task; } catch (TaskCanceledException) { } // Assert Assert.Same(request, runner.LastDispatched); }
public async Task AcknowledgesMessageOnCompletionOfInvocation() { // Arrange var cts = new CancellationTokenSource(); var runner = new TestableJobRunner(TimeSpan.FromSeconds(5)); var invocation = TestHelpers.CreateInvocation(Guid.NewGuid(), "test", "test", new Dictionary <string, string>()); runner.MockDispatcher .Setup(d => d.Dispatch(It.IsAny <InvocationContext>())) .Completes(InvocationResult.Completed()) .Verifiable(); // Act await runner.Dispatch(invocation, cts.Token); // Assert runner.MockQueue.Verify(q => q.Complete(invocation, ExecutionResult.Completed, null, null)); }
public async Task DispatchesTheJobUsingTheDispatcher() { // Arrange var cts = new CancellationTokenSource(); var runner = new TestableJobRunner(TimeSpan.FromSeconds(5)); var invocation = TestHelpers.CreateInvocation(Guid.NewGuid(), "test", "test", new Dictionary <string, string>()); runner.MockDispatcher .Setup(d => d.Dispatch(It.IsAny <InvocationContext>())) .Completes(InvocationResult.Completed()) .Verifiable(); // Act await runner.Dispatch(invocation, cts.Token); // Assert runner.MockDispatcher.VerifyAll(); }
public async Task SleepsForPollIntervalWhenDequeueReturnsNoMessage() { // Arrange var cts = new CancellationTokenSource(); var runner = new TestableJobRunner(TimeSpan.FromSeconds(5), skipDispatch: true); var dequeueTcs = new TaskCompletionSource <InvocationState>(); runner.MockQueue .Setup(q => q.Dequeue(JobRunner.DefaultInvisibilityPeriod, cts.Token)) .Returns(async() => { var result = await dequeueTcs.Task; dequeueTcs = new TaskCompletionSource <InvocationState>(); return(result); }); RunnerStatus statusAtLastHeartBeat = RunnerStatus.Working; runner.Heartbeat += (_, __) => statusAtLastHeartBeat = runner.Status; dequeueTcs.SetResult(null); runner.DispatchTCS.TrySetResult(null); // Run to the sleep var task = runner.Run(cts.Token); runner.DispatchTCS = new TaskCompletionSource <object>(); // Act runner.VirtualClock.Advance(TimeSpan.FromSeconds(5)); // Assert Assert.Equal(RunnerStatus.Dequeuing, runner.Status); Assert.Equal(RunnerStatus.Dequeuing, statusAtLastHeartBeat); // Abort the waiting threads runner.DispatchTCS.SetResult(null); dequeueTcs.SetResult(null); cts.Cancel(); try { await task; } catch (TaskCanceledException) { } }
public async Task EnqueuesARescheduleIfTheResultRequestsIt(ExecutionResult result) { // Arrange var cts = new CancellationTokenSource(); var runner = new TestableJobRunner(TimeSpan.FromSeconds(5)); var invocation = TestHelpers.CreateInvocation(Guid.NewGuid(), "test", "test", new Dictionary <string, string>()); var repeat = TestHelpers.CreateInvocation(Guid.NewGuid(), "test", "test", new Dictionary <string, string>()); runner.MockDispatcher .Setup(d => d.Dispatch(It.IsAny <InvocationContext>())) .Completes(new InvocationResult(result, result == ExecutionResult.Faulted ? new Exception() : null, TimeSpan.FromDays(365))) .Verifiable(); runner.MockQueue .Setup(q => q.Enqueue("test", Constants.Source_RepeatingJob, It.IsAny <Dictionary <string, string> >(), TimeSpan.FromDays(365), null)) .Completes(repeat); // Act await runner.Dispatch(invocation, cts.Token); // Assert runner.MockQueue.Verify(q => q.Enqueue(invocation.Job, Constants.Source_RepeatingJob, invocation.Payload, TimeSpan.FromDays(365), null)); }
public async Task UpdatesTheStatusOfTheRequestToExecuting() { // Arrange var cts = new CancellationTokenSource(); var runner = new TestableJobRunner(TimeSpan.FromSeconds(5)); var invocation = TestHelpers.CreateInvocation(Guid.NewGuid(), "test", "test", new Dictionary <string, string>()); var dispatchTCS = runner .MockDispatcher .Setup(d => d.Dispatch(It.IsAny <InvocationContext>())) .WaitsForSignal(); // Act var task = runner.Dispatch(invocation, cts.Token); // Assert runner.MockQueue.Verify(q => q.UpdateStatus(invocation, InvocationStatus.Executing, ExecutionResult.Incomplete)); dispatchTCS.SetResult(InvocationResult.Completed()); await task; }
public async Task PutsServiceInDispatchingStateWhenQueueReturnsMessage() { // Arrange var cts = new CancellationTokenSource(); var runner = new TestableJobRunner(TimeSpan.FromSeconds(5), skipDispatch: true); var dequeueTcs = new TaskCompletionSource <InvocationState>(); runner.MockQueue .Setup(q => q.Dequeue(JobRunner.DefaultInvisibilityPeriod, cts.Token)) .Returns(async() => { var result = await dequeueTcs.Task; dequeueTcs = new TaskCompletionSource <InvocationState>(); return(result); }); RunnerStatus statusAtHeartBeat = RunnerStatus.Working; runner.Heartbeat += (_, __) => statusAtHeartBeat = runner.Status; // Act var task = runner.Run(cts.Token); dequeueTcs.SetResult(TestHelpers.CreateInvocation(Guid.NewGuid(), "test", "test", new Dictionary <string, string>())); // Assert Assert.Equal(RunnerStatus.Dispatching, runner.Status); Assert.Equal(RunnerStatus.Dispatching, statusAtHeartBeat); // Abort the waiting threads cts.Cancel(); runner.DispatchTCS.TrySetResult(null); dequeueTcs.SetResult(null); try { await task; } catch (TaskCanceledException) { } }
public async Task SuspendsInvocationIfJobRemainsIncompleteWithAContinuation() { // Arrange var cts = new CancellationTokenSource(); var runner = new TestableJobRunner(TimeSpan.FromSeconds(5)); var invocation = TestHelpers.CreateInvocation(Guid.NewGuid(), "test", "test", new Dictionary <string, string>()); var continuationPayload = new Dictionary <string, string>() { { "foo", "bar" } }; runner.MockDispatcher .Setup(d => d.Dispatch(It.IsAny <InvocationContext>())) .Completes(InvocationResult.Suspended(new JobContinuation(TimeSpan.FromDays(365), continuationPayload))) .Verifiable(); // Act await runner.Dispatch(invocation, cts.Token); // Assert runner.MockQueue.Verify(q => q.Suspend(invocation, continuationPayload, TimeSpan.FromDays(365), null)); }
public async Task CompletesWithResultMessageIfThereIsAnException(ExecutionResult result) { // Arrange var cts = new CancellationTokenSource(); var runner = new TestableJobRunner(TimeSpan.FromSeconds(5)); var invocation = TestHelpers.CreateInvocation(Guid.NewGuid(), "test", "test", new Dictionary <string, string>()); var exception = new Exception("BORK!"); runner.MockDispatcher .Setup(d => d.Dispatch(It.IsAny <InvocationContext>())) .Completes(() => { runner.VirtualClock.Advance(TimeSpan.FromDays(365)); // Wow this is a long job ;) return(new InvocationResult(result, exception)); }) .Verifiable(); // Act await runner.Dispatch(invocation, cts.Token); // Assert runner.MockQueue.Verify(q => q.Complete(invocation, result, exception.ToString(), null)); }
public async Task DequeuesMessageFromQueue() { // Arrange var runner = new TestableJobRunner(TimeSpan.FromSeconds(5), skipDispatch: true); var cts = new CancellationTokenSource(); var dequeueTcs = runner.MockQueue .Setup(q => q.Dequeue(JobRunner.DefaultInvisibilityPeriod, cts.Token)) .WaitsForSignal(); // Act var task = runner.Run(cts.Token); // Assert runner.MockQueue.Verify(q => q.Dequeue(JobRunner.DefaultInvisibilityPeriod, cts.Token)); // Abort the waiting threads dequeueTcs.SetException(new OperationCanceledException()); cts.Cancel(); try { await task; } catch (TaskCanceledException) { } }
public async Task PutsServiceInDispatchingStateWhenQueueReturnsMessage() { // Arrange var cts = new CancellationTokenSource(); var runner = new TestableJobRunner(TimeSpan.FromSeconds(5), skipDispatch: true); var dequeueTcs = new TaskCompletionSource<InvocationState>(); runner.MockQueue .Setup(q => q.Dequeue(JobRunner.DefaultInvisibilityPeriod, cts.Token)) .Returns(async () => { var result = await dequeueTcs.Task; dequeueTcs = new TaskCompletionSource<InvocationState>(); return result; }); RunnerStatus statusAtHeartBeat = RunnerStatus.Working; runner.Heartbeat += (_, __) => statusAtHeartBeat = runner.Status; // Act var task = runner.Run(cts.Token); dequeueTcs.SetResult(TestHelpers.CreateInvocation(Guid.NewGuid(), "test", "test", new Dictionary<string, string>())); // Assert Assert.Equal(RunnerStatus.Dispatching, runner.Status); Assert.Equal(RunnerStatus.Dispatching, statusAtHeartBeat); // Abort the waiting threads cts.Cancel(); runner.DispatchTCS.TrySetResult(null); dequeueTcs.SetResult(null); try { await task; } catch (TaskCanceledException) { } }
public async Task DispatchesRequestIfOneIsReceived() { // Arrange var cts = new CancellationTokenSource(); var runner = new TestableJobRunner(TimeSpan.FromSeconds(5), skipDispatch: true); var dequeueTcs = runner.MockQueue .Setup(q => q.Dequeue(JobRunner.DefaultInvisibilityPeriod, cts.Token)) .WaitsForSignal(); var request = TestHelpers.CreateInvocation(Guid.NewGuid(), "test", "test", new Dictionary<string, string>()); // Act var task = runner.Run(cts.Token); dequeueTcs.SetResult(request); cts.Cancel(); runner.DispatchTCS.TrySetResult(null); // Abort the waiting threads try { await task; } catch (TaskCanceledException) { } // Assert Assert.Same(request, runner.LastDispatched); }
public async Task SleepsForPollIntervalWhenDequeueReturnsNoMessage() { // Arrange var cts = new CancellationTokenSource(); var runner = new TestableJobRunner(TimeSpan.FromSeconds(5), skipDispatch: true); var dequeueTcs = new TaskCompletionSource<InvocationState>(); runner.MockQueue .Setup(q => q.Dequeue(JobRunner.DefaultInvisibilityPeriod, cts.Token)) .Returns(async () => { var result = await dequeueTcs.Task; dequeueTcs = new TaskCompletionSource<InvocationState>(); return result; }); RunnerStatus statusAtLastHeartBeat = RunnerStatus.Working; runner.Heartbeat += (_, __) => statusAtLastHeartBeat = runner.Status; dequeueTcs.SetResult(null); runner.DispatchTCS.TrySetResult(null); // Run to the sleep var task = runner.Run(cts.Token); runner.DispatchTCS = new TaskCompletionSource<object>(); // Act runner.VirtualClock.Advance(TimeSpan.FromSeconds(5)); // Assert Assert.Equal(RunnerStatus.Dequeuing, runner.Status); Assert.Equal(RunnerStatus.Dequeuing, statusAtLastHeartBeat); // Abort the waiting threads runner.DispatchTCS.SetResult(null); dequeueTcs.SetResult(null); cts.Cancel(); try { await task; } catch (TaskCanceledException) { } }
public async Task EnqueuesARescheduleIfTheResultRequestsIt(ExecutionResult result) { // Arrange var cts = new CancellationTokenSource(); var runner = new TestableJobRunner(TimeSpan.FromSeconds(5)); var invocation = TestHelpers.CreateInvocation(Guid.NewGuid(), "test", "test", new Dictionary<string, string>()); var repeat = TestHelpers.CreateInvocation(Guid.NewGuid(), "test", "test", new Dictionary<string,string>()); runner.MockDispatcher .Setup(d => d.Dispatch(It.IsAny<InvocationContext>())) .Completes(new InvocationResult(result, result == ExecutionResult.Faulted ? new Exception() : null, TimeSpan.FromDays(365))) .Verifiable(); runner.MockQueue .Setup(q => q.Enqueue("test", Constants.Source_RepeatingJob, It.IsAny<Dictionary<string, string>>(), TimeSpan.FromDays(365), null)) .Completes(repeat); // Act await runner.Dispatch(invocation, cts.Token); // Assert runner.MockQueue.Verify(q => q.Enqueue(invocation.Job, Constants.Source_RepeatingJob, invocation.Payload, TimeSpan.FromDays(365), null)); }
public async Task SuspendsInvocationIfJobRemainsIncompleteWithAContinuation() { // Arrange var cts = new CancellationTokenSource(); var runner = new TestableJobRunner(TimeSpan.FromSeconds(5)); var invocation = TestHelpers.CreateInvocation(Guid.NewGuid(), "test", "test", new Dictionary<string, string>()); var continuationPayload = new Dictionary<string, string>() { { "foo", "bar" } }; runner.MockDispatcher .Setup(d => d.Dispatch(It.IsAny<InvocationContext>())) .Completes(InvocationResult.Suspended(new JobContinuation(TimeSpan.FromDays(365), continuationPayload))) .Verifiable(); // Act await runner.Dispatch(invocation, cts.Token); // Assert runner.MockQueue.Verify(q => q.Suspend(invocation, continuationPayload, TimeSpan.FromDays(365), null)); }
public async Task CompletesWithResultMessageIfThereIsAnException(ExecutionResult result) { // Arrange var cts = new CancellationTokenSource(); var runner = new TestableJobRunner(TimeSpan.FromSeconds(5)); var invocation = TestHelpers.CreateInvocation(Guid.NewGuid(), "test", "test", new Dictionary<string, string>()); var exception = new Exception("BORK!"); runner.MockDispatcher .Setup(d => d.Dispatch(It.IsAny<InvocationContext>())) .Completes(() => { runner.VirtualClock.Advance(TimeSpan.FromDays(365)); // Wow this is a long job ;) return new InvocationResult(result, exception); }) .Verifiable(); // Act await runner.Dispatch(invocation, cts.Token); // Assert runner.MockQueue.Verify(q => q.Complete(invocation, result, exception.ToString(), null)); }
public async Task AcknowledgesMessageOnCompletionOfInvocation() { // Arrange var cts = new CancellationTokenSource(); var runner = new TestableJobRunner(TimeSpan.FromSeconds(5)); var invocation = TestHelpers.CreateInvocation(Guid.NewGuid(), "test", "test", new Dictionary<string, string>()); runner.MockDispatcher .Setup(d => d.Dispatch(It.IsAny<InvocationContext>())) .Completes(InvocationResult.Completed()) .Verifiable(); // Act await runner.Dispatch(invocation, cts.Token); // Assert runner.MockQueue.Verify(q => q.Complete(invocation, ExecutionResult.Completed, null, null)); }
public async Task DispatchesTheJobUsingTheDispatcher() { // Arrange var cts = new CancellationTokenSource(); var runner = new TestableJobRunner(TimeSpan.FromSeconds(5)); var invocation = TestHelpers.CreateInvocation(Guid.NewGuid(), "test", "test", new Dictionary<string, string>()); runner.MockDispatcher .Setup(d => d.Dispatch(It.IsAny<InvocationContext>())) .Completes(InvocationResult.Completed()) .Verifiable(); // Act await runner.Dispatch(invocation, cts.Token); // Assert runner.MockDispatcher.VerifyAll(); }
public async Task UpdatesTheStatusOfTheRequestToExecuting() { // Arrange var cts = new CancellationTokenSource(); var runner = new TestableJobRunner(TimeSpan.FromSeconds(5)); var invocation = TestHelpers.CreateInvocation(Guid.NewGuid(), "test", "test", new Dictionary<string, string>()); var dispatchTCS = runner .MockDispatcher .Setup(d => d.Dispatch(It.IsAny<InvocationContext>())) .WaitsForSignal(); // Act var task = runner.Dispatch(invocation, cts.Token); // Assert runner.MockQueue.Verify(q => q.UpdateStatus(invocation, InvocationStatus.Executing, ExecutionResult.Incomplete)); dispatchTCS.SetResult(InvocationResult.Completed()); await task; }