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

Response type: Fix deadlock on scenarios with SynchronizationContext for remaining Response.ResourceType #1437

Merged
merged 2 commits into from
Apr 29, 2020
Merged
Show file tree
Hide file tree
Changes from all 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
Original file line number Diff line number Diff line change
Expand Up @@ -9,34 +9,31 @@ namespace Microsoft.Azure.Cosmos
using System.Threading.Tasks;

// This class acts as a wrapper for environments that use SynchronizationContext.
internal sealed class ConflictsInlineCore : Conflicts
internal sealed class ConflictsInlineCore : ConflictsCore
kirankumarkolli marked this conversation as resolved.
Show resolved Hide resolved
{
private readonly ConflictsCore conflicts;

internal ConflictsInlineCore(ConflictsCore conflicts)
internal ConflictsInlineCore(
CosmosClientContext clientContext,
ContainerInternal container)
: base(
clientContext,
container)
{
if (conflicts == null)
{
throw new ArgumentNullException(nameof(conflicts));
}

this.conflicts = conflicts;
}

public override Task<ResponseMessage> DeleteAsync(
ConflictProperties conflict,
PartitionKey partitionKey,
CancellationToken cancellationToken = default(CancellationToken))
{
return TaskHelper.RunInlineIfNeededAsync(() => this.conflicts.DeleteAsync(conflict, partitionKey, cancellationToken));
return TaskHelper.RunInlineIfNeededAsync(() => base.DeleteAsync(conflict, partitionKey, cancellationToken));
}

public override FeedIterator GetConflictQueryStreamIterator(
string queryText = null,
string continuationToken = null,
QueryRequestOptions requestOptions = null)
{
return new FeedIteratorInlineCore(this.conflicts.GetConflictQueryStreamIterator(
return new FeedIteratorInlineCore(base.GetConflictQueryStreamIterator(
queryText,
continuationToken,
requestOptions));
Expand All @@ -47,7 +44,7 @@ public override FeedIterator<T> GetConflictQueryIterator<T>(
string continuationToken = null,
QueryRequestOptions requestOptions = null)
{
return new FeedIteratorInlineCore<T>(this.conflicts.GetConflictQueryIterator<T>(
return new FeedIteratorInlineCore<T>(base.GetConflictQueryIterator<T>(
queryText,
continuationToken,
requestOptions));
Expand All @@ -58,7 +55,7 @@ public override FeedIterator GetConflictQueryStreamIterator(
string continuationToken = null,
QueryRequestOptions requestOptions = null)
{
return new FeedIteratorInlineCore(this.conflicts.GetConflictQueryStreamIterator(
return new FeedIteratorInlineCore(base.GetConflictQueryStreamIterator(
queryDefinition,
continuationToken,
requestOptions));
Expand All @@ -69,7 +66,7 @@ public override FeedIterator<T> GetConflictQueryIterator<T>(
string continuationToken = null,
QueryRequestOptions requestOptions = null)
{
return new FeedIteratorInlineCore<T>(this.conflicts.GetConflictQueryIterator<T>(
return new FeedIteratorInlineCore<T>(base.GetConflictQueryIterator<T>(
queryDefinition,
continuationToken,
requestOptions));
Expand All @@ -80,12 +77,12 @@ public override Task<ItemResponse<T>> ReadCurrentAsync<T>(
PartitionKey partitionKey,
CancellationToken cancellationToken = default(CancellationToken))
{
return TaskHelper.RunInlineIfNeededAsync(() => this.conflicts.ReadCurrentAsync<T>(cosmosConflict, partitionKey, cancellationToken));
return TaskHelper.RunInlineIfNeededAsync(() => base.ReadCurrentAsync<T>(cosmosConflict, partitionKey, cancellationToken));
}

public override T ReadConflictContent<T>(ConflictProperties cosmosConflict)
{
return this.conflicts.ReadConflictContent<T>(cosmosConflict);
return base.ReadConflictContent<T>(cosmosConflict);
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -39,8 +39,8 @@ protected ContainerCore(
id: containerId);

this.Database = database;
this.Conflicts = new ConflictsInlineCore(new ConflictsCore(this.ClientContext, this));
this.Scripts = new ScriptsInlineCore(new ScriptsCore(this, this.ClientContext));
this.Conflicts = new ConflictsInlineCore(this.ClientContext, this);
this.Scripts = new ScriptsInlineCore(this, this.ClientContext);
this.cachedUriSegmentWithoutId = this.GetResourceSegmentUriWithoutId();
this.queryClient = cosmosQueryClient ?? new CosmosQueryClientCore(this.ClientContext, this);
this.lazyBatchExecutor = new Lazy<BatchAsyncContainerExecutor>(() => this.ClientContext.GetExecutorForContainer(this));
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -457,10 +457,10 @@ public override User GetUser(string id)
throw new ArgumentNullException(nameof(id));
}

return new UserInlineCore(new UserCore(
return new UserInlineCore(
this.ClientContext,
this,
id));
id);
}

public Task<ResponseMessage> CreateUserStreamAsync(
Expand Down
46 changes: 16 additions & 30 deletions Microsoft.Azure.Cosmos/src/Resource/Permission/PermissionCore.cs
Original file line number Diff line number Diff line change
Expand Up @@ -17,40 +17,25 @@ namespace Microsoft.Azure.Cosmos
/// </summary>
internal class PermissionCore : Permission
{
/// <summary>
/// Only used for unit testing
/// </summary>
internal PermissionCore()
{
}
private readonly Uri linkUri;
private readonly CosmosClientContext clientContext;

internal PermissionCore(
CosmosClientContext clientContext,
UserCore user,
string userId)
{
this.Id = userId;
this.ClientContext = clientContext;
this.LinkUri = clientContext.CreateLink(
this.clientContext = clientContext;
this.linkUri = clientContext.CreateLink(
parentLink: user.LinkUri.OriginalString,
uriPathSegment: Paths.PermissionsPathSegment,
id: userId);

this.User = user;
}

/// <inheritdoc/>
public override string Id { get; }

/// <summary>
/// Returns a reference to a user object.
/// </summary>
public User User { get; }

internal virtual Uri LinkUri { get; }

internal virtual CosmosClientContext ClientContext { get; }

/// <inheritdoc/>
public override Task<PermissionResponse> DeleteAsync(RequestOptions requestOptions = null,
CancellationToken cancellationToken = default(CancellationToken))
Expand All @@ -59,11 +44,12 @@ public override Task<PermissionResponse> DeleteAsync(RequestOptions requestOptio
requestOptions: requestOptions,
cancellationToken: cancellationToken);

return this.ClientContext.ResponseFactory.CreatePermissionResponseAsync(this, response);
return this.clientContext.ResponseFactory.CreatePermissionResponseAsync(this, response);
}

public Task<ResponseMessage> DeletePermissionStreamAsync(RequestOptions requestOptions = null,
CancellationToken cancellationToken = default(CancellationToken))
public Task<ResponseMessage> DeletePermissionStreamAsync(
RequestOptions requestOptions,
CancellationToken cancellationToken)
{
return this.ProcessStreamAsync(
streamPayload: null,
Expand All @@ -82,7 +68,7 @@ public override Task<PermissionResponse> ReadAsync(int? tokenExpiryInSeconds = n
requestOptions: requestOptions,
cancellationToken: cancellationToken);

return this.ClientContext.ResponseFactory.CreatePermissionResponseAsync(this, response);
return this.clientContext.ResponseFactory.CreatePermissionResponseAsync(this, response);
}

public Task<ResponseMessage> ReadPermissionStreamAsync(int? tokenExpiryInSeconds = null,
Expand All @@ -108,14 +94,14 @@ public override Task<PermissionResponse> ReplaceAsync(PermissionProperties permi
throw new ArgumentNullException(nameof(permissionProperties));
}

this.ClientContext.ValidateResource(permissionProperties.Id);
this.clientContext.ValidateResource(permissionProperties.Id);
Task<ResponseMessage> response = this.ReplaceStreamInternalAsync(
streamPayload: this.ClientContext.SerializerCore.ToStream(permissionProperties),
streamPayload: this.clientContext.SerializerCore.ToStream(permissionProperties),
tokenExpiryInSeconds: tokenExpiryInSeconds,
requestOptions: requestOptions,
cancellationToken: cancellationToken);

return this.ClientContext.ResponseFactory.CreatePermissionResponseAsync(this, response);
return this.clientContext.ResponseFactory.CreatePermissionResponseAsync(this, response);
}

public Task<ResponseMessage> ReplacePermissionStreamAsync(PermissionProperties permissionProperties,
Expand All @@ -127,9 +113,9 @@ public Task<ResponseMessage> ReplacePermissionStreamAsync(PermissionProperties p
throw new ArgumentNullException(nameof(permissionProperties));
}

this.ClientContext.ValidateResource(permissionProperties.Id);
this.clientContext.ValidateResource(permissionProperties.Id);
return this.ReplaceStreamInternalAsync(
streamPayload: this.ClientContext.SerializerCore.ToStream(permissionProperties),
streamPayload: this.clientContext.SerializerCore.ToStream(permissionProperties),
requestOptions: requestOptions,
cancellationToken: cancellationToken);
}
Expand Down Expand Up @@ -158,7 +144,7 @@ private Task<ResponseMessage> ProcessStreamAsync(
return this.ProcessResourceOperationStreamAsync(
streamPayload: streamPayload,
operationType: operationType,
linkUri: this.LinkUri,
linkUri: this.linkUri,
resourceType: ResourceType.Permission,
tokenExpiryInSeconds: tokenExpiryInSeconds,
requestOptions: requestOptions,
Expand All @@ -174,7 +160,7 @@ private Task<ResponseMessage> ProcessResourceOperationStreamAsync(
RequestOptions requestOptions = null,
CancellationToken cancellationToken = default(CancellationToken))
{
return this.ClientContext.ProcessResourceOperationStreamAsync(
return this.clientContext.ProcessResourceOperationStreamAsync(
resourceUri: linkUri,
resourceType: resourceType,
operationType: operationType,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,33 +4,29 @@

namespace Microsoft.Azure.Cosmos
{
using System;
using System.Threading;
using System.Threading.Tasks;

// This class acts as a wrapper for environments that use SynchronizationContext.
internal sealed class PermissionInlineCore : Permission
internal sealed class PermissionInlineCore : PermissionCore
{
private readonly PermissionCore permission;

public override string Id => this.permission.Id;

internal PermissionInlineCore(PermissionCore database)
internal PermissionInlineCore(
CosmosClientContext clientContext,
UserCore user,
string userId)
: base(
clientContext,
user,
userId)
{
if (database == null)
{
throw new ArgumentNullException(nameof(database));
}

this.permission = database;
}

public override Task<PermissionResponse> ReadAsync(
int? tokenExpiryInSeconds = null,
RequestOptions requestOptions = null,
CancellationToken cancellationToken = default)
{
return TaskHelper.RunInlineIfNeededAsync(() => this.permission.ReadAsync(tokenExpiryInSeconds, requestOptions, cancellationToken));
return TaskHelper.RunInlineIfNeededAsync(() => base.ReadAsync(tokenExpiryInSeconds, requestOptions, cancellationToken));
}

public override Task<PermissionResponse> ReplaceAsync(
Expand All @@ -39,14 +35,14 @@ public override Task<PermissionResponse> ReplaceAsync(
RequestOptions requestOptions = null,
CancellationToken cancellationToken = default)
{
return TaskHelper.RunInlineIfNeededAsync(() => this.permission.ReplaceAsync(permissionProperties, tokenExpiryInSeconds, requestOptions, cancellationToken));
return TaskHelper.RunInlineIfNeededAsync(() => base.ReplaceAsync(permissionProperties, tokenExpiryInSeconds, requestOptions, cancellationToken));
}

public override Task<PermissionResponse> DeleteAsync(
RequestOptions requestOptions = null,
CancellationToken cancellationToken = default)
{
return TaskHelper.RunInlineIfNeededAsync(() => this.permission.DeleteAsync(requestOptions, cancellationToken));
return TaskHelper.RunInlineIfNeededAsync(() => base.DeleteAsync(requestOptions, cancellationToken));
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ namespace Microsoft.Azure.Cosmos.Scripts
using System.Threading.Tasks;
using Microsoft.Azure.Documents;

internal sealed class ScriptsCore : Scripts
internal class ScriptsCore : Scripts
{
private readonly ContainerInternal container;
private readonly CosmosClientContext clientContext;
Expand Down
Loading