Skip to content

Commit

Permalink
CosmosQueryExecutionContextFactory Refactory (#988)
Browse files Browse the repository at this point in the history
* drafted out refactor

* removed null check

* resolved some iteration comments

* reproduced failure

* got exceptionless to work for non order by queries

* got exceptionless working for order by

* got parallel basic working

* got non failure case working again

* got continuation token story working

* fixed miscellaneous tests

* got all the combinations working for exceptionless

* added test for empty pages

* uncommented

* wip

* resolved iteration comments

* fixed changelog

* build

* build

* resolved iteration comments

* update test

* automatically advancing page

* fixed some split failures

* fixed split bugs

* fixed continuation token exception

* added a catch all query excetuion context

* ammend

* removed is done check for try get continuation token

* updated baseline

* fixed test since code doesn't just throw exceptions anymore

* removed stack trace from exception

* updated error message one more time?

* updated baselines
  • Loading branch information
bchong95 authored and sboshra committed Nov 18, 2019
1 parent 9f3e8ea commit 6c34648
Show file tree
Hide file tree
Showing 25 changed files with 706 additions and 521 deletions.
55 changes: 55 additions & 0 deletions Microsoft.Azure.Cosmos/src/Query/Core/AsyncLazy.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
// ------------------------------------------------------------
// Copyright (c) Microsoft Corporation. All rights reserved.
// ------------------------------------------------------------

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

internal sealed class AsyncLazy<T>
{
private readonly Func<CancellationToken, Task<T>> valueFactory;
private T value;

public AsyncLazy(Func<CancellationToken, Task<T>> valueFactory)
{
if (valueFactory == null)
{
throw new ArgumentNullException(nameof(valueFactory));
}

this.valueFactory = valueFactory;
}

public bool ValueInitialized { get; private set; }

public async Task<T> GetValueAsync(CancellationToken cancellationToken)
{
// Note that this class is not thread safe.
// if the valueFactory has side effects than this will have issues.
cancellationToken.ThrowIfCancellationRequested();
if (!this.ValueInitialized)
{
this.value = await this.valueFactory(cancellationToken);
this.ValueInitialized = true;
}

return this.value;
}

public T Result
{
get
{
if (!this.ValueInitialized)
{
throw new InvalidOperationException("Can not retrieve value before initialization.");
}

return this.value;
}
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
// ------------------------------------------------------------
// Copyright (c) Microsoft Corporation. All rights reserved.
// ------------------------------------------------------------

namespace Microsoft.Azure.Cosmos.Query.Core.ExecutionContext
{
using System;
using System.Threading;
using System.Threading.Tasks;

internal sealed class CatchAllCosmosQueryExecutionContext : CosmosQueryExecutionContext
{
private readonly CosmosQueryExecutionContext cosmosQueryExecutionContext;
private bool hitException;

public CatchAllCosmosQueryExecutionContext(
CosmosQueryExecutionContext cosmosQueryExecutionContext)
{
if (cosmosQueryExecutionContext == null)
{
throw new ArgumentNullException(nameof(cosmosQueryExecutionContext));
}

this.cosmosQueryExecutionContext = cosmosQueryExecutionContext;
}

public override bool IsDone => this.hitException || this.cosmosQueryExecutionContext.IsDone;

public override void Dispose()
{
this.cosmosQueryExecutionContext.Dispose();
}

public override async Task<QueryResponseCore> ExecuteNextAsync(CancellationToken cancellationToken)
{
if (this.IsDone)
{
throw new InvalidOperationException(
$"Can not {nameof(ExecuteNextAsync)} from a {nameof(CosmosQueryExecutionContext)} where {nameof(this.IsDone)}.");
}

cancellationToken.ThrowIfCancellationRequested();

QueryResponseCore queryResponseCore;
try
{
queryResponseCore = await this.cosmosQueryExecutionContext.ExecuteNextAsync(cancellationToken);
}
catch (Exception ex)
{
queryResponseCore = QueryResponseFactory.CreateFromException(ex);
}

if (!queryResponseCore.IsSuccess)
{
this.hitException = true;
}

return queryResponseCore;
}

public override bool TryGetContinuationToken(out string continuationToken)
{
return this.cosmosQueryExecutionContext.TryGetContinuationToken(out continuationToken);
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -26,10 +26,10 @@ public abstract bool IsDone
/// <summary>
/// Executes the context to feed the next page of results.
/// </summary>
/// <param name="token">The cancellation token.</param>
/// <param name="cancellationToken">The cancellation token.</param>
/// <returns>A task to await on, which in return provides a DoucmentFeedResponse of documents.</returns>
public abstract Task<QueryResponseCore> ExecuteNextAsync(CancellationToken token);
public abstract Task<QueryResponseCore> ExecuteNextAsync(CancellationToken cancellationToken);

public abstract bool TryGetContinuationToken(out string state);
public abstract bool TryGetContinuationToken(out string continuationToken);
}
}
Loading

0 comments on commit 6c34648

Please sign in to comment.