public void GivenEmptyInput_WhenGettingProgress_ThenReturnDefaultStatus() { OperationProgress progress = new ReindexInput().GetProgress(); Assert.Equal(0, progress.PercentComplete); Assert.Null(progress.ResourceIds); }
public virtual async Task ReindexAsync(ReindexInput input) { await RequestAsync(nameof(ReindexAsync), new ClientProxyRequestTypeValue { { typeof(ReindexInput), input } }); }
public void GivenMinimumCompletion_WhenGettingProgress_ThenReturnCompletedProgress() { OperationProgress progress = new ReindexInput { Completed = new WatermarkRange(1, 1) }.GetProgress(); Assert.Equal(100, progress.PercentComplete); Assert.Null(progress.ResourceIds); }
private static OperationProgress GetOperationProgress(OperationType type, DurableOrchestrationStatus status) { switch (type) { case OperationType.Reindex: ReindexInput reindexInput = status.Input?.ToObject <ReindexInput>() ?? new ReindexInput(); return(reindexInput.GetProgress()); default: return(new OperationProgress()); } }
public void GivenReindexInput_WhenGettingProgress_ThenReturnComputedProgress(int start, int end, int expected) { int[] expectedTagKeys = new int[] { 1, 3, 10 }; OperationProgress progress = new ReindexInput { Completed = new WatermarkRange(start, end), QueryTagKeys = expectedTagKeys, }.GetProgress(); Assert.Equal(expected, progress.PercentComplete); Assert.True(progress.ResourceIds.SequenceEqual(expectedTagKeys.Select(x => x.ToString(CultureInfo.InvariantCulture)))); }
public async Task ReindexInstancesAsync( [OrchestrationTrigger] IDurableOrchestrationContext context, ILogger logger) { EnsureArg.IsNotNull(context, nameof(context)); logger = context.CreateReplaySafeLogger(logger); ReindexInput input = context.GetInput <ReindexInput>(); // The ID should be a GUID as generated by the trigger, but we'll assert here just to make sure! if (!context.HasInstanceGuid()) { return; } // Fetch the set of query tags that require re-indexing IReadOnlyList <ExtendedQueryTagStoreEntry> queryTags = await GetOperationQueryTagsAsync(context, input); logger.LogInformation( "Found {Count} extended query tag paths to re-index {{{TagPaths}}}.", queryTags.Count, string.Join(", ", queryTags.Select(x => x.Path))); List <int> queryTagKeys = queryTags.Select(x => x.Key).ToList(); if (queryTags.Count > 0) { IReadOnlyList <WatermarkRange> batches = await context.CallActivityWithRetryAsync <IReadOnlyList <WatermarkRange> >( nameof(GetInstanceBatchesV2Async), _options.ActivityRetryOptions, BatchCreationArguments.FromOptions(input.Completed?.Start - 1, _options)); if (batches.Count > 0) { // Note that batches are in reverse order because we start from the highest watermark var batchRange = new WatermarkRange(batches[^ 1].Start, batches[0].End);
public Task ReindexAsync(ReindexInput input) { return(_projectAppService.ReindexAsync(input)); }
public async Task GivenNewOrchestrationWithWork_WhenReindexingInstances_ThenDivideAndReindexBatches() { const int batchSize = 5; _options.BatchSize = batchSize; _options.MaxParallelBatches = 3; IReadOnlyList <WatermarkRange> expectedBatches = CreateBatches(50); var expectedInput = new ReindexInput { QueryTagKeys = new List <int> { 1, 2, 3, 4, 5 } }; var expectedTags = new List <ExtendedQueryTagStoreEntry> { new ExtendedQueryTagStoreEntry(1, "01010101", "AS", null, QueryTagLevel.Instance, ExtendedQueryTagStatus.Adding, QueryStatus.Enabled, 0), new ExtendedQueryTagStoreEntry(2, "02020202", "IS", "foo", QueryTagLevel.Series, ExtendedQueryTagStatus.Adding, QueryStatus.Enabled, 0), new ExtendedQueryTagStoreEntry(4, "04040404", "SH", null, QueryTagLevel.Study, ExtendedQueryTagStatus.Adding, QueryStatus.Enabled, 0) }; // Arrange the input IDurableOrchestrationContext context = CreateContext(); context .GetInput <ReindexInput>() .Returns(expectedInput); context .CallActivityWithRetryAsync <IReadOnlyList <ExtendedQueryTagStoreEntry> >( nameof(ReindexDurableFunction.AssignReindexingOperationAsync), _options.ActivityRetryOptions, expectedInput.QueryTagKeys) .Returns(expectedTags); context .CallActivityWithRetryAsync <IReadOnlyList <WatermarkRange> >( nameof(ReindexDurableFunction.GetInstanceBatchesV2Async), _options.ActivityRetryOptions, Arg.Is(GetPredicate(null))) .Returns(expectedBatches); context .CallActivityWithRetryAsync( nameof(ReindexDurableFunction.ReindexBatchV2Async), _options.ActivityRetryOptions, Arg.Any <ReindexBatchArguments>()) .Returns(Task.CompletedTask); // Invoke the orchestration await _reindexDurableFunction.ReindexInstancesAsync(context, NullLogger.Instance); // Assert behavior context .Received(1) .GetInput <ReindexInput>(); await context .Received(1) .CallActivityWithRetryAsync <IReadOnlyList <ExtendedQueryTagStoreEntry> >( nameof(ReindexDurableFunction.AssignReindexingOperationAsync), _options.ActivityRetryOptions, expectedInput.QueryTagKeys); await context .DidNotReceive() .CallActivityWithRetryAsync <IReadOnlyList <ExtendedQueryTagStoreEntry> >( nameof(ReindexDurableFunction.GetQueryTagsAsync), _options.ActivityRetryOptions, Arg.Any <object>()); await context .Received(1) .CallActivityWithRetryAsync <IReadOnlyList <WatermarkRange> >( nameof(ReindexDurableFunction.GetInstanceBatchesV2Async), _options.ActivityRetryOptions, Arg.Is(GetPredicate(null))); foreach (WatermarkRange batch in expectedBatches) { await context .Received(1) .CallActivityWithRetryAsync( nameof(ReindexDurableFunction.ReindexBatchV2Async), _options.ActivityRetryOptions, Arg.Is(GetPredicate(expectedTags, batch))); } await context .DidNotReceive() .CallActivityWithRetryAsync <IReadOnlyList <int> >( nameof(ReindexDurableFunction.CompleteReindexingAsync), _options.ActivityRetryOptions, Arg.Any <object>()); context .Received(1) .ContinueAsNew( Arg.Is <ReindexInput>(x => GetPredicate(expectedTags, expectedBatches, 50)(x)), false); }
public async Task GivenNoInstances_WhenReindexingInstances_ThenComplete() { var expectedBatches = new List <WatermarkRange>(); var expectedInput = new ReindexInput { QueryTagKeys = new List <int> { 1, 2, 3, 4, 5 } }; var expectedTags = new List <ExtendedQueryTagStoreEntry> { new ExtendedQueryTagStoreEntry(1, "01010101", "AS", null, QueryTagLevel.Instance, ExtendedQueryTagStatus.Adding, QueryStatus.Enabled, 0), new ExtendedQueryTagStoreEntry(2, "02020202", "IS", "foo", QueryTagLevel.Series, ExtendedQueryTagStatus.Adding, QueryStatus.Enabled, 0), new ExtendedQueryTagStoreEntry(4, "04040404", "SH", null, QueryTagLevel.Study, ExtendedQueryTagStatus.Adding, QueryStatus.Enabled, 0) }; // Arrange the input IDurableOrchestrationContext context = CreateContext(); context .GetInput <ReindexInput>() .Returns(expectedInput); context .CallActivityWithRetryAsync <IReadOnlyList <ExtendedQueryTagStoreEntry> >( nameof(ReindexDurableFunction.AssignReindexingOperationAsync), _options.ActivityRetryOptions, expectedInput.QueryTagKeys) .Returns(expectedTags); context .CallActivityWithRetryAsync <IReadOnlyList <WatermarkRange> >( nameof(ReindexDurableFunction.GetInstanceBatchesV2Async), _options.ActivityRetryOptions, Arg.Is(GetPredicate(null))) .Returns(expectedBatches); context .CallActivityWithRetryAsync <IReadOnlyList <int> >( nameof(ReindexDurableFunction.CompleteReindexingAsync), _options.ActivityRetryOptions, Arg.Is <IReadOnlyList <int> >(x => x.SequenceEqual(expectedTags.Select(x => x.Key)))) .Returns(expectedTags.Select(x => x.Key).ToList()); // Invoke the orchestration await _reindexDurableFunction.ReindexInstancesAsync(context, NullLogger.Instance); // Assert behavior context .Received(1) .GetInput <ReindexInput>(); await context .Received(1) .CallActivityWithRetryAsync <IReadOnlyList <ExtendedQueryTagStoreEntry> >( nameof(ReindexDurableFunction.AssignReindexingOperationAsync), _options.ActivityRetryOptions, expectedInput.QueryTagKeys); await context .DidNotReceive() .CallActivityWithRetryAsync <IReadOnlyList <ExtendedQueryTagStoreEntry> >( nameof(ReindexDurableFunction.GetQueryTagsAsync), _options.ActivityRetryOptions, Arg.Any <object>()); await context .Received(1) .CallActivityWithRetryAsync <IReadOnlyList <WatermarkRange> >( nameof(ReindexDurableFunction.GetInstanceBatchesV2Async), _options.ActivityRetryOptions, Arg.Is(GetPredicate(null))); await context .DidNotReceive() .CallActivityWithRetryAsync( nameof(ReindexDurableFunction.ReindexBatchV2Async), _options.ActivityRetryOptions, Arg.Any <object>()); await context .Received(1) .CallActivityWithRetryAsync <IReadOnlyList <int> >( nameof(ReindexDurableFunction.CompleteReindexingAsync), _options.ActivityRetryOptions, Arg.Is <IReadOnlyList <int> >(x => x.SequenceEqual(expectedTags.Select(x => x.Key)))); context .DidNotReceiveWithAnyArgs() .ContinueAsNew(default, default);