Skip to content

Commit

Permalink
It was once beleived Task.Yield has magic powers. This was not true.
Browse files Browse the repository at this point in the history
  • Loading branch information
slang25 committed Nov 20, 2018
1 parent 427bfdc commit a915200
Show file tree
Hide file tree
Showing 16 changed files with 428 additions and 446 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -118,7 +118,6 @@ private async Task AndAMessageIsPublished()
_message = new SimpleMessage { Id = Guid.NewGuid() };
await _publisher.PublishAsync(_message);

await Task.Yield();
await Task.Delay(TimeSpan.FromSeconds(1));
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -99,7 +99,6 @@ private async Task WhenMessagesArePublishedToBothRegions()
await _primaryPublisher.PublishAsync(_message1);
await _secondaryPublisher.PublishAsync(_message2);

await Task.Yield();
await Task.Delay(TimeSpan.FromSeconds(1));
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -118,7 +118,6 @@ private async Task AndAMessageIsPublished()
_message = new SimpleMessage { Id = Guid.NewGuid() };
await _publisher.PublishAsync(_message);

await Task.Yield();
await Task.Delay(TimeSpan.FromSeconds(1));
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -99,7 +99,6 @@ private async Task WhenMessagesArePublishedToBothRegions()
await _primaryPublisher.PublishAsync(_message1);
await _secondaryPublisher.PublishAsync(_message2);

await Task.Yield();
await Task.Delay(TimeSpan.FromSeconds(1));
}

Expand Down
65 changes: 32 additions & 33 deletions JustSaying.TestingFramework/Tasks.cs
Original file line number Diff line number Diff line change
@@ -1,33 +1,32 @@
using System;
using System.Threading.Tasks;

namespace JustSaying.TestingFramework
{
public static class Tasks
{
private const int DefaultTimeoutMillis = 10000;
private const int DelaySendMillis = 200;

public static async Task<bool> WaitWithTimeoutAsync(Task task)
=> await WaitWithTimeoutAsync(task, TimeSpan.FromMilliseconds(DefaultTimeoutMillis))
.ConfigureAwait(false);

public static async Task<bool> WaitWithTimeoutAsync(Task task, TimeSpan timeoutDuration)
{
var timeoutTask = Task.Delay(timeoutDuration);
var firstToComplete = await Task.WhenAny(task, timeoutTask).ConfigureAwait(false);

if (firstToComplete != timeoutTask) return true;
return false;
}
public static void DelaySendDone(TaskCompletionSource<object> doneSignal)
{
Task.Run(async () =>
{
await Task.Yield();
await Task.Delay(DelaySendMillis).ConfigureAwait(false);
doneSignal.SetResult(null);
});
}
}
}
using System;
using System.Threading.Tasks;

