Skip to content

Commit

Permalink
Make IExecutionStrategy a scoped service.
Browse files Browse the repository at this point in the history
  • Loading branch information
AndriySvyryd committed Sep 2, 2021
1 parent c4bc2f9 commit 82a82ba
Show file tree
Hide file tree
Showing 24 changed files with 283 additions and 458 deletions.
121 changes: 25 additions & 96 deletions src/EFCore.Cosmos/Storage/Internal/CosmosClientWrapper.cs
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,6 @@
using Microsoft.EntityFrameworkCore.Infrastructure;
using Microsoft.EntityFrameworkCore.Metadata;
using Microsoft.EntityFrameworkCore.Metadata.Conventions;
using Microsoft.EntityFrameworkCore.Metadata.Internal;
using Microsoft.EntityFrameworkCore.Storage;
using Microsoft.EntityFrameworkCore.Update;
using Microsoft.EntityFrameworkCore.Utilities;
Expand Down Expand Up @@ -63,7 +62,7 @@ public class CosmosClientWrapper : ICosmosClientWrapper

private readonly ISingletonCosmosClientWrapper _singletonWrapper;
private readonly string _databaseId;
private readonly IExecutionStrategyFactory _executionStrategyFactory;
private readonly IExecutionStrategy _executionStrategy;
private readonly IDiagnosticsLogger<DbLoggerCategory.Database.Command> _commandLogger;
private readonly bool? _enableContentResponseOnWrite;

Expand All @@ -84,14 +83,14 @@ static CosmosClientWrapper()
public CosmosClientWrapper(
ISingletonCosmosClientWrapper singletonWrapper,
IDbContextOptions dbContextOptions,
IExecutionStrategyFactory executionStrategyFactory,
IExecutionStrategy executionStrategy,
IDiagnosticsLogger<DbLoggerCategory.Database.Command> commandLogger)
{
var options = dbContextOptions.FindExtension<CosmosOptionsExtension>();

_singletonWrapper = singletonWrapper;
_databaseId = options!.DatabaseName;
_executionStrategyFactory = executionStrategyFactory;
_executionStrategy = executionStrategy;
_commandLogger = commandLogger;
_enableContentResponseOnWrite = options.EnableContentResponseOnWrite;
}
Expand All @@ -106,12 +105,7 @@ private CosmosClient Client
/// doing so can result in application failures when updating to a new Entity Framework Core release.
/// </summary>
public virtual bool CreateDatabaseIfNotExists(ThroughputProperties? throughput)
{
var executionStrategy = _executionStrategyFactory.Create();
var result = executionStrategy.Execute((throughput, this), CreateDatabaseIfNotExistsOnce, null);
_executionStrategyFactory.Return(executionStrategy);
return result;
}
=> _executionStrategy.Execute((throughput, this), CreateDatabaseIfNotExistsOnce, null);

