/* * Copyright 2012 AppSatori s.r.o. * * Licensed 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 eu.appsatori.pipes; import java.util.logging.Logger; import com.google.appengine.api.taskqueue.DeferredTask; import com.google.appengine.api.taskqueue.DeferredTaskContext; /** * Internal implementation of {@link DeferredTask} used to run nodes in queues. * * @author <a href="mailto:vladimir.orany@appsatori.eu">Vladimir Orany</a> * * @param <P> either {@link SerialPipe} or {@link ParallelPipe} to control the flow * @param <A> type of argument passed to the node * @param <N> type of the passed node */ class NodeTask<P extends Pipe, A,N extends Node<P,A>> implements DeferredTask { private static final Logger log = Logger.getLogger(NodeTask.class.getName()); private static final long serialVersionUID = -3569377001403545004L; private final String baseTaskId; private final int index; private final Object arg; private final Class<N> node; private final PipeType type; private transient boolean executed; public NodeTask(PipeType type, Class<N>node, String baseTaskId, int index, Object arg) { this.type = type; this.node = node; this.baseTaskId = baseTaskId; this.index = index; this.arg = arg; } public void run() { NodeResult result = NodeResult.END_RESULT; Throwable t = null; try { Object a = arg; if(arg instanceof StashedArgument){ a = Pipes.getRunner().getPipeDatastore().retrieveArgument(((StashedArgument)arg).getKey()); } if(Pipes.getRunner().getPipeDatastore().isActive(baseTaskId)){ log.info("Executing: id=" + baseTaskId + ", index=" + index); result = type.execute(createTaskInstance(), a, index); executed = true; } else { log.info("Skipping due inactivity: id=" + baseTaskId + ", index=" + index); return; } } catch(Throwable th){ DeferredTaskContext.setDoNotRetry(true); t = th; } if(result == null || !result.hasNext()){ type.handlePipeEnd(Pipes.getRunner(), Pipes.getQueueName(node), baseTaskId, index, result); return; } log.info("Handle Next: id=" + baseTaskId + ", index=" + index + ", result= " + result); type.handleNext(Pipes.getRunner(), Pipes.getQueueName(node), baseTaskId, index, result); if(t != null){ throw new RuntimeException("Exception during running task.", t); } } private N createTaskInstance() { try { return node.newInstance(); } catch (InstantiationException e) { throw new IllegalStateException("Cannot initiate instance " + node.getName() + " does it have parameterless constructor?"); } catch (IllegalAccessException e) { throw new IllegalStateException("Cannot initiate instance " + node.getName() + " does it have parameterless constructor?"); } } public String getBaseTaskId() { return baseTaskId; } public boolean isExecuted() { return executed; } @Override public String toString() { return (executed ? "Executed " : "") + (index + 1) + " of " + PipeType.sizeOf(arg) + " " + node.getSimpleName() + " (" + type + ") with parameter '" + PipeType.getAt(index, arg) + "' and base name '" + baseTaskId + "'"; } }