001/*- 002 * #%L 003 * HAPI FHIR Storage api 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.dao.tx; 021 022import ca.uhn.fhir.interceptor.model.RequestPartitionId; 023import ca.uhn.fhir.rest.api.server.RequestDetails; 024import ca.uhn.fhir.rest.api.server.storage.TransactionDetails; 025import ca.uhn.fhir.util.ICallable; 026import jakarta.annotation.Nonnull; 027import jakarta.annotation.Nullable; 028import org.springframework.transaction.annotation.Isolation; 029import org.springframework.transaction.annotation.Propagation; 030import org.springframework.transaction.support.TransactionCallback; 031import org.springframework.transaction.support.TransactionOperations; 032 033import java.util.List; 034import java.util.concurrent.Callable; 035import java.util.stream.Stream; 036 037/** 038 * This class is used to execute code within the context of a database transaction, 039 * just like Spring's {@link org.springframework.transaction.support.TransactionTemplate} 040 * but with more functionality. It can auto-execute code upon rollback, it translates 041 * specific exceptions, and it stores transaction context in a ThreadLocal. 042 */ 043public interface IHapiTransactionService { 044 045 /** 046 * Fluent builder for creating a transactional callback 047 * <p> 048 * Method chain must end with a call to {@link IExecutionBuilder#execute(Runnable)} or one of the other 049 * overloads of <code>task(...)</code> 050 * </p> 051 */ 052 IExecutionBuilder withRequest(@Nullable RequestDetails theRequestDetails); 053 054 /** 055 * Fluent builder for internal system requests with no external 056 * requestdetails associated 057 */ 058 IExecutionBuilder withSystemRequest(); 059 060 /** 061 * Fluent builder for internal system requests with no external 062 * {@link RequestDetails} associated and a pre-specified partition ID. 063 * This method is sugar for 064 * <pre> 065 * withSystemRequest() 066 * .withRequestPartitionId(thePartitionId); 067 * </pre> 068 * 069 * @since 6.6.0 070 */ 071 default IExecutionBuilder withSystemRequestOnPartition(RequestPartitionId theRequestPartitionId) { 072 return withSystemRequest().withRequestPartitionId(theRequestPartitionId); 073 } 074 075 /** 076 * Convenience for TX working with non-partitioned entities. 077 */ 078 default IExecutionBuilder withSystemRequestOnDefaultPartition() { 079 return withSystemRequestOnPartition(RequestPartitionId.defaultPartition()); 080 } 081 082 /** 083 * @deprecated It is highly recommended to use {@link #withRequest(RequestDetails)} instead of this method, for increased visibility. 084 */ 085 @Deprecated(since = "6.10") 086 <T> T withRequest( 087 @Nullable RequestDetails theRequestDetails, 088 @Nullable TransactionDetails theTransactionDetails, 089 @Nonnull Propagation thePropagation, 090 @Nonnull Isolation theIsolation, 091 @Nonnull ICallable<T> theCallback); 092 093 interface IExecutionBuilder extends TransactionOperations { 094 095 IExecutionBuilder withIsolation(Isolation theIsolation); 096 097 IExecutionBuilder withTransactionDetails(TransactionDetails theTransactionDetails); 098 099 IExecutionBuilder withPropagation(Propagation thePropagation); 100 101 IExecutionBuilder withRequestPartitionId(RequestPartitionId theRequestPartitionId); 102 103 IExecutionBuilder readOnly(); 104 105 IExecutionBuilder onRollback(Runnable theOnRollback); 106 107 void execute(Runnable theTask); 108 109 <T> T execute(Callable<T> theTask); 110 111 <T> T execute(@Nonnull TransactionCallback<T> callback); 112 113 /** 114 * Read query path. 115 */ 116 default <T> T read(Callable<T> theCallback) { 117 return execute(theCallback); 118 } 119 120 /** 121 * Search for open Stream. 122 * The Stream may not be readable outside an outermost transaction. 123 */ 124 default <T> Stream<T> search(Callable<Stream<T>> theCallback) { 125 return execute(theCallback); 126 } 127 128 /** 129 * Search for concrete List. 130 */ 131 default <T> List<T> searchList(Callable<List<T>> theCallback) { 132 return execute(theCallback); 133 } 134 } 135}