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.cache; 021 022import ca.uhn.fhir.interceptor.model.RequestPartitionId; 023import ca.uhn.fhir.jpa.entity.Search; 024 025import java.time.Instant; 026import java.util.Optional; 027 028public interface ISearchCacheSvc { 029 030 /** 031 * Places a new search of some sort in the cache, or updates an existing search. The search passed in is guaranteed to have 032 * a {@link Search#getUuid() UUID} so that is a good candidate for consistent identification. 033 * 034 * @param theSearch The search to store 035 * @return Returns a copy of the search as it was saved. Callers should use the returned Search object for any further processing. 036 */ 037 Search save(Search theSearch, RequestPartitionId theRequestPartitionId); 038 039 /** 040 * 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 041 * fields will not cause database errors if the current tranaction scope ends. 042 * 043 * @param theUuid The search UUID 044 * @return The search if it exists 045 */ 046 Optional<Search> fetchByUuid(String theUuid, RequestPartitionId theRequestPartitionId); 047 048 /** 049 * TODO: this is perhaps an inappropriate responsibility for this service 050 * 051 * <p> 052 * This method marks a search as in progress, but should only allow exactly one call to do so across the cluster. This 053 * is done so that if two client threads request the next page at the exact same time (which is unlikely but not 054 * impossible) only one will actually proceed to load the next results and the other will just wait for them 055 * to arrive. 056 * 057 * @param theSearch The search to mark 058 * @return This method should return an empty optional if the search was not marked (meaning that another thread 059 * succeeded in marking it). If the search doesn't exist or some other error occurred, an exception will be thrown 060 * instead of {@link Optional#empty()} 061 */ 062 Optional<Search> tryToMarkSearchAsInProgress(Search theSearch, RequestPartitionId theRequestPartitionId); 063 064 /** 065 * Look for any existing searches matching the given resource type and query string. 066 * <p> 067 * This method is allowed to perform a "best effort" return, so it can return searches that don't match the query string exactly, or 068 * which have a created timestamp before <code>theCreatedAfter</code> date. The caller is responsible for removing 069 * any inappropriate Searches and picking the most relevant one. 070 * </p> 071 * 072 * @param theResourceType The resource type of the search. Results MUST match this type 073 * @param theQueryString The query string. Results SHOULD match this type 074 * @param theCreatedAfter Results SHOULD not include any searches created before this cutoff timestamp 075 * @param theRequestPartitionId Search should examine only the requested partitions. Cache MUST not return results matching the given partition IDs 076 * @return A collection of candidate searches 077 */ 078 Optional<Search> findCandidatesForReuse( 079 String theResourceType, 080 String theQueryString, 081 Instant theCreatedAfter, 082 RequestPartitionId theRequestPartitionId); 083 084 /** 085 * This method will be called periodically to delete stale searches. Implementations are not required to do anything 086 * if they have some other mechanism for expiring stale results other than manually looking for them 087 * and deleting them. 088 */ 089 void pollForStaleSearchesAndDeleteThem(RequestPartitionId theRequestPartitionId, Instant theDeadline); 090}