// perform a query public override async Task QueryAsync(PartitionQueryEvent queryEvent, EffectTracker effectTracker) { try { var instanceQuery = queryEvent.InstanceQuery; #if FASTER_SUPPORTS_PSF IAsyncEnumerable <OrchestrationState> queryPSFsAsync(ClientSession <Key, Value, EffectTracker, TrackedObject, PartitionReadEvent, Functions> session) { // Issue the PSF query. Note that pending operations will be completed before this returns. var querySpec = new List <(IPSF, IEnumerable <PSFKey>)>(); if (instanceQuery.HasRuntimeStatus) { querySpec.Add((this.RuntimeStatusPsf, instanceQuery.RuntimeStatus.Select(s => new PSFKey(s)))); } if (instanceQuery.CreatedTimeFrom.HasValue || instanceQuery.CreatedTimeTo.HasValue) { IEnumerable <PSFKey> enumerateDateBinKeys() { var to = instanceQuery.CreatedTimeTo ?? DateTime.UtcNow; var from = instanceQuery.CreatedTimeFrom ?? to.AddDays(-7); // TODO Some default so we don't have to iterate from the first possible date for (var dt = from; dt <= to; dt += PSFKey.DateBinInterval) { yield return(new PSFKey(dt)); } } querySpec.Add((this.CreatedTimePsf, enumerateDateBinKeys())); } if (!string.IsNullOrWhiteSpace(instanceQuery.InstanceIdPrefix)) { querySpec.Add((this.InstanceIdPrefixPsf, new[] { new PSFKey(instanceQuery.InstanceIdPrefix) })); } var querySettings = new PSFQuerySettings { // This is a match-all-PSFs enumeration so do not continue after any PSF has hit EOS OnStreamEnded = (unusedPsf, unusedIndex) => false }; OrchestrationState getOrchestrationState(ref Value v) { if (v.Val is byte[] serialized) { var result = ((InstanceState)Serializer.DeserializeTrackedObject(serialized))?.OrchestrationState; if (result != null && !instanceQuery.FetchInput) { result.Input = null; } return(result); } else { var state = ((InstanceState)((TrackedObject)v))?.OrchestrationState; var result = state?.ClearFieldsImmutably(instanceQuery.FetchInput, true); return(result); } } return(session.QueryPSFAsync(querySpec, matches => matches.All(b => b), querySettings) .Select(providerData => getOrchestrationState(ref providerData.GetValue())) .Where(orchestrationState => orchestrationState != null)); } #else IAsyncEnumerable <OrchestrationState> queryPSFsAsync(ClientSession <Key, Value, EffectTracker, TrackedObject, object, IFunctions <Key, Value, EffectTracker, TrackedObject, object> > session) => this.ScanOrchestrationStates(effectTracker, queryEvent); #endif // create an individual session for this query so the main session can be used // while the query is progressing. using (var session = this.CreateASession()) { var orchestrationStates = (this.partition.Settings.UsePSFQueries && instanceQuery.IsSet) ? queryPSFsAsync(session) : this.ScanOrchestrationStates(effectTracker, queryEvent); await effectTracker.ProcessQueryResultAsync(queryEvent, orchestrationStates); } } catch (Exception exception) when(this.terminationToken.IsCancellationRequested && !Utils.IsFatal(exception)) { throw new OperationCanceledException("Partition was terminated.", exception, this.terminationToken); } }