-
Notifications
You must be signed in to change notification settings - Fork 8
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Closes #372 - Add Distribution for tasks
- Loading branch information
1 parent
a3a1449
commit e6d9315
Showing
15 changed files
with
1,930 additions
and
7 deletions.
There are no files selected for viewing
592 changes: 592 additions & 0 deletions
592
lib/kadai-core-test/src/test/java/acceptance/task/distribute/DistributeTaskAccTest.java
Large diffs are not rendered by default.
Oops, something went wrong.
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
79 changes: 79 additions & 0 deletions
79
lib/kadai-core/src/main/java/io/kadai/spi/task/api/TaskDistributionProvider.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,79 @@ | ||
package io.kadai.spi.task.api; | ||
|
||
import io.kadai.common.api.KadaiEngine; | ||
import io.kadai.task.api.models.Task; | ||
import io.kadai.workbasket.api.models.Workbasket; | ||
import java.util.List; | ||
import java.util.Map; | ||
|
||
/** | ||
* The {@code TaskDistributionProvider} interface defines a Service Provider Interface for | ||
* implementing custom {@linkplain Task} distribution strategies within the {@linkplain | ||
* KadaiEngine}. | ||
* | ||
* <p>This interface allows the system to distribute {@linkplain Task}s from a source to one or more | ||
* destination {@linkplain Workbasket}s based on a given strategy and additional context-specific | ||
* information. | ||
* | ||
* <p>The implementation of this interface must be registered as a service provider and will be | ||
* called by KADAI during task distribution operations. | ||
*/ | ||
public interface TaskDistributionProvider { | ||
|
||
/** | ||
* Initializes the {@linkplain KadaiEngine} for the current KADAI installation. | ||
* | ||
* <p>This method is called during KADAI startup and allows the service provider to access and | ||
* store the active {@linkplain KadaiEngine} instance for later use during task distribution. | ||
* | ||
* @param kadaiEngine the active {@linkplain KadaiEngine} instance initialized for this | ||
* installation | ||
*/ | ||
void initialize(KadaiEngine kadaiEngine); | ||
|
||
/** | ||
* Determines the distribution of tasks to one or more destination workbaskets based on the | ||
* provided parameters. | ||
* | ||
* <p>This method is invoked by KADAI to calculate the assignment of a set of task IDs to specific | ||
* destination workbaskets using a custom distribution strategy. The method does not directly | ||
* perform the distribution but returns the intended mapping of tasks to workbaskets. | ||
* | ||
* <p><b>Input Parameters:</b> | ||
* | ||
* <ul> | ||
* <li>{@code taskIds (List<String>)}: A list of task IDs to be analyzed for distribution. | ||
* <li>{@code destinationWorkbasketIds (List<String>)}: A list of destination workbasket IDs | ||
* where the tasks are intended to be assigned. | ||
* <li>{@code additionalInformation (Map<String, Object>)}: Additional context-specific details | ||
* that can influence the distribution logic. | ||
* </ul> | ||
* | ||
* <p><b>Output:</b> | ||
* | ||
* <ul> | ||
* <li>The method returns a {@code Map<String, List<String>>}, where each key represents a | ||
* destination workbasket ID, and the corresponding value is a list of task IDs that should | ||
* be assigned to that workbasket. | ||
* <li>The returned mapping provides the intended distribution but does not execute any changes | ||
* in the system. | ||
* </ul> | ||
* | ||
* <p><b>Contract:</b> | ||
* | ||
* <ul> | ||
* <li>The {@code taskIds} and {@code destinationWorkbasketIds} must not be null. | ||
* </ul> | ||
* | ||
* @param taskIds a list of task IDs to be analyzed for distribution | ||
* @param destinationWorkbasketIds a list of destination workbasket IDs where tasks are intended | ||
* to be distributed | ||
* @param additionalInformation a map of additional details for customizing the distribution logic | ||
* @return a {@code Map<String, List<String>>} containing the destination workbasket IDs as keys | ||
* and the corresponding task IDs to be assigned as values | ||
*/ | ||
Map<String, List<String>> distributeTasks( | ||
List<String> taskIds, | ||
List<String> destinationWorkbasketIds, | ||
Map<String, Object> additionalInformation); | ||
} |
42 changes: 42 additions & 0 deletions
42
lib/kadai-core/src/main/java/io/kadai/spi/task/internal/DefaultTaskDistributionProvider.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,42 @@ | ||
package io.kadai.spi.task.internal; | ||
|
||
import io.kadai.common.api.KadaiEngine; | ||
import io.kadai.spi.task.api.TaskDistributionProvider; | ||
import java.util.ArrayList; | ||
import java.util.HashMap; | ||
import java.util.List; | ||
import java.util.Map; | ||
|
||
public class DefaultTaskDistributionProvider implements TaskDistributionProvider { | ||
|
||
@Override | ||
public void initialize(KadaiEngine kadaiEngine) { | ||
// NOOP | ||
} | ||
|
||
@Override | ||
public Map<String, List<String>> distributeTasks( | ||
List<String> taskIds, List<String> workbasketIds, Map<String, Object> additionalInformation) { | ||
|
||
if (taskIds == null || taskIds.isEmpty()) { | ||
throw new IllegalArgumentException("Task Ids list cannot be null or empty."); | ||
} | ||
if (workbasketIds == null || workbasketIds.isEmpty()) { | ||
throw new IllegalArgumentException("Ids of destinationWorkbaskets cannot be null or empty."); | ||
} | ||
|
||
Map<String, List<String>> distributedTaskIds = new HashMap<>(); | ||
for (String workbasketId : workbasketIds) { | ||
distributedTaskIds.put(workbasketId, new ArrayList<>()); | ||
} | ||
|
||
int workbasketCount = workbasketIds.size(); | ||
for (int i = 0; i < taskIds.size(); i++) { | ||
String taskId = taskIds.get(i); | ||
String targetWorkbasketId = workbasketIds.get(i % workbasketCount); | ||
distributedTaskIds.get(targetWorkbasketId).add(taskId); | ||
} | ||
|
||
return distributedTaskIds; | ||
} | ||
} |
76 changes: 76 additions & 0 deletions
76
lib/kadai-core/src/main/java/io/kadai/spi/task/internal/TaskDistributionManager.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,76 @@ | ||
package io.kadai.spi.task.internal; | ||
|
||
import io.kadai.common.api.KadaiEngine; | ||
import io.kadai.common.api.exceptions.InvalidArgumentException; | ||
import io.kadai.common.internal.util.LogSanitizer; | ||
import io.kadai.common.internal.util.SpiLoader; | ||
import io.kadai.spi.task.api.TaskDistributionProvider; | ||
import java.util.ArrayList; | ||
import java.util.List; | ||
import java.util.Map; | ||
import org.slf4j.Logger; | ||
import org.slf4j.LoggerFactory; | ||
|
||
public final class TaskDistributionManager { | ||
|
||
private static final Logger LOGGER = LoggerFactory.getLogger(TaskDistributionManager.class); | ||
private final List<TaskDistributionProvider> taskDistributionProviderList; | ||
private final TaskDistributionProvider defaultProvider = new DefaultTaskDistributionProvider(); | ||
|
||
public TaskDistributionManager(KadaiEngine kadaiEngine) { | ||
List<TaskDistributionProvider> loadedProviders = SpiLoader.load(TaskDistributionProvider.class); | ||
|
||
this.taskDistributionProviderList = new ArrayList<>(loadedProviders); | ||
this.taskDistributionProviderList.add(defaultProvider); | ||
|
||
for (TaskDistributionProvider provider : taskDistributionProviderList) { | ||
provider.initialize(kadaiEngine); | ||
LOGGER.info("Registered TaskDistribution provider: {}", provider.getClass().getName()); | ||
} | ||
|
||
if (loadedProviders.isEmpty()) { | ||
LOGGER.info( | ||
"No Custom TaskDistribution Provider found. Using only DefaultTaskDistributionProvider."); | ||
} | ||
} | ||
|
||
public TaskDistributionProvider getProviderByName(String name) { | ||
if (name == null) { | ||
return defaultProvider; | ||
} | ||
|
||
return taskDistributionProviderList.stream() | ||
.filter(provider -> provider.getClass().getSimpleName().equals(name)) | ||
.findFirst() | ||
.orElseThrow( | ||
() -> | ||
new InvalidArgumentException( | ||
String.format("The distribution strategy '%s' does not exist.", name))); | ||
} | ||
|
||
public Map<String, List<String>> distributeTasks( | ||
List<String> taskIds, | ||
List<String> destinationWorkbasketIds, | ||
Map<String, Object> additionalInformation, | ||
String distributionStrategyName) { | ||
|
||
TaskDistributionProvider provider = getProviderByName(distributionStrategyName); | ||
|
||
String sanitizedDistributionStrategyName = | ||
LogSanitizer.stripLineBreakingChars( | ||
distributionStrategyName != null | ||
? distributionStrategyName | ||
: "DefaultTaskDistributionProvider"); | ||
LOGGER.info("Using TaskDistributionProvider: {}", sanitizedDistributionStrategyName); | ||
|
||
Map<String, List<String>> newTaskDistribution = | ||
provider.distributeTasks(taskIds, destinationWorkbasketIds, additionalInformation); | ||
|
||
if (newTaskDistribution == null || newTaskDistribution.isEmpty()) { | ||
throw new InvalidArgumentException( | ||
"The distribution strategy resulted in no task assignments. Please verify the input."); | ||
} | ||
|
||
return newTaskDistribution; | ||
} | ||
} |
Oops, something went wrong.