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}