namespace JustSaying.TestingFramework
{
public static class Tasks
{
private const int DefaultTimeoutMillis = 10000;
private const int DelaySendMillis = 200;

public static async Task<bool> WaitWithTimeoutAsync(Task task)
=> await WaitWithTimeoutAsync(task, TimeSpan.FromMilliseconds(DefaultTimeoutMillis))
.ConfigureAwait(false);

public static async Task<bool> WaitWithTimeoutAsync(Task task, TimeSpan timeoutDuration)
{
var timeoutTask = Task.Delay(timeoutDuration);
var firstToComplete = await Task.WhenAny(task, timeoutTask).ConfigureAwait(false);

if (firstToComplete != timeoutTask) return true;
return false;
}
public static void DelaySendDone(TaskCompletionSource<object> doneSignal)
{
Task.Run(async () =>
{
await Task.Delay(DelaySendMillis).ConfigureAwait(false);
doneSignal.SetResult(null);
});
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -20,9 +20,9 @@ public ThrowingDuringMessageProcessingStrategy(TaskCompletionSource<object> done
_doneSignal = doneSignal;
}

public async Task WaitForAvailableWorkers()
public Task WaitForAvailableWorkers()
{
await Task.Yield();
return Task.CompletedTask;
}

public Task StartWorker(Func<Task> action, CancellationToken cancellationToken)
Expand Down
Original file line number Diff line number Diff line change
@@ -1,66 +1,64 @@
using System;
using System.Threading;
using System.Threading.Tasks;
using JustSaying.Messaging.MessageHandling;
using JustSaying.TestingFramework;
using JustSaying.UnitTests.AwsTools.MessageHandling.SqsNotificationListener.Support;
using NSubstitute;
using Shouldly;
using Xunit;

namespace JustSaying.UnitTests.AwsTools.MessageHandling.SqsNotificationListener
{
public class WhenExactlyOnceIsAppliedToHandler : BaseQueuePollingTest
{
private int _expectedtimeout;
private readonly TaskCompletionSource<object> _tcs = new TaskCompletionSource<object>();
private ExplicitExactlyOnceSignallingHandler _handler;

protected override async Task Given()
{
await base.Given();
_expectedtimeout = 5;

var messageLockResponse = new MessageLockResponse
{
DoIHaveExclusiveLock = true
};

MessageLock = Substitute.For<IMessageLockAsync>();
MessageLock.TryAquireLockAsync(Arg.Any<string>(), Arg.Any<TimeSpan>())
.Returns(messageLockResponse);

_handler = new ExplicitExactlyOnceSignallingHandler(_tcs);
Handler = _handler;
}

protected override async Task When()
{
SystemUnderTest.AddMessageHandler(() => Handler);
var cts = new CancellationTokenSource();
SystemUnderTest.Listen(cts.Token);


// wait until it's done
await Tasks.WaitWithTimeoutAsync(_tcs.Task);
cts.Cancel();
await Task.Yield();
}

[Fact]
public void ProcessingIsPassedToTheHandler()
{
_handler.HandleWasCalled.ShouldBeTrue();
}

[Fact]
public async Task MessageIsLocked()
{
var messageId = DeserialisedMessage.Id.ToString();

await MessageLock.Received().TryAquireLockAsync(
Arg.Is<string>(a => a.Contains(messageId)),
TimeSpan.FromSeconds(_expectedtimeout));
}
}
}
using System;
using System.Threading;
using System.Threading.Tasks;
using JustSaying.Messaging.MessageHandling;
using JustSaying.TestingFramework;
using JustSaying.UnitTests.AwsTools.MessageHandling.SqsNotificationListener.Support;
using NSubstitute;
using Shouldly;
using Xunit;

namespace JustSaying.UnitTests.AwsTools.MessageHandling.SqsNotificationListener
{
public class WhenExactlyOnceIsAppliedToHandler : BaseQueuePollingTest
{
private int _expectedtimeout;
private readonly TaskCompletionSource<object> _tcs = new TaskCompletionSource<object>();
private ExplicitExactlyOnceSignallingHandler _handler;

protected override async Task Given()
{
await base.Given();
_expectedtimeout = 5;

var messageLockResponse = new MessageLockResponse
{
DoIHaveExclusiveLock = true
};

MessageLock = Substitute.For<IMessageLockAsync>();
MessageLock.TryAquireLockAsync(Arg.Any<string>(), Arg.Any<TimeSpan>())
.Returns(messageLockResponse);

_handler = new ExplicitExactlyOnceSignallingHandler(_tcs);
Handler = _handler;
}

protected override async Task When()
{
SystemUnderTest.AddMessageHandler(() => Handler);
var cts = new CancellationTokenSource();
SystemUnderTest.Listen(cts.Token);

// wait until it's done
await Tasks.WaitWithTimeoutAsync(_tcs.Task);
cts.Cancel();
}

[Fact]
public void ProcessingIsPassedToTheHandler()
{
_handler.HandleWasCalled.ShouldBeTrue();
}

[Fact]
public async Task MessageIsLocked()
{
var messageId = DeserialisedMessage.Id.ToString();

await MessageLock.Received().TryAquireLockAsync(
Arg.Is<string>(a => a.Contains(messageId)),
TimeSpan.FromSeconds(_expectedtimeout));
}
}
}
Original file line number Diff line number Diff line change
@@ -1,65 +1,64 @@
using System;
using System.Threading;
using System.Threading.Tasks;
using JustSaying.Messaging.MessageHandling;
using JustSaying.TestingFramework;
using JustSaying.UnitTests.AwsTools.MessageHandling.SqsNotificationListener.Support;
using NSubstitute;
using Shouldly;
using Xunit;

namespace JustSaying.UnitTests.AwsTools.MessageHandling.SqsNotificationListener
{
public class WhenExactlyOnceIsAppliedWithoutSpecificTimeout : BaseQueuePollingTest
{
//private readonly int _maximumTimeout = int.MaxValue;
private readonly int _maximumTimeout = (int)TimeSpan.MaxValue.TotalSeconds;
private readonly TaskCompletionSource<object> _tcs = new TaskCompletionSource<object>();
private ExactlyOnceSignallingHandler _handler;

protected override async Task Given()
{
await base.Given();

var messageLockResponse = new MessageLockResponse
{
DoIHaveExclusiveLock = true
};

MessageLock = Substitute.For<IMessageLockAsync>();
MessageLock.TryAquireLockAsync(Arg.Any<string>(), Arg.Any<TimeSpan>())
.Returns(messageLockResponse);

_handler = new ExactlyOnceSignallingHandler(_tcs);
Handler = _handler;
}

protected override async Task When()
{
SystemUnderTest.AddMessageHandler(() => Handler);
var cts = new CancellationTokenSource();
SystemUnderTest.Listen(cts.Token);

// wait until it's done
await Tasks.WaitWithTimeoutAsync(_tcs.Task);
cts.Cancel();
await Task.Yield();
}

[Fact]
public void MessageIsLocked()
{
var messageId = DeserialisedMessage.Id.ToString();

MessageLock.Received().TryAquireLockAsync(
Arg.Is<string>(a => a.Contains(messageId)),
TimeSpan.FromSeconds(_maximumTimeout));
}

[Fact]
public void ProcessingIsPassedToTheHandler()
{
_handler.HandleWasCalled.ShouldBeTrue();
}
}
}
using System;
using System.Threading;
using System.Threading.Tasks;
using JustSaying.Messaging.MessageHandling;
using JustSaying.TestingFramework;
using JustSaying.UnitTests.AwsTools.MessageHandling.SqsNotificationListener.Support;
using NSubstitute;
using Shouldly;
using Xunit;

namespace JustSaying.UnitTests.AwsTools.MessageHandling.SqsNotificationListener
{
public class WhenExactlyOnceIsAppliedWithoutSpecificTimeout : BaseQueuePollingTest
{
//private readonly int _maximumTimeout = int.MaxValue;
private readonly int _maximumTimeout = (int)TimeSpan.MaxValue.TotalSeconds;
private readonly TaskCompletionSource<object> _tcs = new TaskCompletionSource<object>();
private ExactlyOnceSignallingHandler _handler;

protected override async Task Given()
{
await base.Given();

var messageLockResponse = new MessageLockResponse
{
DoIHaveExclusiveLock = true
};

MessageLock = Substitute.For<IMessageLockAsync>();
MessageLock.TryAquireLockAsync(Arg.Any<string>(), Arg.Any<TimeSpan>())
.Returns(messageLockResponse);

_handler = new ExactlyOnceSignallingHandler(_tcs);
Handler = _handler;
}

protected override async Task When()
{
SystemUnderTest.AddMessageHandler(() => Handler);
var cts = new CancellationTokenSource();
SystemUnderTest.Listen(cts.Token);

// wait until it's done
await Tasks.WaitWithTimeoutAsync(_tcs.Task);
cts.Cancel();
}

[Fact]
public void MessageIsLocked()
{
var messageId = DeserialisedMessage.Id.ToString();

MessageLock.Received().TryAquireLockAsync(
Arg.Is<string>(a => a.Contains(messageId)),
TimeSpan.FromSeconds(_maximumTimeout));
}

[Fact]
public void ProcessingIsPassedToTheHandler()
{
_handler.HandleWasCalled.ShouldBeTrue();
}
}
}
Loading

0 comments on commit a915200

Please sign in to comment.