private static bool CreateDatabaseIfNotExistsOnce(
DbContext? context,
Expand All @@ -124,16 +118,11 @@ private static bool CreateDatabaseIfNotExistsOnce(
/// any release. You should only use it directly in your code with extreme caution and knowing that
/// doing so can result in application failures when updating to a new Entity Framework Core release.
/// </summary>
public virtual async Task<bool> CreateDatabaseIfNotExistsAsync(
public virtual Task<bool> CreateDatabaseIfNotExistsAsync(
ThroughputProperties? throughput,
CancellationToken cancellationToken = default)
{
var executionStrategy = _executionStrategyFactory.Create();
var result = await executionStrategy.ExecuteAsync(
(throughput, this), CreateDatabaseIfNotExistsOnceAsync, null, cancellationToken).ConfigureAwait(false);
_executionStrategyFactory.Return(executionStrategy);
return result;
}
=> _executionStrategy.ExecuteAsync(
(throughput, this), CreateDatabaseIfNotExistsOnceAsync, null, cancellationToken);

private static async Task<bool> CreateDatabaseIfNotExistsOnceAsync(
DbContext? _,
Expand All @@ -154,12 +143,7 @@ private static async Task<bool> CreateDatabaseIfNotExistsOnceAsync(
/// doing so can result in application failures when updating to a new Entity Framework Core release.
/// </summary>
public virtual bool DeleteDatabase()
{
var executionStrategy = _executionStrategyFactory.Create();
var result = executionStrategy.Execute(this, DeleteDatabaseOnce, null);
_executionStrategyFactory.Return(executionStrategy);
return result;
}
=> _executionStrategy.Execute(this, DeleteDatabaseOnce, null);

private static bool DeleteDatabaseOnce(
DbContext? context,
Expand All @@ -172,15 +156,9 @@ private static bool DeleteDatabaseOnce(
/// any release. You should only use it directly in your code with extreme caution and knowing that
/// doing so can result in application failures when updating to a new Entity Framework Core release.
/// </summary>
public virtual async Task<bool> DeleteDatabaseAsync(
public virtual Task<bool> DeleteDatabaseAsync(
CancellationToken cancellationToken = default)
{
var executionStrategy = _executionStrategyFactory.Create();
var result = await executionStrategy.ExecuteAsync(
this, DeleteDatabaseOnceAsync, null, cancellationToken).ConfigureAwait(false);
_executionStrategyFactory.Return(executionStrategy);
return result;
}
=> _executionStrategy.ExecuteAsync(this, DeleteDatabaseOnceAsync, null, cancellationToken);

private static async Task<bool> DeleteDatabaseOnceAsync(
DbContext? _,
Expand All @@ -205,12 +183,7 @@ private static async Task<bool> DeleteDatabaseOnceAsync(
/// doing so can result in application failures when updating to a new Entity Framework Core release.
/// </summary>
public virtual bool CreateContainerIfNotExists(ContainerProperties properties)
{
var executionStrategy = _executionStrategyFactory.Create();
var result = executionStrategy.Execute((properties, this), CreateContainerIfNotExistsOnce, null);
_executionStrategyFactory.Return(executionStrategy);
return result;
}
=> _executionStrategy.Execute((properties, this), CreateContainerIfNotExistsOnce, null);

private static bool CreateContainerIfNotExistsOnce(
DbContext context,
Expand All @@ -223,14 +196,8 @@ private static bool CreateContainerIfNotExistsOnce(
/// any release. You should only use it directly in your code with extreme caution and knowing that
/// doing so can result in application failures when updating to a new Entity Framework Core release.
/// </summary>
public virtual async Task<bool> CreateContainerIfNotExistsAsync(ContainerProperties properties, CancellationToken cancellationToken = default)
{
var executionStrategy = _executionStrategyFactory.Create();
var result = await executionStrategy.ExecuteAsync(
(properties, this), CreateContainerIfNotExistsOnceAsync, null, cancellationToken).ConfigureAwait(false);
_executionStrategyFactory.Return(executionStrategy);
return result;
}
public virtual Task<bool> CreateContainerIfNotExistsAsync(ContainerProperties properties, CancellationToken cancellationToken = default)
=> _executionStrategy.ExecuteAsync((properties, this), CreateContainerIfNotExistsOnceAsync, null, cancellationToken);

private static async Task<bool> CreateContainerIfNotExistsOnceAsync(
DbContext _,
Expand Down Expand Up @@ -268,12 +235,7 @@ public virtual bool CreateItem(
string containerId,
JToken document,
IUpdateEntry entry)
{
var executionStrategy = _executionStrategyFactory.Create();
var result = executionStrategy.Execute((containerId, document, entry, this), CreateItemOnce, null);
_executionStrategyFactory.Return(executionStrategy);
return result;
}
=> _executionStrategy.Execute((containerId, document, entry, this), CreateItemOnce, null);

private static bool CreateItemOnce(
DbContext context,
Expand All @@ -286,18 +248,12 @@ private static bool CreateItemOnce(
/// any release. You should only use it directly in your code with extreme caution and knowing that
/// doing so can result in application failures when updating to a new Entity Framework Core release.
/// </summary>
public virtual async Task<bool> CreateItemAsync(
public virtual Task<bool> CreateItemAsync(
string containerId,
JToken document,
IUpdateEntry updateEntry,
CancellationToken cancellationToken = default)
{
var executionStrategy = _executionStrategyFactory.Create();
var result = await executionStrategy.ExecuteAsync(
(containerId, document, updateEntry, this), CreateItemOnceAsync, null, cancellationToken).ConfigureAwait(false);
_executionStrategyFactory.Return(executionStrategy);
return result;
}
=> _executionStrategy.ExecuteAsync((containerId, document, updateEntry, this), CreateItemOnceAsync, null, cancellationToken);

private async static Task<bool> CreateItemOnceAsync(
DbContext _,
Expand Down Expand Up @@ -347,13 +303,7 @@ public virtual bool ReplaceItem(
string documentId,
JObject document,
IUpdateEntry entry)
{
var executionStrategy = _executionStrategyFactory.Create();
var result = executionStrategy.Execute(
(collectionId, documentId, document, entry, this), ReplaceItemOnce, null);
_executionStrategyFactory.Return(executionStrategy);
return result;
}
=> _executionStrategy.Execute((collectionId, documentId, document, entry, this), ReplaceItemOnce, null);

private static bool ReplaceItemOnce(
DbContext context,
Expand All @@ -366,20 +316,14 @@ private static bool ReplaceItemOnce(
/// any release. You should only use it directly in your code with extreme caution and knowing that
/// doing so can result in application failures when updating to a new Entity Framework Core release.
/// </summary>
public virtual async Task<bool> ReplaceItemAsync(
public virtual Task<bool> ReplaceItemAsync(
string collectionId,
string documentId,
JObject document,
IUpdateEntry updateEntry,
CancellationToken cancellationToken = default)
{
var executionStrategy = _executionStrategyFactory.Create();
var result = await executionStrategy.ExecuteAsync(
(collectionId, documentId, document, updateEntry, this), ReplaceItemOnceAsync, null, cancellationToken)
.ConfigureAwait(false);
_executionStrategyFactory.Return(executionStrategy);
return result;
}
=> _executionStrategy.ExecuteAsync(
(collectionId, documentId, document, updateEntry, this), ReplaceItemOnceAsync, null, cancellationToken);

private async static Task<bool> ReplaceItemOnceAsync(
DbContext _,
Expand Down Expand Up @@ -429,12 +373,7 @@ public virtual bool DeleteItem(
string containerId,
string documentId,
IUpdateEntry entry)
{
var executionStrategy = _executionStrategyFactory.Create();
var result = executionStrategy.Execute((containerId, documentId, entry, this), DeleteItemOnce, null);
_executionStrategyFactory.Return(executionStrategy);
return result;
}
=> _executionStrategy.Execute((containerId, documentId, entry, this), DeleteItemOnce, null);

private static bool DeleteItemOnce(
DbContext context,
Expand All @@ -447,18 +386,12 @@ private static bool DeleteItemOnce(
/// any release. You should only use it directly in your code with extreme caution and knowing that
/// doing so can result in application failures when updating to a new Entity Framework Core release.
/// </summary>
public virtual async Task<bool> DeleteItemAsync(
public virtual Task<bool> DeleteItemAsync(
string containerId,
string documentId,
IUpdateEntry entry,
CancellationToken cancellationToken = default)
{
var executionStrategy = _executionStrategyFactory.Create();
var result = await executionStrategy.ExecuteAsync(
(containerId, documentId, entry, this), DeleteItemOnceAsync, null, cancellationToken).ConfigureAwait(false);
_executionStrategyFactory.Return(executionStrategy);
return result;
}
=> _executionStrategy.ExecuteAsync((containerId, documentId, entry, this), DeleteItemOnceAsync, null, cancellationToken);

private static async Task<bool> DeleteItemOnceAsync(
DbContext? _,
Expand Down Expand Up @@ -625,9 +558,7 @@ public virtual JObject ExecuteReadItem(
{
_commandLogger.ExecutingReadItem(containerId, partitionKey, resourceId);

var executionStrategy = _executionStrategyFactory.Create();
var response = executionStrategy.Execute((containerId, partitionKey, resourceId, this), CreateSingleItemQuery, null);
_executionStrategyFactory.Return(executionStrategy);
var response = _executionStrategy.Execute((containerId, partitionKey, resourceId, this), CreateSingleItemQuery, null);

_commandLogger.ExecutedReadItem(
response.Diagnostics.GetClientElapsedTime(),
Expand All @@ -654,14 +585,12 @@ public virtual async Task<JObject> ExecuteReadItemAsync(
{
_commandLogger.ExecutingReadItem(containerId, partitionKey, resourceId);

var executionStrategy = _executionStrategyFactory.Create();
var response = await executionStrategy.ExecuteAsync(
var response = await _executionStrategy.ExecuteAsync(
(containerId, partitionKey, resourceId, this),
CreateSingleItemQueryAsync,
null,
cancellationToken)
.ConfigureAwait(false);
_executionStrategyFactory.Return(executionStrategy);

_commandLogger.ExecutedReadItem(
response.Diagnostics.GetClientElapsedTime(),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,6 @@ namespace Microsoft.EntityFrameworkCore.Cosmos.Storage.Internal
public class CosmosExecutionStrategyFactory : IExecutionStrategyFactory
{
private readonly Func<ExecutionStrategyDependencies, IExecutionStrategy> _createExecutionStrategy;
private IExecutionStrategy? _instance;

/// <summary>
/// This is an internal API that supports the Entity Framework Core infrastructure and not subject to
Expand Down Expand Up @@ -68,26 +67,6 @@ protected virtual IExecutionStrategy CreateDefaultStrategy(ExecutionStrategyDepe
/// doing so can result in application failures when updating to a new Entity Framework Core release.
/// </summary>
public virtual IExecutionStrategy Create()
{
var instance = _instance;
if (instance != null)
{
_instance = null;
return instance;
}

return _createExecutionStrategy(Dependencies);
}

/// <summary>
/// This is an internal API that supports the Entity Framework Core infrastructure and not subject to
/// the same compatibility standards as public APIs. It may be changed or removed without notice in
/// any release. You should only use it directly in your code with extreme caution and knowing that
/// doing so can result in application failures when updating to a new Entity Framework Core release.
/// </summary>
public virtual void Return(IExecutionStrategy executionStrategy)
{
_instance = executionStrategy;
}
=> _createExecutionStrategy(Dependencies);
}
}
Loading

0 comments on commit 82a82ba

Please sign in to comment.