use of co.cask.cdap.internal.app.runtime.AbstractListener in project cdap by caskdata.
the class WorkflowTest method testOneActionWorkflow.
@Test(timeout = 120 * 1000L)
public void testOneActionWorkflow() throws Exception {
final ApplicationWithPrograms app = AppFabricTestHelper.deployApplicationWithManager(OneActionWorkflowApp.class, TEMP_FOLDER_SUPPLIER);
final Injector injector = AppFabricTestHelper.getInjector();
final ProgramDescriptor programDescriptor = Iterators.filter(app.getPrograms().iterator(), new Predicate<ProgramDescriptor>() {
@Override
public boolean apply(ProgramDescriptor input) {
return input.getProgramId().getType() == ProgramType.WORKFLOW;
}
}).next();
final SettableFuture<String> completion = SettableFuture.create();
final ProgramController controller = AppFabricTestHelper.submit(app, programDescriptor.getSpecification().getClassName(), new BasicArguments(), TEMP_FOLDER_SUPPLIER);
controller.addListener(new AbstractListener() {
@Override
public void init(ProgramController.State currentState, @Nullable Throwable cause) {
LOG.info("Initializing");
injector.getInstance(Store.class).setStart(controller.getProgramRunId().getParent(), controller.getProgramRunId().getRun(), System.currentTimeMillis());
}
@Override
public void completed() {
LOG.info("Completed");
completion.set("Completed");
}
@Override
public void error(Throwable cause) {
LOG.info("Error", cause);
completion.setException(cause);
}
}, Threads.SAME_THREAD_EXECUTOR);
String run = completion.get();
Assert.assertEquals("Completed", run);
}
use of co.cask.cdap.internal.app.runtime.AbstractListener in project cdap by caskdata.
the class WorkflowProgramRunner method run.
@Override
public ProgramController run(final Program program, final ProgramOptions options) {
// Extract and verify options
ApplicationSpecification appSpec = program.getApplicationSpecification();
Preconditions.checkNotNull(appSpec, "Missing application specification.");
ProgramType processorType = program.getType();
Preconditions.checkNotNull(processorType, "Missing processor type.");
Preconditions.checkArgument(processorType == ProgramType.WORKFLOW, "Only WORKFLOW process type is supported.");
WorkflowSpecification workflowSpec = appSpec.getWorkflows().get(program.getName());
Preconditions.checkNotNull(workflowSpec, "Missing WorkflowSpecification for %s", program.getName());
final RunId runId = ProgramRunners.getRunId(options);
// Setup dataset framework context, if required
if (datasetFramework instanceof ProgramContextAware) {
ProgramId programId = program.getId();
((ProgramContextAware) datasetFramework).setContext(new BasicProgramContext(programId.run(runId)));
}
// List of all Closeable resources that needs to be cleanup
final List<Closeable> closeables = new ArrayList<>();
try {
PluginInstantiator pluginInstantiator = createPluginInstantiator(options, program.getClassLoader());
if (pluginInstantiator != null) {
closeables.add(pluginInstantiator);
}
WorkflowDriver driver = new WorkflowDriver(program, options, hostname, workflowSpec, programRunnerFactory, metricsCollectionService, datasetFramework, discoveryServiceClient, txClient, runtimeStore, cConf, pluginInstantiator, secureStore, secureStoreManager, messagingService);
// Controller needs to be created before starting the driver so that the state change of the driver
// service can be fully captured by the controller.
final ProgramController controller = new WorkflowProgramController(program, driver, serviceAnnouncer, runId);
final String twillRunId = options.getArguments().getOption(ProgramOptionConstants.TWILL_RUN_ID);
controller.addListener(new AbstractListener() {
@Override
public void init(ProgramController.State state, @Nullable Throwable cause) {
// Get start time from RunId
long startTimeInSeconds = RunIds.getTime(controller.getRunId(), TimeUnit.SECONDS);
if (startTimeInSeconds == -1) {
// If RunId is not time-based, use current time as start time
startTimeInSeconds = TimeUnit.MILLISECONDS.toSeconds(System.currentTimeMillis());
}
final long finalStartTimeInSeconds = startTimeInSeconds;
Retries.supplyWithRetries(new Supplier<Void>() {
@Override
public Void get() {
runtimeStore.setStart(program.getId(), runId.getId(), finalStartTimeInSeconds, twillRunId, options.getUserArguments().asMap(), options.getArguments().asMap());
return null;
}
}, RetryStrategies.fixDelay(Constants.Retry.RUN_RECORD_UPDATE_RETRY_DELAY_SECS, TimeUnit.SECONDS));
// This can happen if there is a delay in calling the init listener
if (state == ProgramController.State.COMPLETED) {
completed();
}
// This can happen if there is a delay in calling the init listener
if (state == ProgramController.State.ERROR) {
error(controller.getFailureCause());
}
}
@Override
public void completed() {
LOG.debug("Program {} with run id {} completed successfully.", program.getId(), runId.getId());
Retries.supplyWithRetries(new Supplier<Void>() {
@Override
public Void get() {
runtimeStore.setStop(program.getId(), runId.getId(), TimeUnit.MILLISECONDS.toSeconds(System.currentTimeMillis()), ProgramController.State.COMPLETED.getRunStatus());
return null;
}
}, RetryStrategies.fixDelay(Constants.Retry.RUN_RECORD_UPDATE_RETRY_DELAY_SECS, TimeUnit.SECONDS));
}
@Override
public void killed() {
LOG.debug("Program {} with run id {} killed.", program.getId(), runId.getId());
Retries.supplyWithRetries(new Supplier<Void>() {
@Override
public Void get() {
runtimeStore.setStop(program.getId(), runId.getId(), TimeUnit.MILLISECONDS.toSeconds(System.currentTimeMillis()), ProgramController.State.KILLED.getRunStatus());
return null;
}
}, RetryStrategies.fixDelay(Constants.Retry.RUN_RECORD_UPDATE_RETRY_DELAY_SECS, TimeUnit.SECONDS));
}
@Override
public void suspended() {
LOG.debug("Suspending Program {} with run id {}.", program.getId(), runId.getId());
Retries.supplyWithRetries(new Supplier<Void>() {
@Override
public Void get() {
runtimeStore.setSuspend(program.getId(), runId.getId());
return null;
}
}, RetryStrategies.fixDelay(Constants.Retry.RUN_RECORD_UPDATE_RETRY_DELAY_SECS, TimeUnit.SECONDS));
}
@Override
public void resuming() {
LOG.debug("Resuming Program {} {}.", program.getId(), runId.getId());
Retries.supplyWithRetries(new Supplier<Void>() {
@Override
public Void get() {
runtimeStore.setResume(program.getId(), runId.getId());
return null;
}
}, RetryStrategies.fixDelay(Constants.Retry.RUN_RECORD_UPDATE_RETRY_DELAY_SECS, TimeUnit.SECONDS));
}
@Override
public void error(final Throwable cause) {
LOG.info("Program {} with run id {} stopped because of error {}.", program.getId(), runId.getId(), cause);
closeAllQuietly(closeables);
Retries.supplyWithRetries(new Supplier<Void>() {
@Override
public Void get() {
runtimeStore.setStop(program.getId(), runId.getId(), TimeUnit.MILLISECONDS.toSeconds(System.currentTimeMillis()), ProgramController.State.ERROR.getRunStatus(), new BasicThrowable(cause));
return null;
}
}, RetryStrategies.fixDelay(Constants.Retry.RUN_RECORD_UPDATE_RETRY_DELAY_SECS, TimeUnit.SECONDS));
}
}, Threads.SAME_THREAD_EXECUTOR);
driver.start();
return controller;
} catch (Exception e) {
closeAllQuietly(closeables);
throw Throwables.propagate(e);
}
}
use of co.cask.cdap.internal.app.runtime.AbstractListener in project cdap by caskdata.
the class WorkerProgramRunnerTest method stopProgram.
private void stopProgram(ProgramController controller) throws Throwable {
final AtomicReference<Throwable> errorCause = new AtomicReference<>();
final CountDownLatch complete = new CountDownLatch(1);
controller.addListener(new AbstractListener() {
@Override
public void error(Throwable cause) {
complete.countDown();
errorCause.set(cause);
}
@Override
public void completed() {
complete.countDown();
}
@Override
public void killed() {
complete.countDown();
}
}, Threads.SAME_THREAD_EXECUTOR);
controller.stop();
complete.await(30, TimeUnit.SECONDS);
runningPrograms.remove(controller);
Throwable t = errorCause.get();
if (t != null) {
throw t;
}
}
use of co.cask.cdap.internal.app.runtime.AbstractListener in project cdap by caskdata.
the class ProgramLifecycleService method start.
/**
* Start a Program.
*
* @param programId the {@link ProgramId program} to start
* @param systemArgs system arguments
* @param userArgs user arguments
* @param debug enable debug mode
* @return {@link ProgramRuntimeService.RuntimeInfo}
* @throws IOException if there is an error starting the program
* @throws ProgramNotFoundException if program is not found
* @throws UnauthorizedException if the logged in user is not authorized to start the program. To start a program,
* a user requires {@link Action#EXECUTE} on the program
* @throws Exception if there were other exceptions checking if the current user is authorized to start the program
*/
public ProgramRuntimeService.RuntimeInfo start(final ProgramId programId, final Map<String, String> systemArgs, final Map<String, String> userArgs, boolean debug) throws Exception {
authorizationEnforcer.enforce(programId, authenticationContext.getPrincipal(), Action.EXECUTE);
ProgramDescriptor programDescriptor = store.loadProgram(programId);
BasicArguments systemArguments = new BasicArguments(systemArgs);
BasicArguments userArguments = new BasicArguments(userArgs);
ProgramRuntimeService.RuntimeInfo runtimeInfo = runtimeService.run(programDescriptor, new SimpleProgramOptions(programId.getProgram(), systemArguments, userArguments, debug));
final ProgramController controller = runtimeInfo.getController();
final String runId = controller.getRunId().getId();
final String twillRunId = runtimeInfo.getTwillRunId() == null ? null : runtimeInfo.getTwillRunId().getId();
if (programId.getType() != ProgramType.MAPREDUCE && programId.getType() != ProgramType.SPARK && programId.getType() != ProgramType.WORKFLOW) {
// MapReduce state recording is done by the MapReduceProgramRunner, Spark state recording
// is done by SparkProgramRunner, and Workflow state recording is done by WorkflowProgramRunner.
// TODO [JIRA: CDAP-2013] Same needs to be done for other programs as well
controller.addListener(new AbstractListener() {
@Override
public void init(ProgramController.State state, @Nullable Throwable cause) {
// Get start time from RunId
long startTimeInSeconds = RunIds.getTime(controller.getRunId(), TimeUnit.SECONDS);
if (startTimeInSeconds == -1) {
// If RunId is not time-based, use current time as start time
startTimeInSeconds = TimeUnit.MILLISECONDS.toSeconds(System.currentTimeMillis());
}
final long finalStartTimeInSeconds = startTimeInSeconds;
Retries.supplyWithRetries(new Supplier<Void>() {
@Override
public Void get() {
store.setStart(programId, runId, finalStartTimeInSeconds, twillRunId, userArgs, systemArgs);
return null;
}
}, RetryStrategies.fixDelay(Constants.Retry.RUN_RECORD_UPDATE_RETRY_DELAY_SECS, TimeUnit.SECONDS));
if (state == ProgramController.State.COMPLETED) {
completed();
}
if (state == ProgramController.State.ERROR) {
error(controller.getFailureCause());
}
}
@Override
public void completed() {
LOG.debug("Program {} completed successfully.", programId);
Retries.supplyWithRetries(new Supplier<Void>() {
@Override
public Void get() {
store.setStop(programId, runId, TimeUnit.MILLISECONDS.toSeconds(System.currentTimeMillis()), ProgramController.State.COMPLETED.getRunStatus());
return null;
}
}, RetryStrategies.fixDelay(Constants.Retry.RUN_RECORD_UPDATE_RETRY_DELAY_SECS, TimeUnit.SECONDS));
}
@Override
public void killed() {
LOG.debug("Program {} killed.", programId);
Retries.supplyWithRetries(new Supplier<Void>() {
@Override
public Void get() {
store.setStop(programId, runId, TimeUnit.MILLISECONDS.toSeconds(System.currentTimeMillis()), ProgramController.State.KILLED.getRunStatus());
return null;
}
}, RetryStrategies.fixDelay(Constants.Retry.RUN_RECORD_UPDATE_RETRY_DELAY_SECS, TimeUnit.SECONDS));
}
@Override
public void suspended() {
LOG.debug("Suspending Program {} {}.", programId, runId);
Retries.supplyWithRetries(new Supplier<Void>() {
@Override
public Void get() {
store.setSuspend(programId, runId);
return null;
}
}, RetryStrategies.fixDelay(Constants.Retry.RUN_RECORD_UPDATE_RETRY_DELAY_SECS, TimeUnit.SECONDS));
}
@Override
public void resuming() {
LOG.debug("Resuming Program {} {}.", programId, runId);
Retries.supplyWithRetries(new Supplier<Void>() {
@Override
public Void get() {
store.setResume(programId, runId);
return null;
}
}, RetryStrategies.fixDelay(Constants.Retry.RUN_RECORD_UPDATE_RETRY_DELAY_SECS, TimeUnit.SECONDS));
}
@Override
public void error(final Throwable cause) {
LOG.info("Program stopped with error {}, {}", programId, runId, cause);
Retries.supplyWithRetries(new Supplier<Void>() {
@Override
public Void get() {
store.setStop(programId, runId, TimeUnit.MILLISECONDS.toSeconds(System.currentTimeMillis()), ProgramController.State.ERROR.getRunStatus(), new BasicThrowable(cause));
return null;
}
}, RetryStrategies.fixDelay(Constants.Retry.RUN_RECORD_UPDATE_RETRY_DELAY_SECS, TimeUnit.SECONDS));
}
}, Threads.SAME_THREAD_EXECUTOR);
}
return runtimeInfo;
}
use of co.cask.cdap.internal.app.runtime.AbstractListener in project cdap by caskdata.
the class MapReduceRunnerTestBase method waitForCompletion.
private boolean waitForCompletion(ProgramController controller) throws InterruptedException {
final AtomicBoolean success = new AtomicBoolean(false);
final CountDownLatch completion = new CountDownLatch(1);
controller.addListener(new AbstractListener() {
@Override
public void completed() {
success.set(true);
completion.countDown();
}
@Override
public void error(Throwable cause) {
completion.countDown();
}
}, Threads.SAME_THREAD_EXECUTOR);
// MR tests can run for long time.
completion.await(10, TimeUnit.MINUTES);
return success.get();
}
Aggregations