/* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.apache.usergrid.batch; import java.util.UUID; import org.apache.commons.lang3.builder.ToStringBuilder; import org.apache.usergrid.batch.repository.JobDescriptor; import org.apache.usergrid.batch.service.JobRuntimeService; import org.apache.usergrid.persistence.entities.JobData; import org.apache.usergrid.persistence.entities.JobStat; import com.google.common.base.Preconditions; /** * Models the execution context of the {@link Job} with state transition methods for job status. * * @author zznate * @author tnine */ public class JobExecutionImpl implements JobExecution, JobRuntime { private final UUID jobId; private final UUID runId; private final String jobName; private long duration; private Status status = Status.NOT_STARTED; private long startTime; private JobRuntimeService runtime; private UUID transactionId; private JobData data; private JobStat stats; private long delay = -1; public JobExecutionImpl( JobDescriptor jobDescriptor ) { this.runId = UUID.randomUUID(); this.jobId = jobDescriptor.getJobId(); this.runtime = jobDescriptor.getRuntime(); this.jobName = jobDescriptor.getJobName(); this.transactionId = jobDescriptor.getTransactionId(); this.data = jobDescriptor.getData(); this.stats = jobDescriptor.getStats(); } public String toString() { return new ToStringBuilder(this) .append("runId", runId) .append("jobName", jobName) .append("status", status) .toString(); } public UUID getRunId() { return runId; } public long getDuration() { return duration; } /** @param transactionId the transactionId to set */ public void setTransactionId( UUID transactionId ) { this.transactionId = transactionId; } public UUID getJobId() { return jobId; } /** @return the data */ public JobData getJobData() { return data; } /* * (non-Javadoc) * * @see org.apache.usergrid.batch.JobExecution#getJobStats() */ @Override public JobStat getJobStats() { return stats; } public void start( int maxFailures ) { Preconditions.checkState( this.status.equals( Status.NOT_STARTED ) || this.status.equals( Status.FAILED ), "Attempted to start job in progress" ); this.status = Status.IN_PROGRESS; stats.incrementRuns(); // use >= in case the threshold lowers after the job has passed the failure // mark if ( maxFailures != FOREVER && stats.getTotalAttempts() > maxFailures ) { status = Status.DEAD; } startTime = System.currentTimeMillis(); stats.setStartTime( startTime ); } public void completed() { updateState( Status.IN_PROGRESS, "Attempted to complete job not in progress", Status.COMPLETED ); stats.setDuration( duration ); } /** * Mark this execution as failed. Also pass the maximum number of possible failures. Set to JobExecution.FOREVER for * no limit */ public void failed() { updateState( Status.IN_PROGRESS, "Attempted to fail job not in progress", Status.FAILED ); } /** This job should be killed and not retried */ public void killed() { updateState( Status.IN_PROGRESS, "Attempted to fail job not in progress", Status.DEAD ); } /* * (non-Javadoc) * * @see org.apache.usergrid.batch.JobExecution#delay(long) */ @Override public void delay( long delay ) { updateState( Status.IN_PROGRESS, "Attempted to delay a job not in progress", Status.DELAYED ); stats.incrementDelays(); this.delay = delay; runtime.delay( this ); } /** Update our state */ private void updateState( Status expected, String message, Status newStatus ) { Preconditions.checkState( this.status.equals( expected ), message ); this.status = newStatus; duration = System.currentTimeMillis() - startTime; } /** Make sure we're in progress and notifiy the scheduler we're still running */ public void heartbeat() { Preconditions .checkState( this.status.equals( Status.IN_PROGRESS ), "Attempted to heartbeat job not in progress" ); runtime.heartbeat( this ); } /* (non-Javadoc) * @see org.apache.usergrid.batch.JobExecution#heartbeat(long) */ @Override public void heartbeat( long milliseconds ) { Preconditions .checkState( this.status.equals( Status.IN_PROGRESS ), "Attempted to heartbeat job not in progress" ); runtime.heartbeat( this, milliseconds ); this.delay = milliseconds; } /** @return the startTime */ public long getStartTime() { return startTime; } /** @return the transactionId */ public UUID getTransactionId() { return transactionId; } public Status getStatus() { return this.status; } /** @return the delay */ public long getDelay() { return delay; } /** @return the jobName */ public String getJobName() { return jobName; } /* (non-Javadoc) * @see org.apache.usergrid.batch.JobRuntime#getExecution() */ @Override public JobExecution getExecution() { return this; } }