forked from dexecutor/dexecutor-core
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Showing
15 changed files
with
669 additions
and
193 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
362 changes: 188 additions & 174 deletions
362
src/main/java/com/github/dexecutor/core/DexecutorConfig.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,174 +1,188 @@ | ||
/* | ||
* Licensed to the Apache Software Foundation (ASF) under one or more | ||
* contributor license agreements. See the NOTICE file distributed with | ||
* this work for additional information regarding copyright ownership. | ||
* The ASF licenses this file to You 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 com.github.dexecutor.core; | ||
|
||
import static com.github.dexecutor.core.support.Preconditions.checkNotNull; | ||
|
||
import java.util.concurrent.ExecutorService; | ||
|
||
import com.github.dexecutor.core.graph.CyclicValidator; | ||
import com.github.dexecutor.core.graph.Validator; | ||
import com.github.dexecutor.core.task.TaskProvider; | ||
|
||
/** | ||
* <p>Configuration Object for Dexecutor framework. At a minimum it needs {@code ExecutorService} and {@code TaskProvider}, rest are optional and takes default values</p> | ||
* <p>This provides way to hook in your own {@code DexecutorState} and {@code Validator} </p> | ||
* | ||
* @author Nadeem Mohammad | ||
* | ||
* @param <T> Type of Node/Task ID | ||
* @param <R> Type of Node/Task result | ||
*/ | ||
public class DexecutorConfig<T, R> { | ||
|
||
/** | ||
* Number of threads that should handle the immediate retry. | ||
*/ | ||
private int immediateRetryPoolThreadsCount = 1; | ||
|
||
/** | ||
* Number of threads that should handle the immediate retry. | ||
*/ | ||
private int scheduledRetryPoolThreadsCount = 1; | ||
|
||
/** | ||
* executor is the main platform on which tasks are executed | ||
*/ | ||
private ExecutionEngine<T, R> executionEngine; | ||
|
||
/** | ||
* When it comes to task execution, task provider would be consulted to provide task objects for execution | ||
*/ | ||
private TaskProvider<T, R> taskProvider; | ||
/** | ||
* Validator for validating the constructed graph, defaults to detecting Cyclic checks | ||
*/ | ||
private Validator<T, R> validator = new CyclicValidator<T, R>(); | ||
|
||
private DexecutorState<T, R> dexecutorState = new DefaultDexecutorState<T, R>(); | ||
|
||
/** | ||
* Construct the object with mandatory params, rest are optional | ||
* @param executorService provided executor service | ||
* @param taskProvider provided task provider | ||
*/ | ||
public DexecutorConfig(final ExecutorService executorService, final TaskProvider<T, R> taskProvider) { | ||
this(executorService, taskProvider, null); | ||
} | ||
|
||
public DexecutorConfig(final ExecutorService executorService, final TaskProvider<T, R> taskProvider, final ExecutionListener<T, R> listener) { | ||
checkNotNull(executorService, "Executer Service should not be null"); | ||
checkNotNull(taskProvider, "Task Provider should not be null"); | ||
this.executionEngine = new DefaultExecutionEngine<>(this.dexecutorState, executorService, listener); | ||
this.taskProvider = taskProvider; | ||
} | ||
|
||
/** | ||
* Construct the object with mandatory params, rest are optional | ||
* @param executionEngine provided execution Engine | ||
* @param taskProvider provided task provider | ||
*/ | ||
public DexecutorConfig(final ExecutionEngine<T, R> executionEngine, final TaskProvider<T, R> taskProvider) { | ||
this(new DefaultDexecutorState<>(), executionEngine, taskProvider); | ||
} | ||
|
||
public DexecutorConfig(final DexecutorState<T, R> dexecutorState, final ExecutionEngine<T, R> executionEngine, final TaskProvider<T, R> taskProvider) { | ||
checkNotNull(executionEngine, "Execution Engine should not be null"); | ||
checkNotNull(taskProvider, "Task Provider should not be null"); | ||
checkNotNull(dexecutorState, "Dexecutor State should not be null"); | ||
this.executionEngine = executionEngine; | ||
this.taskProvider = taskProvider; | ||
this.dexecutorState = dexecutorState; | ||
} | ||
|
||
void validate() { | ||
checkNotNull(this.executionEngine, "Execution Engine should not be null"); | ||
checkNotNull(this.taskProvider, "Task Provider should not be null"); | ||
checkNotNull(this.validator, "Validator should not be null"); | ||
checkNotNull(this.dexecutorState, "Dexecutor State should not be null"); | ||
} | ||
|
||
ExecutionEngine<T, R> getExecutorEngine() { | ||
return this.executionEngine; | ||
} | ||
|
||
TaskProvider<T, R> getTaskProvider() { | ||
return this.taskProvider; | ||
} | ||
|
||
Validator<T, R> getValidator() { | ||
return this.validator; | ||
} | ||
/** | ||
* change the validator to that of specified | ||
* @param validator the validator | ||
*/ | ||
public void setValidator(final Validator<T, R> validator) { | ||
this.validator = validator; | ||
} | ||
|
||
/** | ||
* | ||
* @return the immediate retry thread pool count | ||
*/ | ||
public int getImmediateRetryPoolThreadsCount() { | ||
return immediateRetryPoolThreadsCount; | ||
} | ||
/** | ||
* sets the immediate retry thread pool size to that of specified | ||
* @param immediateRetryPoolThreadsCount Number of threads that should process retry immediately | ||
*/ | ||
public void setImmediateRetryPoolThreadsCount(int immediateRetryPoolThreadsCount) { | ||
this.immediateRetryPoolThreadsCount = immediateRetryPoolThreadsCount; | ||
} | ||
/** | ||
* | ||
* @return the scheduled retry thread pool size | ||
*/ | ||
public int getScheduledRetryPoolThreadsCount() { | ||
return scheduledRetryPoolThreadsCount; | ||
} | ||
/** | ||
* sets the scheduled thread pool size to that of specified | ||
* @param scheduledRetryPoolThreadsCount Number of threads that should process retry immediately | ||
*/ | ||
public void setScheduledRetryPoolThreadsCount(int scheduledRetryPoolThreadsCount) { | ||
this.scheduledRetryPoolThreadsCount = scheduledRetryPoolThreadsCount; | ||
} | ||
/** | ||
* | ||
* @return the dexecutor state | ||
*/ | ||
public DexecutorState<T, R> getDexecutorState() { | ||
return this.dexecutorState; | ||
} | ||
|
||
/** | ||
* | ||
* @param dexecutorState to set to | ||
*/ | ||
public void setDexecutorState(final DexecutorState<T, R> dexecutorState) { | ||
this.dexecutorState = dexecutorState; | ||
} | ||
|
||
public void setExecutionListener(ExecutionListener<T, R> listener) { | ||
if (listener != null) { | ||
this.executionEngine.setExecutionListener(listener); | ||
} | ||
} | ||
} | ||
/* | ||
* Licensed to the Apache Software Foundation (ASF) under one or more | ||
* contributor license agreements. See the NOTICE file distributed with | ||
* this work for additional information regarding copyright ownership. | ||
* The ASF licenses this file to You 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 com.github.dexecutor.core; | ||
|
||
import static com.github.dexecutor.core.support.Preconditions.checkNotNull; | ||
|
||
import java.util.concurrent.ExecutorService; | ||
|
||
import com.github.dexecutor.core.graph.CyclicValidator; | ||
import com.github.dexecutor.core.graph.Validator; | ||
import com.github.dexecutor.core.task.TaskProvider; | ||
|
||
/** | ||
* <p>Configuration Object for Dexecutor framework. At a minimum it needs {@code ExecutorService} and {@code TaskProvider}, rest are optional and takes default values</p> | ||
* <p>This provides way to hook in your own {@code DexecutorState} and {@code Validator} </p> | ||
* | ||
* @author Nadeem Mohammad | ||
* | ||
* @param <T> Type of Node/Task ID | ||
* @param <R> Type of Node/Task result | ||
*/ | ||
public class DexecutorConfig<T, R> { | ||
|
||
/** | ||
* Number of threads that should handle the immediate retry. | ||
*/ | ||
private int immediateRetryPoolThreadsCount = 1; | ||
|
||
/** | ||
* Number of threads that should handle the immediate retry. | ||
*/ | ||
private int scheduledRetryPoolThreadsCount = 1; | ||
|
||
/** | ||
* Number of threads that should handle the timeout scheduler. | ||
*/ | ||
private int timeoutSchedulerPoolThreadsCount = 2; | ||
|
||
/** | ||
* executor is the main platform on which tasks are executed | ||
*/ | ||
private ExecutionEngine<T, R> executionEngine; | ||
|
||
/** | ||
* When it comes to task execution, task provider would be consulted to provide task objects for execution | ||
*/ | ||
private TaskProvider<T, R> taskProvider; | ||
/** | ||
* Validator for validating the constructed graph, defaults to detecting Cyclic checks | ||
*/ | ||
private Validator<T, R> validator = new CyclicValidator<T, R>(); | ||
|
||
private DexecutorState<T, R> dexecutorState = new DefaultDexecutorState<T, R>(); | ||
|
||
/** | ||
* Construct the object with mandatory params, rest are optional | ||
* @param executorService provided executor service | ||
* @param taskProvider provided task provider | ||
*/ | ||
public DexecutorConfig(final ExecutorService executorService, final TaskProvider<T, R> taskProvider) { | ||
this(executorService, taskProvider, null); | ||
} | ||
|
||
public DexecutorConfig(final ExecutorService executorService, final TaskProvider<T, R> taskProvider, final ExecutionListener<T, R> listener) { | ||
checkNotNull(executorService, "Executer Service should not be null"); | ||
checkNotNull(taskProvider, "Task Provider should not be null"); | ||
this.executionEngine = new DefaultExecutionEngine<>(this.dexecutorState, executorService, listener); | ||
this.taskProvider = taskProvider; | ||
} | ||
|
||
/** | ||
* Construct the object with mandatory params, rest are optional | ||
* @param executionEngine provided execution Engine | ||
* @param taskProvider provided task provider | ||
*/ | ||
public DexecutorConfig(final ExecutionEngine<T, R> executionEngine, final TaskProvider<T, R> taskProvider) { | ||
this(new DefaultDexecutorState<>(), executionEngine, taskProvider); | ||
} | ||
|
||
public DexecutorConfig(final DexecutorState<T, R> dexecutorState, final ExecutionEngine<T, R> executionEngine, final TaskProvider<T, R> taskProvider) { | ||
checkNotNull(executionEngine, "Execution Engine should not be null"); | ||
checkNotNull(taskProvider, "Task Provider should not be null"); | ||
checkNotNull(dexecutorState, "Dexecutor State should not be null"); | ||
this.executionEngine = executionEngine; | ||
this.taskProvider = taskProvider; | ||
this.dexecutorState = dexecutorState; | ||
} | ||
|
||
void validate() { | ||
checkNotNull(this.executionEngine, "Execution Engine should not be null"); | ||
checkNotNull(this.taskProvider, "Task Provider should not be null"); | ||
checkNotNull(this.validator, "Validator should not be null"); | ||
checkNotNull(this.dexecutorState, "Dexecutor State should not be null"); | ||
} | ||
|
||
ExecutionEngine<T, R> getExecutorEngine() { | ||
return this.executionEngine; | ||
} | ||
|
||
TaskProvider<T, R> getTaskProvider() { | ||
return this.taskProvider; | ||
} | ||
|
||
Validator<T, R> getValidator() { | ||
return this.validator; | ||
} | ||
/** | ||
* change the validator to that of specified | ||
* @param validator the validator | ||
*/ | ||
public void setValidator(final Validator<T, R> validator) { | ||
this.validator = validator; | ||
} | ||
|
||
/** | ||
* | ||
* @return the immediate retry thread pool count | ||
*/ | ||
public int getImmediateRetryPoolThreadsCount() { | ||
return immediateRetryPoolThreadsCount; | ||
} | ||
/** | ||
* sets the immediate retry thread pool size to that of specified | ||
* @param immediateRetryPoolThreadsCount Number of threads that should process retry immediately | ||
*/ | ||
public void setImmediateRetryPoolThreadsCount(int immediateRetryPoolThreadsCount) { | ||
this.immediateRetryPoolThreadsCount = immediateRetryPoolThreadsCount; | ||
} | ||
/** | ||
* | ||
* @return the scheduled retry thread pool size | ||
*/ | ||
public int getScheduledRetryPoolThreadsCount() { | ||
return scheduledRetryPoolThreadsCount; | ||
} | ||
/** | ||
* sets the scheduled thread pool size to that of specified | ||
* @param scheduledRetryPoolThreadsCount Number of threads that should process retry immediately | ||
*/ | ||
public void setScheduledRetryPoolThreadsCount(int scheduledRetryPoolThreadsCount) { | ||
this.scheduledRetryPoolThreadsCount = scheduledRetryPoolThreadsCount; | ||
} | ||
|
||
public int getTimeoutSchedulerPoolThreadsCount() { | ||
return timeoutSchedulerPoolThreadsCount; | ||
} | ||
|
||
public void setTimeoutSchedulerPoolThreadsCount(int timeoutSchedulerPoolThreadsCount) { | ||
this.timeoutSchedulerPoolThreadsCount = timeoutSchedulerPoolThreadsCount; | ||
} | ||
|
||
/** | ||
* | ||
* @return the dexecutor state | ||
*/ | ||
public DexecutorState<T, R> getDexecutorState() { | ||
return this.dexecutorState; | ||
} | ||
|
||
/** | ||
* | ||
* @param dexecutorState to set to | ||
*/ | ||
public void setDexecutorState(final DexecutorState<T, R> dexecutorState) { | ||
this.dexecutorState = dexecutorState; | ||
} | ||
|
||
public void setExecutionListener(ExecutionListener<T, R> listener) { | ||
if (listener != null) { | ||
this.executionEngine.setExecutionListener(listener); | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
8 changes: 8 additions & 0 deletions
8
src/main/java/com/github/dexecutor/core/IdentifiableCallable.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,8 @@ | ||
package com.github.dexecutor.core; | ||
|
||
import java.util.concurrent.Callable; | ||
|
||
public interface IdentifiableCallable<T, V> extends Callable<V>{ | ||
|
||
T getIdentifier(); | ||
} |
107 changes: 107 additions & 0 deletions
107
src/main/java/com/github/dexecutor/core/concurrent/ExecutorCompletionService.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,107 @@ | ||
package com.github.dexecutor.core.concurrent; | ||
|
||
import java.util.concurrent.BlockingQueue; | ||
import java.util.concurrent.Callable; | ||
import java.util.concurrent.CompletionService; | ||
import java.util.concurrent.Executor; | ||
import java.util.concurrent.Future; | ||
import java.util.concurrent.FutureTask; | ||
import java.util.concurrent.LinkedBlockingQueue; | ||
import java.util.concurrent.RunnableFuture; | ||
import java.util.concurrent.TimeUnit; | ||
|
||
import com.github.dexecutor.core.IdentifiableCallable; | ||
|
||
public class ExecutorCompletionService<T, V> implements CompletionService<V> { | ||
private final Executor executor; | ||
private final BlockingQueue<Future<V>> completionQueue; | ||
|
||
/** | ||
* FutureTask extension to enqueue upon completion | ||
*/ | ||
private class QueueingFuture extends FutureTask<Void> { | ||
QueueingFuture(RunnableFuture<V> task) { | ||
super(task, null); | ||
this.task = task; | ||
} | ||
protected void done() { completionQueue.add(task); } | ||
private final Future<V> task; | ||
} | ||
|
||
/** | ||
* Creates an ExecutorCompletionService using the supplied | ||
* executor for base task execution and a | ||
* {@link LinkedBlockingQueue} as a completion queue. | ||
* | ||
* @param executor the executor to use | ||
* @throws NullPointerException if executor is {@code null} | ||
*/ | ||
public ExecutorCompletionService(Executor executor) { | ||
if (executor == null) | ||
throw new NullPointerException(); | ||
this.executor = executor; | ||
this.completionQueue = new LinkedBlockingQueue<Future<V>>(); | ||
} | ||
|
||
/** | ||
* Creates an ExecutorCompletionService using the supplied | ||
* executor for base task execution and the supplied queue as its | ||
* completion queue. | ||
* | ||
* @param executor the executor to use | ||
* @param completionQueue the queue to use as the completion queue | ||
* normally one dedicated for use by this service. This | ||
* queue is treated as unbounded -- failed attempted | ||
* {@code Queue.add} operations for completed tasks cause | ||
* them not to be retrievable. | ||
* @throws NullPointerException if executor or completionQueue are {@code null} | ||
*/ | ||
public ExecutorCompletionService(Executor executor, | ||
BlockingQueue<Future<V>> completionQueue) { | ||
if (executor == null || completionQueue == null) | ||
throw new NullPointerException(); | ||
this.executor = executor; | ||
this.completionQueue = completionQueue; | ||
} | ||
|
||
public Future<V> submit(Callable<V> task) { | ||
if (task == null) throw new NullPointerException(); | ||
RunnableFuture<V> f = newTaskFor(task); | ||
executor.execute(new QueueingFuture(f)); | ||
return f; | ||
} | ||
|
||
public Future<V> submit(Runnable task, V result) { | ||
if (task == null) throw new NullPointerException(); | ||
RunnableFuture<V> f = newTaskFor(task, result); | ||
executor.execute(new QueueingFuture(f)); | ||
return f; | ||
} | ||
|
||
private RunnableFuture<V> newTaskFor(Callable<V> task) { | ||
|
||
@SuppressWarnings("unchecked") | ||
IdentifiableCallable<T, V> callable = (IdentifiableCallable<T, V>) task; | ||
|
||
return new IdentifiableRunnableFuture<T, V>(callable.getIdentifier(), callable); | ||
} | ||
|
||
private RunnableFuture<V> newTaskFor(Runnable task, V result) { | ||
@SuppressWarnings("unchecked") | ||
IdentifiableCallable<T, V> callable = (IdentifiableCallable<T, V>) task; | ||
return new IdentifiableRunnableFuture<T, V>(callable.getIdentifier(), task, result); | ||
} | ||
|
||
public Future<V> take() throws InterruptedException { | ||
return completionQueue.take(); | ||
} | ||
|
||
public Future<V> poll() { | ||
return completionQueue.poll(); | ||
} | ||
|
||
public Future<V> poll(long timeout, TimeUnit unit) | ||
throws InterruptedException { | ||
return completionQueue.poll(timeout, unit); | ||
} | ||
} |
23 changes: 23 additions & 0 deletions
23
src/main/java/com/github/dexecutor/core/concurrent/IdentifiableRunnableFuture.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,23 @@ | ||
package com.github.dexecutor.core.concurrent; | ||
|
||
import java.util.concurrent.Callable; | ||
import java.util.concurrent.FutureTask; | ||
|
||
public class IdentifiableRunnableFuture<T, V> extends FutureTask<V> { | ||
|
||
private T identifier; | ||
|
||
public IdentifiableRunnableFuture(T identifier, Callable<V> callable) { | ||
super(callable); | ||
this.identifier = identifier; | ||
} | ||
|
||
public IdentifiableRunnableFuture(T identifier, Runnable runnable, V result) { | ||
super(runnable, result); | ||
this.identifier = identifier; | ||
} | ||
|
||
public T getIdentifier() { | ||
return identifier; | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
136 changes: 136 additions & 0 deletions
136
src/test/java/com/github/dexecutor/core/DexecutorTimeoutTest.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,136 @@ | ||
/* | ||
* Licensed to the Apache Software Foundation (ASF) under one or more | ||
* contributor license agreements. See the NOTICE file distributed with | ||
* this work for additional information regarding copyright ownership. | ||
* The ASF licenses this file to You 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 com.github.dexecutor.core; | ||
|
||
import static org.assertj.core.api.Assertions.assertThat; | ||
|
||
import java.time.Duration; | ||
import java.util.ArrayList; | ||
import java.util.Collection; | ||
import java.util.List; | ||
import java.util.concurrent.ExecutorService; | ||
import java.util.concurrent.Executors; | ||
import java.util.concurrent.TimeUnit; | ||
|
||
import org.junit.Test; | ||
import org.slf4j.Logger; | ||
import org.slf4j.LoggerFactory; | ||
|
||
import com.github.dexecutor.core.graph.Node; | ||
import com.github.dexecutor.core.support.TestUtil; | ||
import com.github.dexecutor.core.task.ExecutionResults; | ||
import com.github.dexecutor.core.task.Task; | ||
import com.github.dexecutor.core.task.TaskProvider; | ||
|
||
/** | ||
* | ||
* @author Nadeem Mohammad | ||
* | ||
*/ | ||
public class DexecutorTimeoutTest { | ||
|
||
private static final Logger logger = LoggerFactory.getLogger(DexecutorTimeoutTest.class); | ||
|
||
@Test | ||
public void testDependentTaskExecution() { | ||
ExecutorService executorService = newExecutor(); | ||
|
||
try { | ||
DexecutorConfig<Integer, Integer> config = new DexecutorConfig<>(executorService, new SleepyTaskProvider()); | ||
DefaultDexecutor<Integer, Integer> executor = new DefaultDexecutor<Integer, Integer>(config); | ||
executor.addDependency(1, 2); | ||
executor.addDependency(1, 2); | ||
executor.addDependency(1, 3); | ||
executor.addDependency(3, 4); | ||
executor.addDependency(3, 5); | ||
executor.addDependency(3, 6); | ||
executor.addDependency(2, 7); | ||
executor.addDependency(2, 9); | ||
executor.addDependency(2, 8); | ||
executor.addDependency(9, 10); | ||
executor.addDependency(12, 13); | ||
executor.addDependency(13, 4); | ||
executor.addDependency(13, 14); | ||
executor.addIndependent(11); | ||
|
||
ExecutionResults<Integer, Integer> result = executor.execute(ExecutionConfig.TERMINATING); | ||
System.out.println(result); | ||
|
||
Collection<Node<Integer, Integer>> processedNodesOrder = TestUtil.processedNodesOrder(executor); | ||
assertThat(processedNodesOrder).containsAll(executionOrderExpectedResult()); | ||
assertThat(processedNodesOrder).size().isGreaterThanOrEqualTo(4); | ||
|
||
} finally { | ||
try { | ||
executorService.shutdownNow(); | ||
executorService.awaitTermination(1, TimeUnit.SECONDS); | ||
} catch (InterruptedException e) { | ||
|
||
} | ||
} | ||
} | ||
|
||
private Collection<Node<Integer, Integer>> executionOrderExpectedResult() { | ||
List<Node<Integer, Integer>> result = new ArrayList<Node<Integer, Integer>>(); | ||
result.add(new Node<Integer, Integer>(1)); | ||
//result.add(new Node<Integer, Integer>(2)); | ||
result.add(new Node<Integer, Integer>(11)); | ||
result.add(new Node<Integer, Integer>(12)); | ||
return result; | ||
} | ||
|
||
private ExecutorService newExecutor() { | ||
return Executors.newFixedThreadPool(7); | ||
} | ||
|
||
private static class SleepyTaskProvider implements TaskProvider<Integer, Integer> { | ||
|
||
public Task<Integer, Integer> provideTask(final Integer id) { | ||
|
||
return new Task<Integer, Integer>() { | ||
|
||
private static final long serialVersionUID = 1L; | ||
|
||
public Integer execute() { | ||
|
||
if (id == 14) { | ||
try { | ||
TimeUnit.MILLISECONDS.sleep(100); | ||
} catch (InterruptedException e) { | ||
logger.error(this.toString(), e); | ||
} | ||
} else { | ||
try { | ||
TimeUnit.MILLISECONDS.sleep(1); | ||
} catch (InterruptedException e) { | ||
logger.error(this.toString(), e); | ||
} | ||
} | ||
|
||
return id; | ||
} | ||
|
||
@Override | ||
public Duration getTimeout() { | ||
return Duration.ofMillis(1); | ||
} | ||
}; | ||
} | ||
} | ||
|
||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters