001/*- 002 * #%L 003 * HAPI FHIR JPA Server 004 * %% 005 * Copyright (C) 2014 - 2024 Smile CDR, Inc. 006 * %% 007 * Licensed under the Apache License, Version 2.0 (the "License"); 008 * you may not use this file except in compliance with the License. 009 * You may obtain a copy of the License at 010 * 011 * http://www.apache.org/licenses/LICENSE-2.0 012 * 013 * Unless required by applicable law or agreed to in writing, software 014 * distributed under the License is distributed on an "AS IS" BASIS, 015 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 016 * See the License for the specific language governing permissions and 017 * limitations under the License. 018 * #L% 019 */ 020package ca.uhn.fhir.jpa.search.builder.tasks; 021 022import ca.uhn.fhir.context.FhirContext; 023import ca.uhn.fhir.interceptor.api.IInterceptorBroadcaster; 024import ca.uhn.fhir.interceptor.model.RequestPartitionId; 025import ca.uhn.fhir.jpa.api.config.JpaStorageSettings; 026import ca.uhn.fhir.jpa.dao.SearchBuilderFactory; 027import ca.uhn.fhir.jpa.dao.tx.HapiTransactionService; 028import ca.uhn.fhir.jpa.model.dao.JpaPid; 029import ca.uhn.fhir.jpa.model.search.SearchStatusEnum; 030import ca.uhn.fhir.jpa.search.ExceptionService; 031import ca.uhn.fhir.jpa.search.cache.ISearchCacheSvc; 032import ca.uhn.fhir.jpa.search.cache.ISearchResultCacheSvc; 033import ca.uhn.fhir.rest.api.server.RequestDetails; 034import ca.uhn.fhir.rest.server.IPagingProvider; 035import ca.uhn.fhir.rest.server.exceptions.BaseServerResponseException; 036 037import java.util.List; 038 039public class SearchContinuationTask extends SearchTask { 040 041 private static final org.slf4j.Logger ourLog = org.slf4j.LoggerFactory.getLogger(SearchContinuationTask.class); 042 043 private final ExceptionService myExceptionSvc; 044 private final RequestDetails myRequestDetails; 045 046 public SearchContinuationTask( 047 SearchTaskParameters theCreationParams, 048 HapiTransactionService theTxService, 049 FhirContext theContext, 050 IInterceptorBroadcaster theInterceptorBroadcaster, 051 SearchBuilderFactory theSearchBuilderFactory, 052 ISearchResultCacheSvc theSearchResultCacheSvc, 053 JpaStorageSettings theStorageSettings, 054 ISearchCacheSvc theSearchCacheSvc, 055 IPagingProvider thePagingProvider, 056 ExceptionService theExceptionSvc) { 057 super( 058 theCreationParams, 059 theTxService, 060 theContext, 061 theInterceptorBroadcaster, 062 theSearchBuilderFactory, 063 theSearchResultCacheSvc, 064 theStorageSettings, 065 theSearchCacheSvc, 066 thePagingProvider); 067 068 myRequestDetails = theCreationParams.Request; 069 myExceptionSvc = theExceptionSvc; 070 } 071 072 @Override 073 public Void call() { 074 try { 075 RequestPartitionId requestPartitionId = getRequestPartitionId(); 076 myTxService 077 .withRequest(myRequestDetails) 078 .withRequestPartitionId(requestPartitionId) 079 .execute(() -> { 080 List<JpaPid> previouslyAddedResourcePids = mySearchResultCacheSvc.fetchAllResultPids( 081 getSearch(), myRequestDetails, requestPartitionId); 082 if (previouslyAddedResourcePids == null) { 083 throw myExceptionSvc.newUnknownSearchException( 084 getSearch().getUuid()); 085 } 086 087 ourLog.trace( 088 "Have {} previously added IDs in search: {}", 089 previouslyAddedResourcePids.size(), 090 getSearch().getUuid()); 091 setPreviouslyAddedResourcePids(previouslyAddedResourcePids); 092 }); 093 094 } catch (Throwable e) { 095 ourLog.error("Failure processing search", e); 096 getSearch().setFailureMessage(e.getMessage()); 097 getSearch().setStatus(SearchStatusEnum.FAILED); 098 if (e instanceof BaseServerResponseException) { 099 getSearch().setFailureCode(((BaseServerResponseException) e).getStatusCode()); 100 } 101 102 saveSearch(); 103 return null; 104 } 105 106 return super.call(); 107 } 108}