Skip to content

Commit

Permalink
Add TelemetrySource to RateLimiterRejectedException
Browse files Browse the repository at this point in the history
  • Loading branch information
peter-csala committed Oct 16, 2024
1 parent cd0b75c commit e7bedd2
Show file tree
Hide file tree
Showing 2 changed files with 154 additions and 22 deletions.
15 changes: 13 additions & 2 deletions src/Polly.RateLimiting/RateLimiterRejectedException.cs
Original file line number Diff line number Diff line change
Expand Up @@ -125,15 +125,26 @@ private RateLimiterRejectedException(SerializationInfo info, StreamingContext co
RetryAfter = TimeSpan.FromSeconds(retryAfter);
}

Source = info.GetString(nameof(Source));
var telemetrySource = info.GetString(nameof(TelemetrySource));
if (telemetrySource is not null)
{
Source = telemetrySource;
}
}

/// <inheritdoc/>
public override void GetObjectData(SerializationInfo info, StreamingContext context)
{
Guard.NotNull(info);

info.AddValue(nameof(Source), Source);
if (TelemetrySource is not null)
{
info.AddValue(nameof(TelemetrySource), TelemetrySource);
}
else
{
info.AddValue(nameof(TelemetrySource), "(null)/(null)/(null)");
}

if (RetryAfter.HasValue)
{
Expand Down
161 changes: 141 additions & 20 deletions test/Polly.RateLimiting.Tests/RateLimiterRejectedExceptionTests.cs
Original file line number Diff line number Diff line change
@@ -1,44 +1,165 @@
using Polly.RateLimiting;
using Polly.Telemetry;

namespace Polly.Core.Tests.Timeout;

public class RateLimiterRejectedExceptionTests
{
private readonly string _telemetrySource = "MyPipeline/MyPipelineInstance/MyRateLimiterStrategy";
private readonly string _message = "dummy";
private readonly TimeSpan _retryAfter = TimeSpan.FromSeconds(4);
private readonly ResilienceTelemetrySource _source = new("MyPipeline", "MyPipelineInstance", "MyRateLimiterStrategy");

[Fact]
public void Ctor_Ok()
{
var retryAfter = TimeSpan.FromSeconds(4);
var exception = new RateLimiterRejectedException();
exception.InnerException.Should().BeNull();
exception.Message.Should().Be("The operation could not be executed because it was rejected by the rate limiter.");
exception.RetryAfter.Should().BeNull();
exception.TelemetrySource.Should().BeNull();
}

[Fact]
public void Ctor_TelemetrySource_Ok()
{
var exception = new RateLimiterRejectedException(_source);
exception.InnerException.Should().BeNull();
exception.Message.Should().Be("The operation could not be executed because it was rejected by the rate limiter.");
exception.RetryAfter.Should().BeNull();
exception.TelemetrySource.Should().Be(_telemetrySource);
}

[Fact]
public void Ctor_TelemetrySource_Null_Ok()
{
// Arrange
ResilienceTelemetrySource? source = null;

// Act
var exception = new RateLimiterRejectedException(source!);

// Assert
exception.InnerException.Should().BeNull();
exception.Message.Should().Be("The operation could not be executed because it was rejected by the rate limiter.");
exception.RetryAfter.Should().BeNull();
exception.TelemetrySource.Should().Be("(null)/(null)/(null)");
}

[Fact]
public void Ctor_TelemetrySource_Nulls_Ok()
{
// Arrange
var source = new ResilienceTelemetrySource(null, null, null);

// Act
var exception = new RateLimiterRejectedException(source);

// Arrange
exception.InnerException.Should().BeNull();
exception.Message.Should().Be("The operation could not be executed because it was rejected by the rate limiter.");
exception.RetryAfter.Should().BeNull();
exception.TelemetrySource.Should().Be("(null)/(null)/(null)");
}

[Fact]
public void Ctor_RetryAfter_Ok()
{
var exception = new RateLimiterRejectedException(_retryAfter);
exception.InnerException.Should().BeNull();
exception.Message.Should().Be($"The operation could not be executed because it was rejected by the rate limiter. It can be retried after '00:00:04'.");
exception.RetryAfter.Should().Be(_retryAfter);
exception.TelemetrySource.Should().BeNull();
}

[Fact]
public void Ctor_TelemetrySource_RetryAfter_Ok()
{
var exception = new RateLimiterRejectedException(_source, _retryAfter);
exception.InnerException.Should().BeNull();
exception.Message.Should().Be($"The operation could not be executed because it was rejected by the rate limiter. It can be retried after '00:00:04'.");
exception.RetryAfter.Should().Be(_retryAfter);
exception.TelemetrySource.Should().Be(_telemetrySource);
}

[Fact]
public void Ctor_TelemetrySource_Null_RetryAfter_Ok()
{
// Arrange
ResilienceTelemetrySource? source = null;

// Act
var exception = new RateLimiterRejectedException(source!, _retryAfter);

// Assert
exception.InnerException.Should().BeNull();
exception.Message.Should().Be($"The operation could not be executed because it was rejected by the rate limiter. It can be retried after '00:00:04'.");
exception.RetryAfter.Should().Be(_retryAfter);
exception.TelemetrySource.Should().Be("(null)/(null)/(null)");
}

[Fact]
public void Ctor_TelemetrySource_Nulls_RetryAfter_Ok()
{
// Arrange
var source = new ResilienceTelemetrySource(null, null, null);

// Act
var exception = new RateLimiterRejectedException(source, _retryAfter);

// Assert
exception.InnerException.Should().BeNull();
exception.Message.Should().Be($"The operation could not be executed because it was rejected by the rate limiter. It can be retried after '00:00:04'.");
exception.RetryAfter.Should().Be(_retryAfter);
exception.TelemetrySource.Should().Be("(null)/(null)/(null)");
}

[Fact]
public void Ctor_Message_Ok()
{
var exception = new RateLimiterRejectedException(_message);
exception.InnerException.Should().BeNull();
exception.Message.Should().Be(_message);
exception.RetryAfter.Should().BeNull();
exception.TelemetrySource.Should().BeNull();
}

new RateLimiterRejectedException().Message.Should().Be("The operation could not be executed because it was rejected by the rate limiter.");
new RateLimiterRejectedException().RetryAfter.Should().BeNull();
new RateLimiterRejectedException("dummy").Message.Should().Be("dummy");
new RateLimiterRejectedException("dummy", new InvalidOperationException()).Message.Should().Be("dummy");
new RateLimiterRejectedException(retryAfter).RetryAfter.Should().Be(retryAfter);
new RateLimiterRejectedException(retryAfter).Message.Should().Be($"The operation could not be executed because it was rejected by the rate limiter. It can be retried after '{retryAfter}'.");
new RateLimiterRejectedException("dummy", retryAfter).RetryAfter.Should().Be(retryAfter);
new RateLimiterRejectedException("dummy", retryAfter, new InvalidOperationException()).RetryAfter.Should().Be(retryAfter);
[Fact]
public void Ctor_Message_InnerException_Ok()
{
var exception = new RateLimiterRejectedException(_message, new InvalidOperationException());
exception.InnerException.Should().BeOfType<InvalidOperationException>();
exception.Message.Should().Be(_message);
exception.RetryAfter.Should().BeNull();
exception.TelemetrySource.Should().BeNull();
}

[Fact]
public void Ctor_Message_RetryAfter_InnerException_Ok()
{
var exception = new RateLimiterRejectedException(_message, _retryAfter, new InvalidOperationException());
exception.InnerException.Should().BeOfType<InvalidOperationException>();
exception.Message.Should().Be(_message);
exception.RetryAfter.Should().Be(_retryAfter);
exception.TelemetrySource.Should().BeNull();
}

#if !NETCOREAPP
[Fact]
public void BinaryDeserialization_Ok()
{
var timeout = TimeSpan.FromSeconds(4);
var result = SerializeAndDeserializeException(new RateLimiterRejectedException(timeout));
var result = BinarySerializationUtil.SerializeAndDeserializeException(new RateLimiterRejectedException(timeout));

Check failure on line 152 in test/Polly.RateLimiting.Tests/RateLimiterRejectedExceptionTests.cs

View workflow job for this annotation

GitHub Actions / mutations-core

The name 'BinarySerializationUtil' does not exist in the current context

Check failure on line 152 in test/Polly.RateLimiting.Tests/RateLimiterRejectedExceptionTests.cs

View workflow job for this annotation

GitHub Actions / mutations-core

The name 'BinarySerializationUtil' does not exist in the current context

Check failure on line 152 in test/Polly.RateLimiting.Tests/RateLimiterRejectedExceptionTests.cs

View workflow job for this annotation

GitHub Actions / windows-latest

The name 'BinarySerializationUtil' does not exist in the current context

Check failure on line 152 in test/Polly.RateLimiting.Tests/RateLimiterRejectedExceptionTests.cs

View workflow job for this annotation

GitHub Actions / windows-latest

The name 'BinarySerializationUtil' does not exist in the current context

Check failure on line 152 in test/Polly.RateLimiting.Tests/RateLimiterRejectedExceptionTests.cs

View workflow job for this annotation

GitHub Actions / mutations-legacy

The name 'BinarySerializationUtil' does not exist in the current context

Check failure on line 152 in test/Polly.RateLimiting.Tests/RateLimiterRejectedExceptionTests.cs

View workflow job for this annotation

GitHub Actions / mutations-legacy

The name 'BinarySerializationUtil' does not exist in the current context
result.RetryAfter.Should().Be(timeout);

result = SerializeAndDeserializeException(new RateLimiterRejectedException());
result = BinarySerializationUtil.SerializeAndDeserializeException(new RateLimiterRejectedException(TimeSpan.Zero));

Check failure on line 155 in test/Polly.RateLimiting.Tests/RateLimiterRejectedExceptionTests.cs

View workflow job for this annotation

GitHub Actions / mutations-core

The name 'BinarySerializationUtil' does not exist in the current context

Check failure on line 155 in test/Polly.RateLimiting.Tests/RateLimiterRejectedExceptionTests.cs

View workflow job for this annotation

GitHub Actions / mutations-core

The name 'BinarySerializationUtil' does not exist in the current context

Check failure on line 155 in test/Polly.RateLimiting.Tests/RateLimiterRejectedExceptionTests.cs

View workflow job for this annotation

GitHub Actions / windows-latest

The name 'BinarySerializationUtil' does not exist in the current context

Check failure on line 155 in test/Polly.RateLimiting.Tests/RateLimiterRejectedExceptionTests.cs

View workflow job for this annotation

GitHub Actions / windows-latest

The name 'BinarySerializationUtil' does not exist in the current context

Check failure on line 155 in test/Polly.RateLimiting.Tests/RateLimiterRejectedExceptionTests.cs

View workflow job for this annotation

GitHub Actions / mutations-legacy

The name 'BinarySerializationUtil' does not exist in the current context

Check failure on line 155 in test/Polly.RateLimiting.Tests/RateLimiterRejectedExceptionTests.cs

View workflow job for this annotation

GitHub Actions / mutations-legacy

The name 'BinarySerializationUtil' does not exist in the current context
result.RetryAfter.Should().BeNull();
}

public static T SerializeAndDeserializeException<T>(T exception)
where T : Exception
{
using var stream = new MemoryStream();
var formatter = new System.Runtime.Serialization.Formatters.Binary.BinaryFormatter();
formatter.Serialize(stream, exception);
stream.Position = 0;
return (T)formatter.Deserialize(stream);
result = BinarySerializationUtil.SerializeAndDeserializeException(new RateLimiterRejectedException());

Check failure on line 158 in test/Polly.RateLimiting.Tests/RateLimiterRejectedExceptionTests.cs

View workflow job for this annotation

GitHub Actions / mutations-core

The name 'BinarySerializationUtil' does not exist in the current context

Check failure on line 158 in test/Polly.RateLimiting.Tests/RateLimiterRejectedExceptionTests.cs

View workflow job for this annotation

GitHub Actions / mutations-core

The name 'BinarySerializationUtil' does not exist in the current context

Check failure on line 158 in test/Polly.RateLimiting.Tests/RateLimiterRejectedExceptionTests.cs

View workflow job for this annotation

GitHub Actions / windows-latest

The name 'BinarySerializationUtil' does not exist in the current context

Check failure on line 158 in test/Polly.RateLimiting.Tests/RateLimiterRejectedExceptionTests.cs

View workflow job for this annotation

GitHub Actions / windows-latest

The name 'BinarySerializationUtil' does not exist in the current context

Check failure on line 158 in test/Polly.RateLimiting.Tests/RateLimiterRejectedExceptionTests.cs

View workflow job for this annotation

GitHub Actions / mutations-legacy

The name 'BinarySerializationUtil' does not exist in the current context

Check failure on line 158 in test/Polly.RateLimiting.Tests/RateLimiterRejectedExceptionTests.cs

View workflow job for this annotation

GitHub Actions / mutations-legacy

The name 'BinarySerializationUtil' does not exist in the current context
result.RetryAfter.Should().BeNull();

result = BinarySerializationUtil.SerializeAndDeserializeException(new RateLimiterRejectedException(_source));

Check failure on line 161 in test/Polly.RateLimiting.Tests/RateLimiterRejectedExceptionTests.cs

View workflow job for this annotation

GitHub Actions / mutations-core

The name 'BinarySerializationUtil' does not exist in the current context

Check failure on line 161 in test/Polly.RateLimiting.Tests/RateLimiterRejectedExceptionTests.cs

View workflow job for this annotation

GitHub Actions / mutations-core

The name 'BinarySerializationUtil' does not exist in the current context

Check failure on line 161 in test/Polly.RateLimiting.Tests/RateLimiterRejectedExceptionTests.cs

View workflow job for this annotation

GitHub Actions / windows-latest

The name 'BinarySerializationUtil' does not exist in the current context

Check failure on line 161 in test/Polly.RateLimiting.Tests/RateLimiterRejectedExceptionTests.cs

View workflow job for this annotation

GitHub Actions / windows-latest

The name 'BinarySerializationUtil' does not exist in the current context

Check failure on line 161 in test/Polly.RateLimiting.Tests/RateLimiterRejectedExceptionTests.cs

View workflow job for this annotation

GitHub Actions / mutations-legacy

The name 'BinarySerializationUtil' does not exist in the current context

Check failure on line 161 in test/Polly.RateLimiting.Tests/RateLimiterRejectedExceptionTests.cs

View workflow job for this annotation

GitHub Actions / mutations-legacy

The name 'BinarySerializationUtil' does not exist in the current context
result.TelemetrySource.Should().Be(_telemetrySource);
}
#endif
}

0 comments on commit e7bedd2

Please sign in to comment.