@Test public void testUpdateWithNoStream() throws Exception { monitor = new ChunkMonitor(); monitor.setItemReader(new ItemReader<String>() { @Override public String read() throws Exception, UnexpectedInputException, ParseException { return "" + (count++); } }); monitor.setChunkSize(CHUNK_SIZE); monitor.incrementOffset(); ExecutionContext executionContext = new ExecutionContext(); monitor.update(executionContext); assertEquals(0, executionContext.size()); } }
@Before public void setUp() { monitor.setItemReader(new ItemReader<String>() { @Override public String read() throws Exception, UnexpectedInputException, ParseException { return "" + (count++); } }); monitor.registerItemStream(new ItemStreamSupport() { @Override public void close() { super.close(); closed = true; } }); monitor.setChunkSize(CHUNK_SIZE); }
public void incrementOffset() { ChunkMonitorData data = getData(); data.offset ++; if (data.offset >= data.chunkSize) { resetOffset(); } }
@Override public void update(ExecutionContext executionContext) throws ItemStreamException { super.update(executionContext); if (streamsRegistered) { ChunkMonitorData data = getData(); if (data.offset == 0) { // Only call the underlying update method if we are on a chunk // boundary stream.update(executionContext); executionContext.remove(getExecutionContextKey(OFFSET)); } else { executionContext.putInt(getExecutionContextKey(OFFSET), data.offset); } } }
data.scanning(false); inputs.setBusy(false); chunkMonitor.resetOffset(); return; chunkMonitor.incrementOffset(); if (outputs.isEmpty()) { data.scanning(false); inputs.setBusy(false); chunkMonitor.resetOffset();
@Override public void open(ExecutionContext executionContext) throws ItemStreamException { super.open(executionContext); if (streamsRegistered) { stream.open(executionContext); ChunkMonitorData data = new ChunkMonitorData(executionContext.getInt(getExecutionContextKey(OFFSET), 0), 0); holder.set(data); if (reader == null) { logger.warn("No ItemReader set (must be concurrent step), so ignoring offset data."); return; } for (int i = 0; i < data.offset; i++) { try { reader.read(); } catch (Exception e) { throw new ItemStreamException("Could not position reader with offset: " + data.offset, e); } } resetOffset(); } }
@Override public Object doWithRetry(RetryContext context) throws Exception { contextHolder.set(context); if (!data.scanning()) { chunkMonitor.setChunkSize(inputs.size()); try { doWrite(outputs.getItems()); } catch (Exception e) { if (rollbackClassifier.classify(e)) { throw e; } /* * If the exception is marked as no-rollback, we need to * override that, otherwise there's no way to write the * rest of the chunk or to honour the skip listener * contract. */ throw new ForceRollbackForWriteSkipException( "Force rollback on skippable exception so that skipped item can be located.", e); } contribution.incrementWriteCount(outputs.size()); } else { scan(contribution, inputs, outputs, chunkMonitor, false); } return null; } };
@Test public void testResetOffsetManually() { monitor.incrementOffset(); monitor.resetOffset(); assertEquals(0, monitor.getOffset()); }
public void resetOffset() { getData().offset = 0; }
protected void detectStreamInReader() { if (streamIsReader) { if (!concurrent()) { chunkMonitor.setItemReader(getReader()); } else { logger.warn("Asynchronous TaskExecutor detected with ItemStream reader. This is probably an error, " + "and may lead to incorrect restart data being stored."); } } }
@Override public AbstractTaskletStepBuilder<SimpleStepBuilder<I, O>> stream(ItemStream stream) { if (stream instanceof ItemReader<?>) { if (!streamIsReader) { streamIsReader = true; super.stream(chunkMonitor); } // In cases where multiple nested item readers are registered, // they all want to get the open() and close() callbacks. chunkMonitor.registerItemStream(stream); } else { super.stream(stream); } return this; }
if (stream instanceof ItemReader<?>) { streamIsReader = true; chunkMonitor.registerItemStream(stream); boolean concurrent = taskExecutor != null && !(taskExecutor instanceof SyncTaskExecutor); if (!concurrent) { chunkMonitor.setItemReader(itemReader);
@Test public void testOpenWithNullReader() { monitor.setItemReader(null); ExecutionContext executionContext = new ExecutionContext(); monitor.open(executionContext); assertEquals(0, monitor.getOffset()); }
@Test public void testClose() { monitor.incrementOffset(); monitor.close(); assertTrue(closed); assertEquals(0, monitor.getOffset()); }
@Test public void testIncrementOffset() { assertEquals(0, monitor.getOffset()); monitor.incrementOffset(); assertEquals(1, monitor.getOffset()); }
@Test(expected = ItemStreamException.class) public void testOpenWithErrorInReader() { monitor.setItemReader(new ItemReader<String>() { @Override public String read() throws Exception, UnexpectedInputException, ParseException { throw new IllegalStateException("Expected"); } }); ExecutionContext executionContext = new ExecutionContext(); executionContext.putInt(ChunkMonitor.class.getName() + ".OFFSET", 2); monitor.open(executionContext); }
@Test public void testUpdateVanilla() { monitor.incrementOffset(); ExecutionContext executionContext = new ExecutionContext(); monitor.update(executionContext); assertEquals(1, executionContext.size()); }
@Test public void testUpdateOnBoundary() { monitor.resetOffset(); ExecutionContext executionContext = new ExecutionContext(); monitor.update(executionContext); assertEquals(0, executionContext.size()); executionContext.put(ChunkMonitor.class.getName() + ".OFFSET", 3); monitor.update(executionContext); assertEquals(0, executionContext.size()); }
public ChunkMonitor() { this.setExecutionContextName(ChunkMonitor.class.getName()); }
data.scanning(false); inputs.setBusy(false); chunkMonitor.resetOffset(); return; chunkMonitor.incrementOffset(); if (outputs.isEmpty()) { data.scanning(false); inputs.setBusy(false); chunkMonitor.resetOffset();