Skip to content

Commit

Permalink
Merge pull request #487 from App-vNext/v610dev
Browse files Browse the repository at this point in the history
Merge v6.1.0 to master
  • Loading branch information
reisenberger authored Jul 14, 2018
2 parents 9947e06 + 21130f8 commit dec0b02
Show file tree
Hide file tree
Showing 52 changed files with 2,502 additions and 150 deletions.
7 changes: 7 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,10 @@
## 6.1.0
- Bug Fix: Context.PolicyKey behaviour in PolicyWrap (issue 463)
- Bug Fix: CachePolicy behaviour with non-nullable types (issues 472, 475)
- Enhancement: WaitAnd/RetryForever overloads where onRetry takes the retry number as a parameter (issue 451)
- Enhancement: Overloads where onTimeout takes thrown exception as a parameter (issue 338)
- Enhancement: Improved cache error message (issue 455)

## 6.0.1
- Version 6 RTM, for integration to ASPNET Core 2.1 IHttpClientFactory

Expand Down
2 changes: 1 addition & 1 deletion GitVersionConfig.yaml
Original file line number Diff line number Diff line change
@@ -1 +1 @@
next-version: 6.0.1
next-version: 6.1.0
24 changes: 18 additions & 6 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -309,7 +309,9 @@ Policy
});
```

For more detail see: [Retry policy documentation](https://github.com/App-vNext/Polly/wiki/Retry) on wiki.
If all retries fail, a retry policy rethrows the final exception back to the calling code.

For more depth see also: [Retry policy documentation on wiki](https://github.com/App-vNext/Polly/wiki/Retry).

### Circuit Breaker

Expand Down Expand Up @@ -355,7 +357,10 @@ breaker.Isolate();
breaker.Reset();

```
For more detail see: [Circuit-Breaker documentation](https://github.com/App-vNext/Polly/wiki/Circuit-Breaker) on wiki.

Note that circuit-breaker policies [rethrow all exceptions](https://github.com/App-vNext/Polly/wiki/Circuit-Breaker#exception-handling), even handled ones. A circuit-breaker exists to measure faults and break the circuit when too many faults occur, but does not orchestrate retries. Combine a circuit-breaker with a retry policy as needed.

For more depth see also: [Circuit-Breaker documentation on wiki](https://github.com/App-vNext/Polly/wiki/Circuit-Breaker).

### Advanced Circuit Breaker
```csharp
Expand Down Expand Up @@ -589,22 +594,27 @@ For more detail see: [Bulkhead policy documentation](https://github.com/App-vNex
var memoryCacheProvider = new MemoryCacheProvider(MemoryCache.Default);
var cachePolicy = Policy.Cache(memoryCacheProvider, TimeSpan.FromMinutes(5));

// For .NET Core examples see the CacheProviders linked to from https://github.com/App-vNext/Polly/wiki/Cache#working-with-cacheproviders :
// - https://github.com/App-vNext/Polly.Caching.MemoryCache
// - https://github.com/App-vNext/Polly.Caching.IDistributedCache
// Define a cache policy with absolute expiration at midnight tonight.
var cachePolicy = Policy.Cache(memoryCacheProvider, new AbsoluteTtl(DateTimeOffset.Now.Date.AddDays(1));

// Define a cache policy with sliding expiration: items remain valid for another 5 minutes each time the cache item is used.
var cachePolicy = Policy.Cache(memoryCacheProvider, new SlidingTtl(TimeSpan.FromMinutes(5));

// Execute through the cache as a read-through cache: check the cache first; if not found, execute underlying delegate and store the result in the cache.
TResult result = cachePolicy.Execute(() => getFoo(), new Context("FooKey")); // "FooKey" is the cache key used in this execution.
// Define a cache Policy, and catch any cache provider errors for logging.
var cachePolicy = Policy.Cache(myCacheProvider, TimeSpan.FromMinutes(5),
(context, key, ex) => {
logger.Error($"Cache provider, for key {key}, threw exception: {ex}."); // (for example)
}
);

// Execute through the cache as a read-through cache: check the cache first; if not found, execute underlying delegate and store the result in the cache.
// The key to use for caching, for a particular execution, is specified by setting the OperationKey (before v6: ExecutionKey) on a Context instance passed to the execution. Use an overload of the form shown below (or a richer overload including the same elements).
// Example: "FooKey" is the cache key that will be used in the below execution.
TResult result = cachePolicy.Execute(context => getFoo(), new Context("FooKey"));

```

Expand Down Expand Up @@ -772,7 +782,7 @@ var policy = Policy
.WithPolicyKey("MyDataAccessPolicy");

int id = ... // customer id from somewhere
var customerDetails = policy.Execute(() => GetCustomer(id),
var customerDetails = policy.Execute(context => GetCustomer(id),
new Context("GetCustomerDetails", new Dictionary<string, object>() {{"Type","Customer"},{"Id",id}}
));
```
Expand Down Expand Up @@ -980,6 +990,8 @@ For full detailed of supported targets by version, see [supported targets](https
* [@benagain](https://github.com/benagain) - Bug fix: RelativeTtl in CachePolicy now always returns a ttl relative to time item is cached.
* [@urig](https://github.com/urig) - Allow TimeoutPolicy to be configured with Timeout.InfiniteTimeSpan.
* [@reisenberger](https://github.com/reisenberger) - Integration with [IHttpClientFactory](https://github.com/aspnet/HttpClientFactory/) for ASPNET Core 2.1.
* [@freakazoid182](https://github.com/Freakazoid182) - WaitAnd/RetryForever overloads where onRetry takes the retry number as a parameter.
* [@dustyhoppe](https://github.com/dustyhoppe) - Overloads where onTimeout takes thrown exception as a parameter
# Sample Projects

Expand Down
4 changes: 2 additions & 2 deletions src/Polly.NetStandard11/Properties/AssemblyInfo.cs
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,8 @@
using System.Runtime.CompilerServices;

[assembly: AssemblyTitle("Polly")]
[assembly: AssemblyInformationalVersion("6.0.1.0")]
[assembly: AssemblyFileVersion("6.0.1.0")]
[assembly: AssemblyInformationalVersion("6.1.0.0")]
[assembly: AssemblyFileVersion("6.1.0.0")]
[assembly: AssemblyVersion("6.0.0.0")]
[assembly: CLSCompliant(true)]

Expand Down
4 changes: 2 additions & 2 deletions src/Polly.NetStandard20/Properties/AssemblyInfo.cs
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,8 @@
using System.Runtime.CompilerServices;

[assembly: AssemblyTitle("Polly")]
[assembly: AssemblyInformationalVersion("6.0.1.0")]
[assembly: AssemblyFileVersion("6.0.1.0")]
[assembly: AssemblyInformationalVersion("6.1.0.0")]
[assembly: AssemblyFileVersion("6.1.0.0")]
[assembly: AssemblyVersion("6.0.0.0")]
[assembly: CLSCompliant(true)]

Expand Down
2 changes: 2 additions & 0 deletions src/Polly.Shared/Caching/CachePolicy.cs
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,8 @@ internal CachePolicy(
[DebuggerStepThrough]
internal override TResult ExecuteInternal<TResult>(Func<Context, CancellationToken, TResult> action, Context context, CancellationToken cancellationToken)
{
if (_syncCacheProvider == null) throw new InvalidOperationException("Please use the synchronous-defined policies when calling the synchronous Execute (and similar) methods.");

return CacheEngine.Implementation<TResult>(
_syncCacheProvider.For<TResult>(),
_ttlStrategy.For<TResult>(),
Expand Down
2 changes: 2 additions & 0 deletions src/Polly.Shared/Caching/CachePolicyAsync.cs
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,8 @@ internal CachePolicy(
[DebuggerStepThrough]
internal override Task<TResult> ExecuteAsyncInternal<TResult>(Func<Context, CancellationToken, Task<TResult>> action, Context context, CancellationToken cancellationToken, bool continueOnCapturedContext)
{
if (_asyncCacheProvider == null) throw new InvalidOperationException("Please use asynchronous-defined policies when calling asynchronous ExecuteAsync (and similar) methods.");

return CacheEngine.ImplementationAsync<TResult>(
_asyncCacheProvider.AsyncFor<TResult>(),
_ttlStrategy.For<TResult>(),
Expand Down
6 changes: 2 additions & 4 deletions src/Polly.Shared/Caching/GenericCacheProvider.cs
Original file line number Diff line number Diff line change
Expand Up @@ -12,14 +12,12 @@ internal class GenericCacheProvider<TCacheFormat> : ISyncCacheProvider<TCacheFor

internal GenericCacheProvider(ISyncCacheProvider nonGenericCacheProvider)
{
if (nonGenericCacheProvider == null) throw new ArgumentNullException(nameof(nonGenericCacheProvider));

_wrappedCacheProvider = nonGenericCacheProvider;
_wrappedCacheProvider = nonGenericCacheProvider ?? throw new ArgumentNullException(nameof(nonGenericCacheProvider));
}

TCacheFormat ISyncCacheProvider<TCacheFormat>.Get(string key)
{
return (TCacheFormat) _wrappedCacheProvider.Get(key);
return (TCacheFormat) (_wrappedCacheProvider.Get(key) ?? default(TCacheFormat));
}

void ISyncCacheProvider<TCacheFormat>.Put(string key, TCacheFormat value, Ttl ttl)
Expand Down
6 changes: 2 additions & 4 deletions src/Polly.Shared/Caching/GenericCacheProviderAsync.cs
Original file line number Diff line number Diff line change
Expand Up @@ -14,14 +14,12 @@ internal class GenericCacheProviderAsync<TCacheFormat> : IAsyncCacheProvider<TCa

internal GenericCacheProviderAsync(IAsyncCacheProvider nonGenericCacheProvider)
{
if (nonGenericCacheProvider == null) throw new ArgumentNullException(nameof(nonGenericCacheProvider));

_wrappedCacheProvider = nonGenericCacheProvider;
_wrappedCacheProvider = nonGenericCacheProvider ?? throw new ArgumentNullException(nameof(nonGenericCacheProvider));
}

async Task<TCacheFormat> IAsyncCacheProvider<TCacheFormat>.GetAsync(string key, CancellationToken cancellationToken, bool continueOnCapturedContext)
{
return (TCacheFormat) await _wrappedCacheProvider.GetAsync(key, cancellationToken, continueOnCapturedContext).ConfigureAwait(continueOnCapturedContext);
return (TCacheFormat) (await _wrappedCacheProvider.GetAsync(key, cancellationToken, continueOnCapturedContext).ConfigureAwait(continueOnCapturedContext) ?? default(TCacheFormat));
}

Task IAsyncCacheProvider<TCacheFormat>.PutAsync(string key, TCacheFormat value, Ttl ttl, CancellationToken cancellationToken, bool continueOnCapturedContext)
Expand Down
26 changes: 12 additions & 14 deletions src/Polly.Shared/Caching/SerializingCacheProvider.cs
Original file line number Diff line number Diff line change
Expand Up @@ -20,11 +20,8 @@ public class SerializingCacheProvider<TSerialized> : ISyncCacheProvider
/// <exception cref="System.ArgumentNullException">serializer </exception>
public SerializingCacheProvider(ISyncCacheProvider<TSerialized> wrappedCacheProvider, ICacheItemSerializer<object, TSerialized> serializer)
{
if (wrappedCacheProvider == null) throw new ArgumentNullException(nameof(wrappedCacheProvider));
if (serializer == null) throw new ArgumentNullException(nameof(serializer));

_wrappedCacheProvider = wrappedCacheProvider;
_serializer = serializer;
_wrappedCacheProvider = wrappedCacheProvider ?? throw new ArgumentNullException(nameof(wrappedCacheProvider));
_serializer = serializer ?? throw new ArgumentNullException(nameof(serializer));
}

/// <summary>
Expand All @@ -34,7 +31,8 @@ public SerializingCacheProvider(ISyncCacheProvider<TSerialized> wrappedCacheProv
/// <returns>The value from cache; or null, if none was found.</returns>
public object Get(string key)
{
return _serializer.Deserialize(_wrappedCacheProvider.Get(key));
TSerialized objectToDeserialize = _wrappedCacheProvider.Get(key);
return objectToDeserialize == null || objectToDeserialize.Equals(default(TSerialized)) ? null : _serializer.Deserialize(objectToDeserialize);
}

/// <summary>
Expand All @@ -45,7 +43,8 @@ public object Get(string key)
/// <param name="ttl">The time-to-live for the cache entry.</param>
public void Put(string key, object value, Ttl ttl)
{
_wrappedCacheProvider.Put(key, _serializer.Serialize(value), ttl);
if (value != null)
_wrappedCacheProvider.Put(key, _serializer.Serialize(value), ttl);
}

}
Expand All @@ -69,11 +68,8 @@ public class SerializingCacheProvider<TResult, TSerialized> : ISyncCacheProvider
/// <exception cref="System.ArgumentNullException">serializer </exception>
public SerializingCacheProvider(ISyncCacheProvider<TSerialized> wrappedCacheProvider, ICacheItemSerializer<TResult, TSerialized> serializer)
{
if (wrappedCacheProvider == null) throw new ArgumentNullException(nameof(wrappedCacheProvider));
if (serializer == null) throw new ArgumentNullException(nameof(serializer));

_wrappedCacheProvider = wrappedCacheProvider;
_serializer = serializer;
_wrappedCacheProvider = wrappedCacheProvider ?? throw new ArgumentNullException(nameof(wrappedCacheProvider));
_serializer = serializer ?? throw new ArgumentNullException(nameof(serializer));
}

/// <summary>
Expand All @@ -83,7 +79,8 @@ public SerializingCacheProvider(ISyncCacheProvider<TSerialized> wrappedCacheProv
/// <returns>The value from cache; or null, if none was found.</returns>
public TResult Get(string key)
{
return _serializer.Deserialize(_wrappedCacheProvider.Get(key));
TSerialized objectToDeserialize = _wrappedCacheProvider.Get(key);
return objectToDeserialize == null || objectToDeserialize.Equals(default(TSerialized)) ? default(TResult) : _serializer.Deserialize(objectToDeserialize);
}

/// <summary>
Expand All @@ -94,7 +91,8 @@ public TResult Get(string key)
/// <param name="ttl">The time-to-live for the cache entry.</param>
public void Put(string key, TResult value, Ttl ttl)
{
_wrappedCacheProvider.Put(key, _serializer.Serialize(value), ttl);
if (value != null && !value.Equals(default(TResult)))
_wrappedCacheProvider.Put(key, _serializer.Serialize(value), ttl);
}

}
Expand Down
30 changes: 14 additions & 16 deletions src/Polly.Shared/Caching/SerializingCacheProviderAsync.cs
Original file line number Diff line number Diff line change
Expand Up @@ -22,11 +22,8 @@ public class SerializingCacheProviderAsync<TSerialized> : IAsyncCacheProvider
/// <exception cref="System.ArgumentNullException">serializer </exception>
public SerializingCacheProviderAsync(IAsyncCacheProvider<TSerialized> wrappedCacheProvider, ICacheItemSerializer<object, TSerialized> serializer)
{
if (wrappedCacheProvider == null) throw new ArgumentNullException(nameof(wrappedCacheProvider));
if (serializer == null) throw new ArgumentNullException(nameof(serializer));

_wrappedCacheProvider = wrappedCacheProvider;
_serializer = serializer;
_wrappedCacheProvider = wrappedCacheProvider ?? throw new ArgumentNullException(nameof(wrappedCacheProvider));
_serializer = serializer ?? throw new ArgumentNullException(nameof(serializer));
}

/// <summary>
Expand All @@ -38,8 +35,8 @@ public SerializingCacheProviderAsync(IAsyncCacheProvider<TSerialized> wrappedCac
/// <returns>A <see cref="Task{TResult}" /> promising as Result the value from cache; or null, if none was found.</returns>
public async Task<object> GetAsync(string key, CancellationToken cancellationToken, bool continueOnCapturedContext)
{
return _serializer.Deserialize(
await _wrappedCacheProvider.GetAsync(key, cancellationToken, continueOnCapturedContext).ConfigureAwait(continueOnCapturedContext));
TSerialized objectToDeserialize = await _wrappedCacheProvider.GetAsync(key, cancellationToken, continueOnCapturedContext).ConfigureAwait(continueOnCapturedContext);
return objectToDeserialize == null || objectToDeserialize.Equals(default(TSerialized)) ? null :_serializer.Deserialize(objectToDeserialize);
}

/// <summary>
Expand All @@ -54,7 +51,9 @@ public async Task<object> GetAsync(string key, CancellationToken cancellationTok
public async Task PutAsync(string key, object value, Ttl ttl, CancellationToken cancellationToken,
bool continueOnCapturedContext)
{
await _wrappedCacheProvider.PutAsync(
if (value != null)

await _wrappedCacheProvider.PutAsync(
key,
_serializer.Serialize(value),
ttl,
Expand Down Expand Up @@ -83,11 +82,8 @@ public class SerializingCacheProviderAsync<TResult, TSerialized> : IAsyncCachePr
/// <exception cref="System.ArgumentNullException">serializer </exception>
public SerializingCacheProviderAsync(IAsyncCacheProvider<TSerialized> wrappedCacheProvider, ICacheItemSerializer<TResult, TSerialized> serializer)
{
if (wrappedCacheProvider == null) throw new ArgumentNullException(nameof(wrappedCacheProvider));
if (serializer == null) throw new ArgumentNullException(nameof(serializer));

_wrappedCacheProvider = wrappedCacheProvider;
_serializer = serializer;
_wrappedCacheProvider = wrappedCacheProvider ?? throw new ArgumentNullException(nameof(wrappedCacheProvider));
_serializer = serializer ?? throw new ArgumentNullException(nameof(serializer));
}

/// <summary>
Expand All @@ -99,8 +95,8 @@ public SerializingCacheProviderAsync(IAsyncCacheProvider<TSerialized> wrappedCac
/// <returns>A <see cref="Task{TResult}" /> promising as Result the value from cache; or null, if none was found.</returns>
public async Task<TResult> GetAsync(string key, CancellationToken cancellationToken, bool continueOnCapturedContext)
{
return _serializer.Deserialize(
await _wrappedCacheProvider.GetAsync(key, cancellationToken, continueOnCapturedContext).ConfigureAwait(continueOnCapturedContext));
TSerialized objectToDeserialize = await _wrappedCacheProvider.GetAsync(key, cancellationToken, continueOnCapturedContext).ConfigureAwait(continueOnCapturedContext);
return objectToDeserialize == null || objectToDeserialize.Equals(default(TSerialized)) ? default(TResult) : _serializer.Deserialize(objectToDeserialize);
}

/// <summary>
Expand All @@ -115,7 +111,9 @@ public async Task<TResult> GetAsync(string key, CancellationToken cancellationTo
public async Task PutAsync(string key, TResult value, Ttl ttl, CancellationToken cancellationToken,
bool continueOnCapturedContext)
{
await _wrappedCacheProvider.PutAsync(
if (value != null && !value.Equals(default(TResult)))

await _wrappedCacheProvider.PutAsync(
key,
_serializer.Serialize(value),
ttl,
Expand Down
24 changes: 20 additions & 4 deletions src/Polly.Shared/Policy.Async.ExecuteOverloads.cs
Original file line number Diff line number Diff line change
Expand Up @@ -117,9 +117,17 @@ public Task ExecuteAsync(Func<Context, CancellationToken, Task> action, IDiction
public Task ExecuteAsync(Func<Context, CancellationToken, Task> action, Context context, CancellationToken cancellationToken, bool continueOnCapturedContext)
{
if (context == null) throw new ArgumentNullException(nameof(context));
SetPolicyContext(context);

return ExecuteAsyncInternal(action, context, cancellationToken, continueOnCapturedContext);
SetPolicyContext(context, out string priorPolicyWrapKey, out string priorPolicyKey);

try
{
return ExecuteAsyncInternal(action, context, cancellationToken, continueOnCapturedContext);
}
finally
{
RestorePolicyContext(context, priorPolicyWrapKey, priorPolicyKey);
}
}

#region Overloads method-generic in TResult
Expand Down Expand Up @@ -245,9 +253,17 @@ public Task<TResult> ExecuteAsync<TResult>(Func<Context, CancellationToken, Task
public Task<TResult> ExecuteAsync<TResult>(Func<Context, CancellationToken, Task<TResult>> action, Context context, CancellationToken cancellationToken, bool continueOnCapturedContext)
{
if (context == null) throw new ArgumentNullException(nameof(context));
SetPolicyContext(context);

return ExecuteAsyncInternal(action, context, cancellationToken, continueOnCapturedContext);
SetPolicyContext(context, out string priorPolicyWrapKey, out string priorPolicyKey);

try
{
return ExecuteAsyncInternal(action, context, cancellationToken, continueOnCapturedContext);
}
finally
{
RestorePolicyContext(context, priorPolicyWrapKey, priorPolicyKey);
}
}

#endregion
Expand Down
Loading

0 comments on commit dec0b02

Please sign in to comment.