
001/*- 002 * #%L 003 * HAPI FHIR JPA Server 004 * %% 005 * Copyright (C) 2014 - 2025 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.search.ExceptionService; 030import ca.uhn.fhir.jpa.search.cache.ISearchCacheSvc; 031import ca.uhn.fhir.jpa.search.cache.ISearchResultCacheSvc; 032import ca.uhn.fhir.rest.api.server.RequestDetails; 033import ca.uhn.fhir.rest.server.IPagingProvider; 034 035import java.util.List; 036 037public class SearchContinuationTask extends SearchTask { 038 039 private static final org.slf4j.Logger ourLog = org.slf4j.LoggerFactory.getLogger(SearchContinuationTask.class); 040 041 private final ExceptionService myExceptionSvc; 042 private final RequestDetails myRequestDetails; 043 044 public SearchContinuationTask( 045 SearchTaskParameters theCreationParams, 046 HapiTransactionService theTxService, 047 FhirContext theContext, 048 IInterceptorBroadcaster theInterceptorBroadcaster, 049 SearchBuilderFactory theSearchBuilderFactory, 050 ISearchResultCacheSvc theSearchResultCacheSvc, 051 JpaStorageSettings theStorageSettings, 052 ISearchCacheSvc theSearchCacheSvc, 053 IPagingProvider thePagingProvider, 054 ExceptionService theExceptionSvc) { 055 super( 056 theCreationParams, 057 theTxService, 058 theContext, 059 theInterceptorBroadcaster, 060 theSearchBuilderFactory, 061 theSearchResultCacheSvc, 062 theStorageSettings, 063 theSearchCacheSvc, 064 thePagingProvider); 065 066 myRequestDetails = theCreationParams.Request; 067 myExceptionSvc = theExceptionSvc; 068 } 069 070 @Override 071 public Void call() { 072 try { 073 RequestPartitionId requestPartitionId = getRequestPartitionId(); 074 myTxService 075 .withRequest(myRequestDetails) 076 .withRequestPartitionId(requestPartitionId) 077 .execute(() -> { 078 List<JpaPid> previouslyAddedResourcePids = mySearchResultCacheSvc.fetchAllResultPids( 079 getSearch(), myRequestDetails, requestPartitionId); 080 if (previouslyAddedResourcePids == null) { 081 throw myExceptionSvc.newUnknownSearchException( 082 getSearch().getUuid()); 083 } 084 085 ourLog.trace( 086 "Have {} previously added IDs in search: {}", 087 previouslyAddedResourcePids.size(), 088 getSearch().getUuid()); 089 setPreviouslyAddedResourcePids(previouslyAddedResourcePids); 090 }); 091 092 } catch (Throwable e) { 093 ourLog.error("Failure processing search", e); 094 095 markSearchAsFailedWithExceptionDetails(e); 096 097 saveSearch(); 098 return null; 099 } 100 101 return super.call(); 102 } 103}