001package ca.uhn.fhir.jpa.search.cache;
002
003/*-
004 * #%L
005 * HAPI FHIR JPA Server
006 * %%
007 * Copyright (C) 2014 - 2021 Smile CDR, Inc.
008 * %%
009 * Licensed under the Apache License, Version 2.0 (the "License");
010 * you may not use this file except in compliance with the License.
011 * You may obtain a copy of the License at
012 *
013 *      http://www.apache.org/licenses/LICENSE-2.0
014 *
015 * Unless required by applicable law or agreed to in writing, software
016 * distributed under the License is distributed on an "AS IS" BASIS,
017 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
018 * See the License for the specific language governing permissions and
019 * limitations under the License.
020 * #L%
021 */
022
023import ca.uhn.fhir.interceptor.model.RequestPartitionId;
024import ca.uhn.fhir.jpa.entity.Search;
025
026import java.time.Instant;
027import java.util.Optional;
028
029public interface ISearchCacheSvc {
030
031        /**
032         * Places a new search of some sort in the cache, or updates an existing search. The search passed in is guaranteed to have
033         * a {@link Search#getUuid() UUID} so that is a good candidate for consistent identification.
034         *
035         * @param theSearch The search to store
036         * @return Returns a copy of the search as it was saved. Callers should use the returned Search object for any further processing.
037         */
038        Search save(Search theSearch);
039
040        /**
041         * Fetch a search using its UUID. The search should be fully loaded when it is returned (i.e. includes are fetched, so that access to its
042         * fields will not cause database errors if the current tranaction scope ends.
043         *
044         * @param theUuid The search UUID
045         * @return The search if it exists
046         */
047        Optional<Search> fetchByUuid(String theUuid);
048
049        /**
050         * TODO: this is perhaps an inappropriate responsibility for this service
051         *
052         * <p>
053         * This method marks a search as in progress, but should only allow exactly one call to do so across the cluster. This
054         * is done so that if two client threads request the next page at the exact same time (which is unlikely but not
055         * impossible) only one will actually proceed to load the next results and the other will just wait for them
056         * to arrive.
057         *
058         * @param theSearch The search to mark
059         * @return This method should return an empty optional if the search was not marked (meaning that another thread
060         * succeeded in marking it). If the search doesn't exist or some other error occurred, an exception will be thrown
061         * instead of {@link Optional#empty()}
062         */
063        Optional<Search> tryToMarkSearchAsInProgress(Search theSearch);
064
065        /**
066         * Look for any existing searches matching the given resource type and query string.
067         * <p>
068         * This method is allowed to perform a "best effort" return, so it can return searches that don't match the query string exactly, or
069         * which have a created timestamp before <code>theCreatedAfter</code> date. The caller is responsible for removing
070         * any inappropriate Searches and picking the most relevant one.
071         * </p>
072         *
073         * @param theResourceType The resource type of the search. Results MUST match this type
074         * @param theQueryString  The query string. Results SHOULD match this type
075         * @param theCreatedAfter Results SHOULD not include any searches created before this cutoff timestamp
076         * @param theRequestPartitionId Search should examine only the requested partitions. Cache MUST not return results matching the given partition IDs
077         * @return A collection of candidate searches
078         */
079        Optional<Search> findCandidatesForReuse(String theResourceType, String theQueryString, Instant theCreatedAfter, RequestPartitionId theRequestPartitionId);
080
081        /**
082         * This method will be called periodically to delete stale searches. Implementations are not required to do anything
083         * if they have some other mechanism for expiring stale results other than manually looking for them
084         * and deleting them.
085         */
086        void pollForStaleSearchesAndDeleteThem();
087}