001/*
002 * Copyright 2006-2018 the original author or authors.
003 *
004 * Licensed under the Apache License, Version 2.0 (the "License");
005 * you may not use this file except in compliance with the License.
006 * You may obtain a copy of the License at
007 *
008 *      https://www.apache.org/licenses/LICENSE-2.0
009 *
010 * Unless required by applicable law or agreed to in writing, software
011 * distributed under the License is distributed on an "AS IS" BASIS,
012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
013 * See the License for the specific language governing permissions and
014 * limitations under the License.
015 */
016
017package org.springframework.batch.core.repository;
018
019import org.springframework.batch.core.Job;
020import org.springframework.batch.core.JobExecution;
021import org.springframework.batch.core.JobInstance;
022import org.springframework.batch.core.JobParameters;
023import org.springframework.batch.core.Step;
024import org.springframework.batch.core.StepExecution;
025import org.springframework.batch.core.repository.dao.JobExecutionDao;
026import org.springframework.batch.core.repository.dao.JobInstanceDao;
027import org.springframework.batch.item.ExecutionContext;
028import org.springframework.lang.Nullable;
029import org.springframework.transaction.annotation.Isolation;
030
031import java.util.Collection;
032
033/**
034 * <p>
035 * Repository responsible for persistence of batch meta-data entities.
036 * </p>
037 *
038 * @see JobInstance
039 * @see JobExecution
040 * @see StepExecution
041 *
042 * @author Lucas Ward
043 * @author Dave Syer
044 * @author Robert Kasanicky
045 * @author David Turanski
046 * @author Michael Minella
047 * @author Mahmoud Ben Hassine
048 */
049public interface JobRepository {
050
051        /**
052         * Check if an instance of this job already exists with the parameters
053         * provided.
054         *
055         * @param jobName the name of the job
056         * @param jobParameters the parameters to match
057         * @return true if a {@link JobInstance} already exists for this job name
058         * and job parameters
059         */
060        boolean isJobInstanceExists(String jobName, JobParameters jobParameters);
061
062        /**
063         * Create a new {@link JobInstance} with the name and job parameters provided.
064         *
065         * @param jobName logical name of the job
066         * @param jobParameters parameters used to execute the job
067         * @return the new {@link JobInstance}
068         */
069        JobInstance createJobInstance(String jobName, JobParameters jobParameters);
070
071        /**
072         * Create a new {@link JobExecution} based upon the {@link JobInstance} it's associated
073         * with, the {@link JobParameters} used to execute it with and the location of the configuration
074         * file that defines the job.
075         *
076         * @param jobInstance {@link JobInstance} instance to initialize the new JobExecution.
077         * @param jobParameters {@link JobParameters} instance to initialize the new JobExecution.
078         * @param jobConfigurationLocation {@link String} instance to initialize the new JobExecution.
079         * @return the new {@link JobExecution}.
080         */
081        JobExecution createJobExecution(JobInstance jobInstance, JobParameters jobParameters, String jobConfigurationLocation);
082
083        /**
084         * <p>
085         * Create a {@link JobExecution} for a given {@link Job} and
086         * {@link JobParameters}. If matching {@link JobInstance} already exists,
087         * the job must be restartable and it's last JobExecution must *not* be
088         * completed. If matching {@link JobInstance} does not exist yet it will be
089         * created.
090         * </p>
091         *
092         * <p>
093         * If this method is run in a transaction (as it normally would be) with
094         * isolation level at {@link Isolation#REPEATABLE_READ} or better, then this
095         * method should block if another transaction is already executing it (for
096         * the same {@link JobParameters} and job name). The first transaction to
097         * complete in this scenario obtains a valid {@link JobExecution}, and
098         * others throw {@link JobExecutionAlreadyRunningException} (or timeout).
099         * There are no such guarantees if the {@link JobInstanceDao} and
100         * {@link JobExecutionDao} do not respect the transaction isolation levels
101         * (e.g. if using a non-relational data-store, or if the platform does not
102         * support the higher isolation levels).
103         * </p>
104         *
105         * @param jobName the name of the job that is to be executed
106         *
107         * @param jobParameters the runtime parameters for the job
108         *
109         * @return a valid {@link JobExecution} for the arguments provided
110         *
111         * @throws JobExecutionAlreadyRunningException if there is a
112         * {@link JobExecution} already running for the job instance with the
113         * provided job and parameters.
114         * @throws JobRestartException if one or more existing {@link JobInstance}s
115         * is found with the same parameters and {@link Job#isRestartable()} is
116         * false.
117         * @throws JobInstanceAlreadyCompleteException if a {@link JobInstance} is
118         * found and was already completed successfully.
119         *
120         */
121        JobExecution createJobExecution(String jobName, JobParameters jobParameters)
122                        throws JobExecutionAlreadyRunningException, JobRestartException, JobInstanceAlreadyCompleteException;
123
124        /**
125         * Update the {@link JobExecution} (but not its {@link ExecutionContext}).
126         *
127         * Preconditions: {@link JobExecution} must contain a valid
128         * {@link JobInstance} and be saved (have an id assigned).
129         *
130         * @param jobExecution {@link JobExecution} instance to be updated in the repo.
131         */
132        void update(JobExecution jobExecution);
133
134        /**
135         * Save the {@link StepExecution} and its {@link ExecutionContext}. ID will
136         * be assigned - it is not permitted that an ID be assigned before calling
137         * this method. Instead, it should be left blank, to be assigned by a
138         * {@link JobRepository}.
139         *
140         * Preconditions: {@link StepExecution} must have a valid {@link Step}.
141         *
142         * @param stepExecution {@link StepExecution} instance to be added to the repo.
143         */
144        void add(StepExecution stepExecution);
145
146        /**
147         * Save a collection of {@link StepExecution}s and each {@link ExecutionContext}. The
148         * StepExecution ID will be assigned - it is not permitted that an ID be assigned before calling
149         * this method. Instead, it should be left blank, to be assigned by {@link JobRepository}.
150         *
151         * Preconditions: {@link StepExecution} must have a valid {@link Step}.
152         *
153         * @param stepExecutions collection of {@link StepExecution} instances to be added to the repo.
154         */
155        void addAll(Collection<StepExecution> stepExecutions);
156
157        /**
158         * Update the {@link StepExecution} (but not its {@link ExecutionContext}).
159         *
160         * Preconditions: {@link StepExecution} must be saved (have an id assigned).
161         *
162         * @param stepExecution {@link StepExecution} instance to be updated in the repo.
163         */
164        void update(StepExecution stepExecution);
165
166        /**
167         * Persist the updated {@link ExecutionContext}s of the given
168         * {@link StepExecution}.
169         *
170         * @param stepExecution {@link StepExecution} instance to be used to update the context.
171         */
172        void updateExecutionContext(StepExecution stepExecution);
173
174        /**
175         * Persist the updated {@link ExecutionContext} of the given
176         * {@link JobExecution}.
177         * @param jobExecution {@link JobExecution} instance to be used to update the context.
178         */
179        void updateExecutionContext(JobExecution jobExecution);
180
181        /**
182         * @param jobInstance {@link JobInstance} instance containing the step executions.
183         * @param stepName the name of the step execution that might have run.
184         * @return the last execution of step for the given job instance.
185         */
186        @Nullable
187        StepExecution getLastStepExecution(JobInstance jobInstance, String stepName);
188
189        /**
190         * @param jobInstance {@link JobInstance} instance containing the step executions.
191         * @param stepName the name of the step execution that might have run.
192         * @return the execution count of the step within the given job instance.
193         */
194        int getStepExecutionCount(JobInstance jobInstance, String stepName);
195
196        /**
197         * @param jobName the name of the job that might have run
198         * @param jobParameters parameters identifying the {@link JobInstance}
199         * @return the last execution of job if exists, null otherwise
200         */
201        @Nullable
202        JobExecution getLastJobExecution(String jobName, JobParameters jobParameters);
203
204}