Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Introduce ObjectPool and use it for ResilienceContext pooling #1111

Merged
merged 6 commits into from
Apr 12, 2023
Merged
Show file tree
Hide file tree
Changes from 5 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions src/Polly.Core.Tests/ExecutionRejectedExceptionTests.cs
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
namespace Polly.Core.Tests.Timeout;
namespace Polly.Core.Tests;

public class ExecutionRejectedExceptionTests
{
[Fact]
public void Ctor_Ok()
{
new CustomException().Message.Should().Be("Exception of type 'Polly.Core.Tests.Timeout.ExecutionRejectedExceptionTests+CustomException' was thrown.");
new CustomException().Message.Should().Be("Exception of type 'Polly.Core.Tests.ExecutionRejectedExceptionTests+CustomException' was thrown.");
new CustomException("Dummy").Message.Should().Be("Dummy");
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

using System;

namespace Polly.Core.Tests.Utils;
namespace Polly.Core.Tests.Helpers;

/// <summary>
/// Utility that serializes and deserializes the exceptions using the binary formatter.
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
using Moq;
using Polly.Utils;

namespace Polly.Core.Tests.Utils;
namespace Polly.Core.Tests.Helpers;

internal class FakeTimeProvider : Mock<TimeProvider>
{
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
using Polly.Strategy;

namespace Polly.Core.Tests.Utils;
namespace Polly.Core.Tests.Helpers;

public class TestArguments : IResilienceArguments
{
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
namespace Polly.Core.Tests.Utils;
namespace Polly.Core.Tests.Helpers;

public class TestResilienceStrategy : ResilienceStrategy
{
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
namespace Polly.Core.Tests.Utils;
namespace Polly.Core.Tests.Helpers;

#pragma warning disable CA1031 // Do not catch general exception types

Expand Down
2 changes: 1 addition & 1 deletion src/Polly.Core.Tests/Polly.Core.Tests.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,6 @@
</ItemGroup>

<ItemGroup>
<Using Include="Polly.Core.Tests.Utils" />
<Using Include="Polly.Core.Tests.Helpers" />
</ItemGroup>
</Project>
3 changes: 0 additions & 3 deletions src/Polly.Core.Tests/Registry/StrategyId.cs
Original file line number Diff line number Diff line change
@@ -1,6 +1,3 @@
using System;
using System.Collections.Generic;

namespace Polly.Core.Tests.Registry;

public record StrategyId(Type Type, string BuilderName, string InstanceName = "")
Expand Down
10 changes: 10 additions & 0 deletions src/Polly.Core.Tests/ResilienceContextTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,16 @@ public void Get_EnsureDefaults()
AssertDefaults(context);
}

[Fact]
public void Get_EnsurePooled()
{
var context = ResilienceContext.Get();

ResilienceContext.Return(context);

ResilienceContext.Get().Should().BeSameAs(context);
}

[Fact]
public void Return_Null_Throws()
{
Expand Down
3 changes: 0 additions & 3 deletions src/Polly.Core.Tests/Retry/RetryDelayGeneratorTests.cs
Original file line number Diff line number Diff line change
@@ -1,8 +1,5 @@
using System;
using System.Threading.Tasks;
using Polly.Retry;
using Polly.Strategy;
using Xunit;

namespace Polly.Core.Tests.Retry;

Expand Down
1 change: 0 additions & 1 deletion src/Polly.Core.Tests/Retry/RetryHelperTests.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
using System;
using Polly.Retry;

namespace Polly.Core.Tests.Retry;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
using System.ComponentModel.DataAnnotations;
using Polly.Builder;
using Polly.Retry;
using Xunit;

namespace Polly.Core.Tests.Retry;

Expand Down
2 changes: 0 additions & 2 deletions src/Polly.Core.Tests/Strategy/OutcomeEventTests.cs
Original file line number Diff line number Diff line change
@@ -1,5 +1,3 @@
using System;
using System.Threading.Tasks;
using Polly.Strategy;

namespace Polly.Core.Tests.Strategy;
Expand Down
2 changes: 0 additions & 2 deletions src/Polly.Core.Tests/Strategy/OutcomeGeneratorTests.cs
Original file line number Diff line number Diff line change
@@ -1,5 +1,3 @@
using System;
using System.Threading.Tasks;
using Polly.Strategy;

namespace Polly.Core.Tests.Strategy;
Expand Down
2 changes: 0 additions & 2 deletions src/Polly.Core.Tests/Strategy/OutcomePredicateTests.cs
Original file line number Diff line number Diff line change
@@ -1,5 +1,3 @@
using System;
using System.Threading.Tasks;
using Polly.Strategy;

namespace Polly.Core.Tests.Strategy;
Expand Down
1 change: 0 additions & 1 deletion src/Polly.Core.Tests/Strategy/OutcomeTests.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
using System;
using Polly.Strategy;

namespace Polly.Core.Tests.Strategy;
Expand Down
6 changes: 3 additions & 3 deletions src/Polly.Core.Tests/Strategy/SimpleEventTests.cs
Original file line number Diff line number Diff line change
@@ -1,14 +1,14 @@
using Polly.Strategy;

namespace Polly.Core.Tests.Timeout;
namespace Polly.Core.Tests.Strategy;

public class SimpleEventTests
{
[Fact]
public async Task Add_EnsureOrdering()
{
var ev = new DummyEvent();
List<int> raisedEvents = new List<int>();
var raisedEvents = new List<int>();

ev.Add(() => raisedEvents.Add(1));
ev.Add(args => raisedEvents.Add(2));
Expand Down Expand Up @@ -41,7 +41,7 @@ public async Task CreateHandler_Ok(int count)
var ev = new DummyEvent();
var events = new List<int>();

for (int i = 0; i < count; i++)
for (var i = 0; i < count; i++)
{
ev.Add(() => events.Add(i));
}
Expand Down
1 change: 0 additions & 1 deletion src/Polly.Core.Tests/Timeout/TimeoutAttributeTests.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
using System.ComponentModel.DataAnnotations;
using Polly.Timeout;

namespace Polly.Core.Tests.Timeout;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
using System.ComponentModel.DataAnnotations;
using Polly.Timeout;
using Polly.Utils;
using Xunit;

namespace Polly.Core.Tests.Timeout;

Expand Down
2 changes: 0 additions & 2 deletions src/Polly.Core.Tests/Timeout/TimeoutUtilTests.cs
Original file line number Diff line number Diff line change
@@ -1,6 +1,4 @@
using System;
using Polly.Timeout;
using Xunit;

namespace Polly.Core.Tests.Timeout;
public class TimeoutUtilTests
Expand Down
111 changes: 111 additions & 0 deletions src/Polly.Core.Tests/Utils/ObjectPoolTests.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,111 @@
using Polly.Utils;

namespace Polly.Core.Tests.Utils;

public class ObjectPoolTests
{
[Fact]
public void GetAnd_ReturnObject_SameInstance()
{
// Arrange
var pool = new ObjectPool<object>(() => new object(), _ => true);

var obj1 = pool.Get();
pool.Return(obj1);

// Act
var obj2 = pool.Get();

// Assert
Assert.Same(obj1, obj2);
}

[Fact]
public void MaxCapacity_Ok()
{
ObjectPool<object>.MaxCapacity.Should().Be((Environment.ProcessorCount * 2) - 1);
}

[Fact]
public void MaxCapacity_Respected()
{
// Arrange
var pool = new ObjectPool<object>(() => new object(), _ => true);
var items1 = GetStoreReturn(pool);

// Act
var items2 = GetStoreReturn(pool);

// Assert
items1.Should().BeEquivalentTo(items2);
}

[Fact]
public void MaxCapacityOverflow_Respected()
{
// Arrange
var count = ObjectPool<object>.MaxCapacity + 10;
var pool = new ObjectPool<object>(() => new object(), _ => true);
var items1 = GetStoreReturn(pool, count);

// Act
var items2 = GetStoreReturn(pool, count);

// Assert
items1.Last().Should().NotBeSameAs(items2.Last());
}

[Fact]
public void CreatedByPolicy()
{
// Arrange
var policy = new ListPolicy();
var pool = new ObjectPool<List<int>>(ListPolicy.Create, ListPolicy.Return);

// Act
var list = pool.Get();

// Assert
Assert.Equal(17, list.Capacity);
}

[Fact]
public void Return_RejectedByPolicy()
{
// Arrange
var policy = new ListPolicy();
var pool = new ObjectPool<List<int>>(ListPolicy.Create, ListPolicy.Return);
var list1 = pool.Get();
list1.Capacity = 20;

// Act
pool.Return(list1);
var list2 = pool.Get();

// Assert
Assert.NotSame(list1, list2);
}

private static List<object> GetStoreReturn(ObjectPool<object> pool, int? count = null)
{
var items = new List<object>();
for (int i = 0; i < (count ?? ObjectPool<object>.MaxCapacity); i++)
{
items.Add(pool.Get());
}

foreach (var item in items)
{
pool.Return(item);
}

return items;
}

private class ListPolicy
{
public static List<int> Create() => new(17);

public static bool Return(List<int> obj) => obj.Capacity == 17;
}
}
1 change: 0 additions & 1 deletion src/Polly.Core.Tests/Utils/TimeSpanAttributeTests.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
using System;
using System.ComponentModel.DataAnnotations;

namespace Polly.Core.Tests.Utils;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

namespace Polly.Core.Tests.Utils;

public class ValidationContextExtensions
public class ValidationContextExtensionsTests
{
[Fact]
public void GetMemberName_Ok()
Expand Down
12 changes: 8 additions & 4 deletions src/Polly.Core/ResilienceContext.cs
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,9 @@ namespace Polly;
/// </remarks>
public sealed class ResilienceContext
{
internal const bool ContinueOnCapturedContextDefault = false;
private const bool ContinueOnCapturedContextDefault = false;

private static readonly ObjectPool<ResilienceContext> Pool = new(static () => new ResilienceContext(), static c => c.Reset());

private ResilienceContext()
{
Expand Down Expand Up @@ -61,7 +63,7 @@ private ResilienceContext()
/// After the execution is finished you should return the <see cref="ResilienceContext"/> back to the pool
/// by calling <see cref="Return(ResilienceContext)"/> method.
/// </remarks>
public static ResilienceContext Get() => new();
public static ResilienceContext Get() => Pool.Get();

/// <summary>
/// Returns a <paramref name="context"/> back to the pool.
Expand All @@ -71,7 +73,7 @@ public static void Return(ResilienceContext context)
{
Guard.NotNull(context);

context.Reset();
Pool.Return(context);
}

[ExcludeFromCodeCoverage]
Expand All @@ -90,13 +92,15 @@ internal ResilienceContext Initialize<TResult>(bool isSynchronous)
return this;
}

private void Reset()
private bool Reset()
{
IsSynchronous = false;
ResultType = typeof(UnknownResult);
ContinueOnCapturedContext = false;
CancellationToken = default;
((IDictionary<string, object?>)Properties).Clear();

return true;
}

/// <summary>
Expand Down
Loading