protected Action newInstance(ActionInstance actionInstance) { try { return actionInstance.getAction().newInstance(); } catch (InstantiationException | IllegalAccessException e) { throw new RuntimeException( String.format( "Exception occurred while creating an action instance of type %s: %s", actionInstance.getAction(), e.getMessage())); } }
@Override public void validate(ActionInstance actionInstance) { if (actionInstance == null) { throw new IllegalArgumentException("actionInstance cannot be null"); } if (actionInstance.getName() == null || "".equals(actionInstance.getName())) { throw new IllegalArgumentException("name for the actionInstance cannot be null or empty"); } if (actionInstance.getAction() == null) { throw new IllegalArgumentException("No Action class specified for the actionInstance"); } if (actionInstance.getTrigger() != null) { actionInstance.getTrigger().validate(); } }
/** * Deletes/Removes the {@code ActionInstance}. If it has a {@code CronTrigger} then it is also * un-scheduled from scheduler * * @throws com.netflix.scheduledactions.exceptions.ActionOperationException */ @Override public void delete(ActionInstance actionInstance) { actionInstanceDao.deleteActionInstance(actionInstance.getGroup(), actionInstance); if (actionInstance.getFenzoTrigger() != null) { try { triggerOperator.deleteTrigger(actionInstance.getGroup(), actionInstance.getFenzoTrigger()); } catch (SchedulerException e) { throw new ActionOperationException( String.format( "Exception occurred while deleting trigger %s for actionInstance %s", actionInstance.getTrigger(), actionInstance), e); } } logger.info("Successfully deleted the actionInstance {}", actionInstance); }
/** * Enables the {@code ActionInstance} * * @throws com.netflix.scheduledactions.exceptions.ActionOperationException */ @Override public void enable(ActionInstance actionInstance) { actionInstance.setDisabled(false); actionInstanceDao.updateActionInstance(actionInstance); if (actionInstance.getFenzoTrigger() != null) { try { triggerOperator.enableTrigger(actionInstance.getFenzoTrigger()); } catch (SchedulerException e) { throw new ActionOperationException( String.format( "Exception occurred while enabling trigger %s for actionInstance %s", actionInstance.getTrigger(), actionInstance), e); } } logger.info("Successfully enabled the actionInstance {}", actionInstance); }
/** Cancels all {@code Execution}s for this {@code ActionInstance} except for the one passed */ private void cancelPreviousExecutions(ActionInstance actionInstance, Execution execution) { List<Execution> executions = getInCompleteExecutionsBefore(actionInstance.getId(), execution); logger.info( "Cancelling following executions for actionInstance {} before {}: {}", actionInstance, execution, executions); for (Execution incomplete : executions) { cancel(incomplete, actionInstance); } }
@Override public void update(ActionInstance actionInstance) { // Find an existing one to update ActionInstance existingInstance = actionInstanceDao.getActionInstance(actionInstance.getId()); if (existingInstance == null) { throw new ActionOperationException( String.format( "No existing actionInstance with id %s found for the update operation", actionInstance.getId())); } // Set the id of the existing action instance so that this looks like an "update" operation actionInstance.setId(existingInstance.getId()); // Validate the new one before deleting the existing one validate(actionInstance); // Delete the existing one delete(existingInstance); // Register the new one this.register(actionInstance); logger.info("Successfully updated the actionInstance {}", actionInstance); }
/** * Registers a {@code ActionInstance} with actionInstance service * * @param actionInstance */ @Override public String register(ActionInstance actionInstance) { validate(actionInstance); actionInstanceDao.createActionInstance(actionInstance.getGroup(), actionInstance); if (actionInstance.getTrigger() != null) { actionInstance.setFenzoTrigger( actionInstance .getTrigger() .createFenzoTrigger(actionInstance.getContext(), InternalAction.class)); try { triggerOperator.registerTrigger( actionInstance.getGroup(), actionInstance.getFenzoTrigger()); } catch (SchedulerException e) { throw new ActionOperationException( String.format("Exception occurred while registering actionInstance %s", actionInstance), e); } } actionInstanceDao.updateActionInstance(actionInstance); logger.info("Successfully registered the actionInstance {}", actionInstance); return actionInstance.getId(); }
/** * Executes the {@code ActionInstance} * * @throws com.netflix.scheduledactions.exceptions.ExecutionException */ public Execution execute(final ActionInstance actionInstance, String initiator) { if (actionInstance.isDisabled()) { return null; } final String actionInstanceId = actionInstance.getId(); final Execution execution = new Execution(delegateId, actionInstanceId); final String executionId = executionDao.createExecution(actionInstanceId, execution); logger.info("[{}] Created execution for actionInstance: {}", actionInstanceId, executionId); execution.getLogger().info(String.format("Created execution %s", executionId)); List<Execution> previousExecutions = getInCompleteExecutionsBefore(actionInstanceId, execution); if (previousExecutions.size() > 0) { ConcurrentExecutionStrategy strategy = actionInstance.getConcurrentExecutionStrategy(); switch (strategy) { case ALLOW: execution .getLogger() .info("Concurrent execution strategy is: ALLOW, allowing execution..."); logger.info( "[{}] actionInstance concurrent execution strategy is: ALLOW, allowing execution...", actionInstanceId); break; case REJECT: Status status = Status.SKIPPED; status.setMessage( String.format( "ConcurrentExecutionStrategy for ActionInstance %s is REJECT and it has incomplete executions", actionInstance)); execution.setStatus(status); execution.setStartTime(new Date()); execution.setEndTime(new Date()); logger.info( "[{}] actionInstance concurrent execution strategy is: REJECT, skipping execution", actionInstanceId); execution .getLogger() .info("Concurrent execution strategy is: REJECT, skipping execution"); executionDao.updateExecution(execution); return execution; case REPLACE: logger.info( "[{}] actionInstance concurrent execution strategy is: REPLACE, cancelling previous execution(s)", actionInstanceId); cancelPreviousExecutions(actionInstance, execution); break; default: break; } } logger.info("[{}] Submitting runnable for execution: {}", actionInstanceId, executionId); executeService.submit( new Runnable() { @Override public void run() { try { Action action = newInstance(actionInstance); execution.getLogger().info("Calling executor.execute()..."); logger.info( "[{}] Calling executor.execute() for execution {} ...", actionInstanceId, executionId); executor.execute(action, actionInstance, execution); } catch (ExecutionException e) { Status status = e.getStatus() != null ? e.getStatus() : Status.FAILED; status.setMessage(e.getMessage()); execution.setEndTime(new Date()); execution.setStatus(status); execution.getLogger().error("Exception occurred while executing action", e); } catch (Exception e) { Status status = Status.FAILED; status.setMessage( String.format( "Exception occurred while executing action %s: %s", actionInstance.getAction(), e.getMessage())); execution.getLogger().error("Exception occurred while executing action", e); execution.setEndTime(new Date()); execution.setStatus(status); } finally { executionDao.updateExecution(execution); } } }); return execution; }