use of io.cdap.cdap.api.annotation.TransactionControl in project cdap by cdapio.
the class Transactions method getTransactionControl.
/**
* Determines the transaction control of a method, as (optionally) annotated with @TransactionPolicy.
* If the program's class does not implement the method, the superclass is inspected up to and including
* the given base class.
*
* @param defaultValue returned if no annotation is present
* @param baseClass upper bound for the super classes to be inspected
* @param program the program
* @param methodName the name of the method
* @param params the parameter types of the method
*
* @return the transaction control annotated for the method of the program class or its nearest superclass that
* is annotated; or defaultValue if no annotation is present in any of the superclasses
*/
public static TransactionControl getTransactionControl(TransactionControl defaultValue, Class<?> baseClass, Object program, String methodName, Class<?>... params) {
Class<?> cls = program.getClass();
while (Object.class != cls) {
// we know that Object cannot have this annotation :)
TransactionControl txControl = getTransactionControl(cls, methodName, params);
if (txControl != null) {
return txControl;
}
if (cls == baseClass) {
// reached bounding superclass
break;
}
cls = cls.getSuperclass();
}
// if we reach this point, then none of the super classes had an annotation for the method
for (Class<?> interf : program.getClass().getInterfaces()) {
TransactionControl txControl = getTransactionControl(interf, methodName, params);
if (txControl != null) {
return txControl;
}
}
return defaultValue;
}
use of io.cdap.cdap.api.annotation.TransactionControl in project cdap by cdapio.
the class AbstractHttpHandlerDelegator method wrapContentConsumer.
/**
* Returns a new instance of {@link BodyConsumer} that wraps around the given {@link HttpContentConsumer}
* and {@link DelayedHttpServiceResponder}.
*
* IMPORTANT: This method will also capture the context associated with the current thread, hence after
* this method is called, no other methods on this class should be called from the current thread.
*
* This method is called from handler class generated by {@link HttpHandlerGenerator}.
*/
@SuppressWarnings("unused")
protected final BodyConsumer wrapContentConsumer(HttpContentConsumer consumer, DelayedHttpServiceResponder responder, TransactionControl defaultTxControl) {
Preconditions.checkState(!responder.hasBufferedResponse(), "HttpContentConsumer may not be used after a response has already been sent.");
// Close the provided responder since a new one will be created for the BodyConsumerAdapter to use.
responder.close();
ServiceTaskExecutor taskExecutor = context.getServiceTaskExecutor();
Cancellable contextReleaser = context.capture();
return new BodyConsumerAdapter(new DelayedHttpServiceResponder(responder, (contentProducer, txServiceContext) -> new BodyProducerAdapter(contentProducer, txServiceContext, contextReleaser, defaultTxControl)), consumer, taskExecutor, contextReleaser, defaultTxControl);
}
use of io.cdap.cdap.api.annotation.TransactionControl in project cdap by cdapio.
the class WorkflowDriver method executeCondition.
@SuppressWarnings("unchecked")
private void executeCondition(ApplicationSpecification appSpec, final WorkflowConditionNode node, InstantiatorFactory instantiator, ClassLoader classLoader, WorkflowToken token) throws Exception {
final BasicWorkflowContext context = new BasicWorkflowContext(workflowSpec, token, program, programOptions, cConf, metricsCollectionService, datasetFramework, txClient, discoveryServiceClient, nodeStates, pluginInstantiator, secureStore, secureStoreManager, messagingService, node.getConditionSpecification(), metadataReader, metadataPublisher, namespaceQueryAdmin, fieldLineageWriter, remoteClientFactory);
final Iterator<WorkflowNode> iterator;
Class<?> clz = classLoader.loadClass(node.getPredicateClassName());
Predicate<WorkflowContext> predicate = instantiator.get(TypeToken.of((Class<? extends Predicate<WorkflowContext>>) clz)).create();
if (!(predicate instanceof Condition)) {
iterator = predicate.apply(context) ? node.getIfBranch().iterator() : node.getElseBranch().iterator();
} else {
final Condition workflowCondition = (Condition) predicate;
Reflections.visit(workflowCondition, workflowCondition.getClass(), new PropertyFieldSetter(node.getConditionSpecification().getProperties()), new DataSetFieldSetter(context), new MetricsFieldSetter(context.getMetrics()));
TransactionControl defaultTxControl = workflowContext.getDefaultTxControl();
try {
// AbstractCondition implements final initialize(context) and requires subclass to
// implement initialize(), whereas conditions that directly implement Condition can
// override initialize(context)
TransactionControl txControl = workflowCondition instanceof AbstractCondition ? Transactions.getTransactionControl(defaultTxControl, AbstractCondition.class, workflowCondition, "initialize") : Transactions.getTransactionControl(defaultTxControl, Condition.class, workflowCondition, "initialize", WorkflowContext.class);
context.initializeProgram(workflowCondition, txControl, false);
boolean result = context.execute(() -> workflowCondition.apply(context));
iterator = result ? node.getIfBranch().iterator() : node.getElseBranch().iterator();
} finally {
TransactionControl txControl = Transactions.getTransactionControl(defaultTxControl, Condition.class, workflowCondition, "destroy");
context.destroyProgram(workflowCondition, txControl, false);
}
}
// If a workflow updates its token at a condition node, it will be persisted after the execution of the next node.
// However, the call below ensures that even if the workflow fails/crashes after a condition node, updates from the
// condition node are also persisted.
workflowStateWriter.setWorkflowToken(workflowRunId, token);
executeAll(iterator, appSpec, instantiator, classLoader, token);
}
use of io.cdap.cdap.api.annotation.TransactionControl in project cdap by cdapio.
the class WorkflowDriver method initializeWorkflow.
@SuppressWarnings("unchecked")
private Workflow initializeWorkflow() throws Exception {
Class<?> clz = Class.forName(workflowSpec.getClassName(), true, program.getClassLoader());
if (!Workflow.class.isAssignableFrom(clz)) {
throw new IllegalStateException(String.format("%s is not Workflow.", clz));
}
Class<? extends Workflow> workflowClass = (Class<? extends Workflow>) clz;
final Workflow workflow = new InstantiatorFactory(false).get(TypeToken.of(workflowClass)).create();
// set metrics
Reflections.visit(workflow, workflow.getClass(), new MetricsFieldSetter(workflowContext.getMetrics()));
if (!(workflow instanceof ProgramLifecycle)) {
return workflow;
}
final TransactionControl txControl = Transactions.getTransactionControl(workflowContext.getDefaultTxControl(), Workflow.class, workflow, "initialize", WorkflowContext.class);
basicWorkflowToken.setCurrentNode(workflowSpec.getName());
workflowContext.setState(new ProgramState(ProgramStatus.INITIALIZING, null));
workflowContext.initializeProgram((ProgramLifecycle) workflow, txControl, false);
workflowStateWriter.setWorkflowToken(workflowRunId, basicWorkflowToken);
return workflow;
}
use of io.cdap.cdap.api.annotation.TransactionControl in project cdap by cdapio.
the class WorkflowDriver method destroyWorkflow.
@SuppressWarnings("unchecked")
private void destroyWorkflow() {
if (!(workflow instanceof ProgramLifecycle)) {
return;
}
final TransactionControl txControl = Transactions.getTransactionControl(workflowContext.getDefaultTxControl(), Workflow.class, workflow, "destroy");
basicWorkflowToken.setCurrentNode(workflowSpec.getName());
workflowContext.destroyProgram((ProgramLifecycle) workflow, txControl, false);
try {
workflowStateWriter.setWorkflowToken(workflowRunId, basicWorkflowToken);
} catch (Throwable t) {
LOG.error("Failed to store the final workflow token of Workflow {}", workflowRunId, t);
}
if (ProgramStatus.COMPLETED != workflowContext.getState().getStatus()) {
return;
}
writeFieldLineage(workflowContext);
}
Aggregations