RESOLVED - issue BATCH-1278: RepeatTemplate aborts early if multiple threads throw ignorable exceptions
Tweak solution to handle repeat context properly in nested threads
This commit is contained in:
@@ -16,15 +16,15 @@
|
||||
|
||||
package org.springframework.batch.repeat.callback;
|
||||
|
||||
import org.springframework.batch.repeat.RepeatStatus;
|
||||
import org.springframework.batch.repeat.RepeatCallback;
|
||||
import org.springframework.batch.repeat.RepeatContext;
|
||||
import org.springframework.batch.repeat.RepeatOperations;
|
||||
import org.springframework.batch.repeat.RepeatStatus;
|
||||
|
||||
/**
|
||||
* Callback that delegates to another callback, via a {@link RepeatOperations} instance.
|
||||
* Useful when nesting or composing batches in one another, e.g. for breaking a
|
||||
* batch down into chunks.
|
||||
* Callback that delegates to another callback, via a {@link RepeatOperations}
|
||||
* instance. Useful when nesting or composing batches in one another, e.g. for
|
||||
* breaking a batch down into chunks.
|
||||
*
|
||||
* @author Dave Syer
|
||||
*
|
||||
@@ -38,8 +38,8 @@ public class NestedRepeatCallback implements RepeatCallback {
|
||||
/**
|
||||
* Constructor setting mandatory fields.
|
||||
*
|
||||
* @param template the {@link RepeatOperations} to use when calling the delegate
|
||||
* callback
|
||||
* @param template the {@link RepeatOperations} to use when calling the
|
||||
* delegate callback
|
||||
* @param callback the {@link RepeatCallback} delegate
|
||||
*/
|
||||
public NestedRepeatCallback(RepeatOperations template, RepeatCallback callback) {
|
||||
|
||||
@@ -51,7 +51,8 @@ public class TaskExecutorRepeatTemplate extends RepeatTemplate {
|
||||
/**
|
||||
* Default limit for maximum number of concurrent unfinished results allowed
|
||||
* by the template.
|
||||
* {@link #getNextResult(RepeatContext, RepeatCallback, RepeatInternalState)}.
|
||||
* {@link #getNextResult(RepeatContext, RepeatCallback, RepeatInternalState)}
|
||||
* .
|
||||
*/
|
||||
public static final int DEFAULT_THROTTLE_LIMIT = 4;
|
||||
|
||||
@@ -71,10 +72,10 @@ public class TaskExecutorRepeatTemplate extends RepeatTemplate {
|
||||
}
|
||||
|
||||
/**
|
||||
* Use the {@link #setTaskExecutor(TaskExecutor)} to generate a result. The internal state in
|
||||
* this case is a queue of unfinished result holders of type
|
||||
* {@link ResultHolder}. The holder with the return value should not be on
|
||||
* the queue when this method exits. The queue is scoped in the calling
|
||||
* Use the {@link #setTaskExecutor(TaskExecutor)} to generate a result. The
|
||||
* internal state in this case is a queue of unfinished result holders of
|
||||
* type {@link ResultHolder}. The holder with the return value should not be
|
||||
* on the queue when this method exits. The queue is scoped in the calling
|
||||
* method so there is no need to synchronize access.
|
||||
*
|
||||
*/
|
||||
@@ -185,7 +186,7 @@ public class TaskExecutorRepeatTemplate extends RepeatTemplate {
|
||||
*
|
||||
*/
|
||||
private static class ExecutingRunnable implements Runnable, ResultHolder {
|
||||
|
||||
|
||||
private final RepeatCallback callback;
|
||||
|
||||
private final RepeatContext context;
|
||||
@@ -226,13 +227,21 @@ public class TaskExecutorRepeatTemplate extends RepeatTemplate {
|
||||
* @see java.lang.Runnable#run()
|
||||
*/
|
||||
public void run() {
|
||||
boolean clearContext = false;
|
||||
try {
|
||||
if (RepeatSynchronizationManager.getContext() == null) {
|
||||
clearContext = true;
|
||||
RepeatSynchronizationManager.register(context);
|
||||
}
|
||||
result = callback.doInIteration(context);
|
||||
}
|
||||
catch (Exception e) {
|
||||
error = e;
|
||||
}
|
||||
finally {
|
||||
if (clearContext) {
|
||||
RepeatSynchronizationManager.clear();
|
||||
}
|
||||
queue.put(this);
|
||||
}
|
||||
}
|
||||
@@ -264,12 +273,12 @@ public class TaskExecutorRepeatTemplate extends RepeatTemplate {
|
||||
|
||||
/**
|
||||
* @author Dave Syer
|
||||
*
|
||||
*
|
||||
*/
|
||||
private static class ResultQueueInternalState extends RepeatInternalStateSupport {
|
||||
|
||||
private final ResultQueue<ResultHolder> results;
|
||||
|
||||
|
||||
/**
|
||||
* @param throttleLimit the throttle limit for the result queue
|
||||
*/
|
||||
@@ -277,8 +286,12 @@ public class TaskExecutorRepeatTemplate extends RepeatTemplate {
|
||||
super();
|
||||
this.results = new ThrottleLimitResultQueue<ResultHolder>(throttleLimit);
|
||||
}
|
||||
/* (non-Javadoc)
|
||||
* @see org.springframework.batch.repeat.support.RepeatInternalState#getResultQueue()
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @seeorg.springframework.batch.repeat.support.RepeatInternalState#
|
||||
* getResultQueue()
|
||||
*/
|
||||
public ResultQueue<ResultHolder> getResultQueue() {
|
||||
return results;
|
||||
|
||||
Reference in New Issue
Block a user