public async Task <CreateReindexResponse> Handle(CreateReindexRequest request, CancellationToken cancellationToken) { EnsureArg.IsNotNull(request, nameof(request)); if (await _authorizationService.CheckAccess(DataActions.Reindex, cancellationToken) != DataActions.Reindex) { throw new UnauthorizedFhirActionException(); } (var activeReindexJobs, var reindexJobId) = await _fhirOperationDataStore.CheckActiveReindexJobsAsync(cancellationToken); if (activeReindexJobs) { throw new JobConflictException(string.Format(Resources.OnlyOneResourceJobAllowed, reindexJobId)); } // We need to pull in latest search parameter updates from the data store before creating a reindex job. // There could be a potential delay of <see cref="ReindexJobConfiguration.JobPollingFrequency"/> before // search parameter updates on one instance propagates to other instances. If we store the reindex // job with the old hash value in _searchParameterDefinitionManager.SearchParameterHashMap, then we will // not detect the resources that need to be reindexed. await _searchParameterOperations.GetAndApplySearchParameterUpdates(cancellationToken); var jobRecord = new ReindexJobRecord( _searchParameterDefinitionManager.SearchParameterHashMap, request.MaximumConcurrency ?? _reindexJobConfiguration.DefaultMaximumThreadsPerReindexJob, request.MaximumResourcesPerQuery ?? _reindexJobConfiguration.MaximumNumberOfResourcesPerQuery, request.QueryDelayIntervalInMilliseconds ?? _reindexJobConfiguration.QueryDelayIntervalInMilliseconds, request.TargetDataStoreUsagePercentage); var outcome = await _fhirOperationDataStore.CreateReindexJobAsync(jobRecord, cancellationToken); return(new CreateReindexResponse(outcome)); }
public async Task <ReindexSingleResourceResponse> Handle(ReindexSingleResourceRequest request, CancellationToken cancellationToken) { EnsureArg.IsNotNull(request, nameof(request)); if (await _authorizationService.CheckAccess(DataActions.Reindex, cancellationToken) != DataActions.Reindex) { throw new UnauthorizedFhirActionException(); } var key = new ResourceKey(request.ResourceType, request.ResourceId); ResourceWrapper storedResource = await _fhirDataStore.GetAsync(key, cancellationToken); if (storedResource == null) { throw new ResourceNotFoundException(string.Format(Core.Resources.ResourceNotFoundById, request.ResourceType, request.ResourceId)); } await _searchParameterOperations.GetAndApplySearchParameterUpdates(cancellationToken); // We need to extract the "new" search indices since the assumption is that // a new search parameter has been added to the fhir server. ResourceElement resourceElement = _resourceDeserializer.Deserialize(storedResource); IReadOnlyCollection <SearchIndexEntry> newIndices = _searchIndexer.Extract(resourceElement); // If it's a post request we need to go update the resource in the database. if (request.HttpMethod == HttpPostName) { await ProcessPostReindexSingleResourceRequest(storedResource, newIndices); } // Create a new parameter resource and include the new search indices and the corresponding values. var parametersResource = new Parameters { Id = Guid.NewGuid().ToString(), VersionId = "1", Parameter = new List <Parameters.ParameterComponent>(), }; foreach (SearchIndexEntry searchIndex in newIndices) { parametersResource.Parameter.Add(new Parameters.ParameterComponent() { Name = searchIndex.SearchParameter.Code.ToString(), Value = new FhirString(searchIndex.Value.ToString()) }); } return(new ReindexSingleResourceResponse(parametersResource.ToResourceElement())); }
public async Task ExecuteAsync(CancellationToken cancellationToken) { var runningTasks = new List <Task>(); while (!cancellationToken.IsCancellationRequested) { if (_searchParametersInitialized) { // Check for any changes to Search Parameters try { await _searchParameterOperations.GetAndApplySearchParameterUpdates(cancellationToken); } catch (OperationCanceledException) when(cancellationToken.IsCancellationRequested) { _logger.LogDebug("Reindex job worker canceled."); } catch (Exception ex) { // The job failed. _logger.LogError(ex, "Error querying latest SearchParameterStatus updates"); } // Check for any new Reindex Jobs try { // Remove all completed tasks. runningTasks.RemoveAll(task => task.IsCompleted); // Get list of available jobs. if (runningTasks.Count < _reindexJobConfiguration.MaximumNumberOfConcurrentJobsAllowed) { using (IScoped <IFhirOperationDataStore> store = _fhirOperationDataStoreFactory.Invoke()) { _logger.LogTrace("Querying datastore for reindex jobs."); IReadOnlyCollection <ReindexJobWrapper> jobs = await store.Value.AcquireReindexJobsAsync( _reindexJobConfiguration.MaximumNumberOfConcurrentJobsAllowed, _reindexJobConfiguration.JobHeartbeatTimeoutThreshold, cancellationToken); foreach (ReindexJobWrapper job in jobs) { _logger.LogTrace("Picked up reindex job: {jobId}.", job.JobRecord.Id); runningTasks.Add(_reindexJobTaskFactory().ExecuteAsync(job.JobRecord, job.ETag, cancellationToken)); } } } } catch (OperationCanceledException) when(cancellationToken.IsCancellationRequested) { // End the execution of the task } catch (Exception ex) { // The job failed. _logger.LogError(ex, "Error polling Reindex jobs."); } } try { await Task.Delay(_reindexJobConfiguration.JobPollingFrequency, cancellationToken); } catch (OperationCanceledException) when(cancellationToken.IsCancellationRequested) { // End the execution of the task } } }