/// <summary> /// Provide a count of patients in the specified query. /// Converts the query into a local validation context. /// Validates the resulting context to ensure sensible construction. /// Obtains the cohort of unique patient IDs. /// Caches those patient IDs. /// </summary> /// <returns><see cref="CohortCount">The count of patients in the cohort.</see></returns> /// <param name="queryDTO">Abstract query representation.</param> /// <param name="token">Cancellation token.</param> /// <exception cref="OperationCanceledException"/> /// <exception cref="InvalidOperationException"/> /// <exception cref="ArgumentNullException"/> /// <exception cref="LeafDbException"/> public async Task <Result> Count(IPatientCountQueryDTO queryDTO, CancellationToken token) { Ensure.NotNull(queryDTO, nameof(queryDTO)); var ctx = await converter.GetPanelsAsync(queryDTO, token); if (!ctx.PreflightPassed) { return(new Result { ValidationContext = ctx }); } var query = validator.Validate(ctx); var cohort = await counter.GetPatientCohortAsync(query, token); token.ThrowIfCancellationRequested(); log.LogInformation("Caching unsaved cohort."); var qid = await cohortCache.CreateUnsavedQueryAsync(cohort, user); log.LogInformation("Cached unsaved cohort. QueryId:{QueryId}", qid); return(new Result { ValidationContext = ctx, Count = new PatientCount { QueryId = qid, Value = cohort.Count, SqlStatements = cohort.SqlStatements } }); }
/// <summary> /// Provide an zero count of patients in the specified query. /// Converts the query into a local validation context. /// Validates the resulting context to ensure sensible construction. /// Creates a queryId and empty cohort. /// </summary> /// <returns><see cref="Result">The count of patients in the cohort.</see></returns> /// <param name="queryDTO">Abstract query representation.</param> /// <param name="token">Cancellation token.</param> /// <exception cref="OperationCanceledException"/> /// <exception cref="LeafCompilerException"/> /// <exception cref="ArgumentNullException"/> /// <exception cref="LeafRPCException"/> /// <exception cref="System.Data.Common.DbException"/> async Task <Result> GatewayCount(IPatientCountQueryDTO queryDTO, CancellationToken token) { log.LogInformation("GatewayCount starting. DTO:{@DTO}", queryDTO); Ensure.NotNull(queryDTO, nameof(queryDTO)); var ctx = await converter.GetPanelsAsync(queryDTO, token); log.LogInformation("GatewayCount panel validation context. Context:{@Context}", ctx); if (!ctx.PreflightPassed) { return(new Result { ValidationContext = ctx }); } validator.Validate(ctx); token.ThrowIfCancellationRequested(); var cohort = new PatientCohort(); var qid = await CacheCohort(cohort); return(new Result { ValidationContext = ctx, Count = new PatientCount { QueryId = qid, Value = cohort.Count, SqlStatements = cohort.SqlStatements } }); }
/// <summary> /// Converts stub AST query definition into local, fully hydrated AST. /// The returned AST is unvalidated, and has a QueryId property set if the incoming query has one. /// </summary> /// <returns>The panels async.</returns> /// <param name="query">Stub AST query definition.</param> /// <param name="token">Cancellation token.</param> public async Task <PanelValidationContext> GetPanelsAsync(IPatientCountQueryDTO query, CancellationToken token) { token.ThrowIfCancellationRequested(); var validationContext = await GetPanelsAsync(query); validationContext.SetQueryId(query.QueryId); return(validationContext); }
/// <summary> /// Provide a count of patients in the specified query. /// </summary> /// <returns><see cref="Result">The count of patients in the cohort.</see></returns> /// <param name="queryDTO">Abstract query representation.</param> /// <param name="token">Cancellation token.</param> /// <exception cref="OperationCanceledException"/> /// <exception cref="LeafCompilerException"/> /// <exception cref="ArgumentNullException"/> /// <exception cref="LeafRPCException"/> /// <exception cref="System.Data.Common.DbException"/> public async Task <Result> Count(IPatientCountQueryDTO queryDTO, CancellationToken token) { switch (runtime) { case RuntimeMode.Gateway: return(await GatewayCount(queryDTO, token)); default: return(await FullCount(queryDTO, token)); } }
/// <summary> /// Provide a count of patients in the specified query. /// Converts the query into a local validation context. /// Validates the resulting context to ensure sensible construction. /// Obtains the cohort of unique patient IDs. /// Caches those patient IDs. /// </summary> /// <returns><see cref="Result">The count of patients in the cohort.</see></returns> /// <param name="queryDTO">Abstract query representation.</param> /// <param name="token">Cancellation token.</param> /// <exception cref="OperationCanceledException"/> /// <exception cref="LeafCompilerException"/> /// <exception cref="ArgumentNullException"/> /// <exception cref="LeafRPCException"/> /// <exception cref="System.Data.Common.DbException"/> async Task <Result> FullCount(IPatientCountQueryDTO queryDTO, CancellationToken token) { log.LogInformation("FullCount starting. DTO:{@DTO}", queryDTO); Ensure.NotNull(queryDTO, nameof(queryDTO)); var ctx = await converter.GetPanelsAsync(queryDTO, token); log.LogInformation("FullCount panel validation context. Context:{@Context}", ctx); if (!ctx.PreflightPassed) { return(new Result { ValidationContext = ctx }); } var query = validator.Validate(ctx); log.LogInformation("FullCount cohort started."); var cohort = await counter.GetPatientCohortAsync(query, token); log.LogInformation("FullCount cohort retrieved. Cohort:{@Cohort}", new { cohort.Count, cohort.SqlStatements }); token.ThrowIfCancellationRequested(); var qid = await CacheCohort(cohort); var result = new Result { ValidationContext = ctx, Count = new PatientCount { QueryId = qid, Value = cohort.Count, SqlStatements = cohort.SqlStatements } }; if (deidentOpts.ObfuscateCohort) { var count = result.Count; obfuscator.Obfuscate(ref count, result.ValidationContext, deidentOpts); log.LogInformation("FullCount results obfuscated. Obfuscated:{@Result}", result); } return(result); }