public void open(ExecutionContext executionContext) throws ItemStreamException { if (executionContext.containsKey(EXPECTED)) { localState.expected = executionContext.getLong(EXPECTED); localState.actual = executionContext.getLong(ACTUAL); if (!waitForResults()) { throw new ItemStreamException("Timed out waiting for back log on open"); } } }
/** * Wait until all the results that are in the pipeline come back to the reply channel. * * @return true if successfully received a result, false if timed out */ private boolean waitForResults() { int count = 0; int maxCount = maxWaitTimeouts; while (localState.getExpecting() > 0 && count++ < maxCount) { long expecting = localState.getExpecting(); getNextResult(); if (expecting == localState.getExpecting()) { try { Thread.sleep(100); } catch (InterruptedException e) { throw new RuntimeException(e); } } } return count < maxCount; }
public void write(List<? extends T> items) throws Exception { // Block until expecting <= throttle limit while (localState.getExpecting() > throttleLimit) { getNextResult(); } if (!items.isEmpty()) { logger.debug("Dispatching chunk: " + items); ChunkRequest<T> request = new ChunkRequest<T>(items, localState.getJobId(), localState.createStepContribution()); // Create & launch task ChunkTask<T> task = new ChunkTask<T>(); task.setProcessor(chunkProcessor); GridTaskFuture<ChunkResponse> future = grid.<ChunkRequest<T>, ChunkResponse>execute(task, request); futures.add(future); localState.expected++; } }
/** * Get the next result if it is available (within the timeout specified in the gateway), otherwise * do nothing. * * @throws AsynchronousFailureException If there is a response and it contains a failed chunk * response. * @throws IllegalStateException if the result contains the wrong job instance id (maybe we are * sharing a channel and we shouldn't be) */ private void getNextResult() { ChunkResponse payload = null; // Retrieve first finished task found Iterator<GridTaskFuture<ChunkResponse>> iterator = futures.iterator(); while (iterator.hasNext()) { GridTaskFuture<ChunkResponse> future = iterator.next(); if (future.isDone()) { try { payload = future.get(); } catch (GridException e) { throw new AsynchronousFailureException( "Exception occured during GridGain task execution: " + e); } iterator.remove(); break; } } if (payload != null) { Long jobInstanceId = payload.getJobId(); Assert.state(jobInstanceId != null, "Message did not contain job instance id."); Assert.state( jobInstanceId.equals(localState.getJobId()), "Message contained wrong job instance id [" + jobInstanceId + "] should have been [" + localState.getJobId() + "]."); localState.actual++; // TODO: apply the skip count if (!payload.isSuccessful()) { throw new AsynchronousFailureException( "Failure or interrupt detected in handler: " + payload.getMessage()); } } }
@Override public ExitStatus afterStep(StepExecution stepExecution) { if (!(stepExecution.getStatus() == BatchStatus.COMPLETED)) { return ExitStatus.EXECUTING; } long expecting = localState.getExpecting(); boolean timedOut; try { logger.debug("Waiting for results in step listener..."); timedOut = !waitForResults(); logger.debug("Finished waiting for results in step listener."); } catch (RuntimeException e) { logger.debug("Detected failure waiting for results in step listener.", e); stepExecution.setStatus(BatchStatus.FAILED); return ExitStatus.FAILED.addExitDescription(e.getClass().getName() + ": " + e.getMessage()); } if (timedOut) { stepExecution.setStatus(BatchStatus.FAILED); throw new ItemStreamException("Timed out waiting for back log at end of step"); } return ExitStatus.COMPLETED.addExitDescription("Waited for " + expecting + " results."); }
@Override public void beforeStep(StepExecution stepExecution) { localState.setStepExecution(stepExecution); futures = new ArrayList<GridTaskFuture<ChunkResponse>>(); }
public void close() throws ItemStreamException { localState.reset(); }