001/*- 002 * #%L 003 * HAPI FHIR JPA - Search Parameters 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.partition; 021 022import ca.uhn.fhir.interceptor.model.ReadPartitionIdRequestDetails; 023import ca.uhn.fhir.interceptor.model.RequestPartitionId; 024import ca.uhn.fhir.jpa.searchparam.SearchParameterMap; 025import ca.uhn.fhir.rest.api.server.RequestDetails; 026import jakarta.annotation.Nonnull; 027import jakarta.annotation.Nullable; 028import org.hl7.fhir.instance.model.api.IBaseResource; 029import org.hl7.fhir.instance.model.api.IIdType; 030 031import java.util.Set; 032 033public interface IRequestPartitionHelperSvc { 034 035 @Nonnull 036 RequestPartitionId determineReadPartitionForRequest( 037 @Nullable RequestDetails theRequest, @Nonnull ReadPartitionIdRequestDetails theDetails); 038 039 /** 040 * Determine partition to use when performing a server operation such as $bulk-import, $bulk-export, $reindex etc. 041 * @param theRequest the request details from the context of the call 042 * @param theOperationName the explicit name of the operation 043 * @return the partition id which should be used for the operation 044 */ 045 @Nonnull 046 default RequestPartitionId determineReadPartitionForRequestForServerOperation( 047 @Nullable RequestDetails theRequest, @Nonnull String theOperationName) { 048 ReadPartitionIdRequestDetails details = ReadPartitionIdRequestDetails.forServerOperation(theOperationName); 049 return determineReadPartitionForRequest(theRequest, details); 050 } 051 052 /** 053 * Determine partition to use when performing database reads based on a resource instance. 054 * @param theRequest the request details from the context of the call 055 * @param theId the id of the resource instance 056 * @return the partition id which should be used for the database read 057 */ 058 @Nonnull 059 default RequestPartitionId determineReadPartitionForRequestForRead( 060 @Nullable RequestDetails theRequest, @Nonnull IIdType theId) { 061 ReadPartitionIdRequestDetails details = 062 ReadPartitionIdRequestDetails.forRead(theId.getResourceType(), theId, theId.hasVersionIdPart()); 063 return determineReadPartitionForRequest(theRequest, details); 064 } 065 066 /** 067 * Determine partition to use when performing database reads against a certain resource type based on a resource instance. 068 * @param theRequest the request details from the context of the call 069 * @param theResourceType the resource type 070 * @param theId the id of the resource instance 071 * @return the partition id which should be used for the database read 072 */ 073 @Nonnull 074 default RequestPartitionId determineReadPartitionForRequestForRead( 075 @Nullable RequestDetails theRequest, @Nonnull String theResourceType, @Nonnull IIdType theId) { 076 ReadPartitionIdRequestDetails details = 077 ReadPartitionIdRequestDetails.forRead(theResourceType, theId, theId.hasVersionIdPart()); 078 return determineReadPartitionForRequest(theRequest, details); 079 } 080 081 /** 082 * Determine partition to use when performing a database search against a certain resource type. 083 * @param theRequest the request details from the context of the call 084 * @param theResourceType the resource type 085 * @return the partition id which should be used for the database search 086 */ 087 @Nonnull 088 default RequestPartitionId determineReadPartitionForRequestForSearchType( 089 @Nullable RequestDetails theRequest, @Nonnull String theResourceType) { 090 ReadPartitionIdRequestDetails details = 091 ReadPartitionIdRequestDetails.forSearchType(theResourceType, SearchParameterMap.newSynchronous(), null); 092 return determineReadPartitionForRequest(theRequest, details); 093 } 094 095 /** 096 * Determine partition to use when performing a database search based on a resource type and other search parameters. 097 * @param theRequest the request details from the context of the call 098 * @param theResourceType the resource type 099 * @param theParams the search parameters 100 * @return the partition id which should be used for the database search 101 */ 102 @Nonnull 103 default RequestPartitionId determineReadPartitionForRequestForSearchType( 104 @Nullable RequestDetails theRequest, 105 @Nonnull String theResourceType, 106 @Nonnull SearchParameterMap theParams) { 107 ReadPartitionIdRequestDetails details = 108 ReadPartitionIdRequestDetails.forSearchType(theResourceType, theParams, null); 109 return determineReadPartitionForRequest(theRequest, details); 110 } 111 112 /** 113 * Determine partition to use when performing a database search based on a resource type, search parameters and a conditional target resource (if available). 114 * @param theRequest the request details from the context of the call 115 * @param theResourceType the resource type 116 * @param theParams the search parameters 117 * @param theConditionalOperationTargetOrNull the conditional target resource 118 * @return the partition id which should be used for the database search 119 */ 120 @Nonnull 121 default RequestPartitionId determineReadPartitionForRequestForSearchType( 122 RequestDetails theRequest, 123 String theResourceType, 124 SearchParameterMap theParams, 125 IBaseResource theConditionalOperationTargetOrNull) { 126 SearchParameterMap searchParameterMap = theParams != null ? theParams : SearchParameterMap.newSynchronous(); 127 ReadPartitionIdRequestDetails details = ReadPartitionIdRequestDetails.forSearchType( 128 theResourceType, searchParameterMap, theConditionalOperationTargetOrNull); 129 return determineReadPartitionForRequest(theRequest, details); 130 } 131 132 RequestPartitionId determineGenericPartitionForRequest(RequestDetails theRequestDetails); 133 134 /** 135 * Determine partition to use when performing the history operation based on a resource type and resource instance. 136 * @param theRequest the request details from the context of the call 137 * @param theResourceType the resource type 138 * @param theIdType the id of the resource instance 139 * @return the partition id which should be used for the history operation 140 */ 141 @Nonnull 142 default RequestPartitionId determineReadPartitionForRequestForHistory( 143 @Nullable RequestDetails theRequest, String theResourceType, IIdType theIdType) { 144 ReadPartitionIdRequestDetails details = ReadPartitionIdRequestDetails.forHistory(theResourceType, theIdType); 145 return determineReadPartitionForRequest(theRequest, details); 146 } 147 148 default void validateHasPartitionPermissions( 149 @Nonnull RequestDetails theRequest, String theResourceType, RequestPartitionId theRequestPartitionId) {} 150 151 @Nonnull 152 RequestPartitionId determineCreatePartitionForRequest( 153 @Nullable RequestDetails theRequest, @Nonnull IBaseResource theResource, @Nonnull String theResourceType); 154 155 @Nonnull 156 Set<Integer> toReadPartitions(@Nonnull RequestPartitionId theRequestPartitionId); 157 158 boolean isResourcePartitionable(String theResourceType); 159 160 /** 161 * <b>No interceptors should be invoked by this method. It should ONLY be used when partition ids are 162 * known, but partition names are not.</b> 163 * <br/><br/> 164 * Ensures the list of partition ids inside the given {@link RequestPartitionId} correctly map to the 165 * list of partition names. If the list of partition names is empty, this method will map the correct 166 * partition names and return a normalized {@link RequestPartitionId}. 167 * <br/><br/> 168 * @param theRequestPartitionId - An unvalidated and unnormalized {@link RequestPartitionId}. 169 * @return - A {@link RequestPartitionId} with a normalized list of partition ids and partition names. 170 */ 171 RequestPartitionId validateAndNormalizePartitionIds(RequestPartitionId theRequestPartitionId); 172 173 /** 174 * <b>No interceptors should be invoked by this method. It should ONLY be used when partition names are 175 * known, but partition ids are not.</b> 176 * <br/><br/> 177 * Ensures the list of partition names inside the given {@link RequestPartitionId} correctly map to the 178 * list of partition ids. If the list of partition ids is empty, this method will map the correct 179 * partition ids and return a normalized {@link RequestPartitionId}. 180 * <br/><br/> 181 * @param theRequestPartitionId - An unvalidated and unnormalized {@link RequestPartitionId}. 182 * @return - A {@link RequestPartitionId} with a normalized list of partition ids and partition names. 183 */ 184 RequestPartitionId validateAndNormalizePartitionNames(RequestPartitionId theRequestPartitionId); 185}