001/*-
002 * #%L
003 * HAPI FHIR Storage api
004 * %%
005 * Copyright (C) 2014 - 2023 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 org.springframework.transaction.annotation.Isolation;
027import org.springframework.transaction.annotation.Propagation;
028import org.springframework.transaction.support.TransactionCallback;
029
030import java.util.concurrent.Callable;
031import javax.annotation.Nonnull;
032import javax.annotation.Nullable;
033
034/**
035 * This class is used to execute code within the context of a database transaction,
036 * just like Spring's {@link org.springframework.transaction.support.TransactionTemplate}
037 * but with more functionality. It can auto-execute code upon rollback, it translates
038 * specific exceptions, and it stores transaction context in a ThreadLocal.
039 */
040public interface IHapiTransactionService {
041
042        /**
043         * Fluent builder for creating a transactional callback
044         * <p>
045         * Method chain must end with a call to {@link IExecutionBuilder#execute(Runnable)} or one of the other
046         * overloads of <code>task(...)</code>
047         * </p>
048         */
049        IExecutionBuilder withRequest(@Nullable RequestDetails theRequestDetails);
050
051        /**
052         * Fluent builder for internal system requests with no external
053         * requestdetails associated
054         */
055        IExecutionBuilder withSystemRequest();
056
057        /**
058         * Fluent builder for internal system requests with no external
059         * {@link RequestDetails} associated and a pre-specified partition ID.
060         * This method is sugar for
061         * <pre>
062         *    withSystemRequest()
063         *                      .withRequestPartitionId(thePartitionId);
064         * </pre>
065         *
066         * @since 6.6.0
067         */
068        default IExecutionBuilder withSystemRequestOnPartition(RequestPartitionId theRequestPartitionId) {
069                return withSystemRequest().withRequestPartitionId(theRequestPartitionId);
070        }
071
072        /**
073         * @deprecated It is highly recommended to use {@link #withRequest(RequestDetails)} instead of this method, for increased visibility.
074         */
075        @Deprecated
076        <T> T withRequest(
077                        @Nullable RequestDetails theRequestDetails,
078                        @Nullable TransactionDetails theTransactionDetails,
079                        @Nonnull Propagation thePropagation,
080                        @Nonnull Isolation theIsolation,
081                        @Nonnull ICallable<T> theCallback);
082
083        interface IExecutionBuilder {
084
085                IExecutionBuilder withIsolation(Isolation theIsolation);
086
087                IExecutionBuilder withTransactionDetails(TransactionDetails theTransactionDetails);
088
089                IExecutionBuilder withPropagation(Propagation thePropagation);
090
091                IExecutionBuilder withRequestPartitionId(RequestPartitionId theRequestPartitionId);
092
093                IExecutionBuilder readOnly();
094
095                IExecutionBuilder onRollback(Runnable theOnRollback);
096
097                void execute(Runnable theTask);
098
099                <T> T execute(Callable<T> theTask);
100
101                <T> T execute(TransactionCallback<T> callback);
102        }
103}