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}