use of eu.bcvsolutions.idm.core.scheduler.api.exception.ConcurrentExecutionException in project CzechIdMng by bcvsolutions.
the class AbstractLongRunningTaskExecutor method validate.
/**
* Validates task before start e.q. if task already running or to prevent run task concurrently.
*
* Look out: override this method additively
*
* @param task persisted task to validate
*/
@Override
public void validate(IdmLongRunningTaskDto task) {
Assert.notNull(task, "Long running task has to be prepared before task is started");
//
if (task.isRunning()) {
throw new ResultCodeException(CoreResultCode.LONG_RUNNING_TASK_IS_RUNNING, ImmutableMap.of("taskId", task.getId()));
}
if (!OperationState.isRunnable(task.getResultState())) {
throw new ResultCodeException(CoreResultCode.LONG_RUNNING_TASK_IS_PROCESSED, ImmutableMap.of("taskId", task.getId()));
}
//
// check concurrent task is not running (or waiting => operation state is used)
String taskType = task.getTaskType();
if (this.getClass().isAnnotationPresent(DisallowConcurrentExecution.class)) {
IdmLongRunningTaskFilter filter = new IdmLongRunningTaskFilter();
filter.setTaskType(taskType);
filter.setOperationState(OperationState.RUNNING);
// ignore waiting tasks
filter.setRunning(Boolean.TRUE);
List<UUID> runningTasks = longRunningTaskService.findIds(filter, null).getContent().stream().filter(t -> {
// not self
return !t.equals(task.getId());
}).collect(Collectors.toList());
if (!runningTasks.isEmpty()) {
throw new ConcurrentExecutionException(CoreResultCode.LONG_RUNNING_TASK_IS_RUNNING, ImmutableMap.of("taskId", getName()));
}
}
if (this.getClass().isAnnotationPresent(IdmCheckConcurrentExecution.class)) {
List<String> disallowConcurrentTaskTypes = new ArrayList<>();
IdmCheckConcurrentExecution disallowConcurrentExecution = this.getClass().getAnnotation(IdmCheckConcurrentExecution.class);
Class<? extends LongRunningTaskExecutor<?>>[] taskTypes = disallowConcurrentExecution.taskTypes();
if (taskTypes.length == 0) {
disallowConcurrentTaskTypes.add(taskType);
} else {
disallowConcurrentTaskTypes.addAll(// TODO: move to utils somewhere - DRY manager
Arrays.asList(taskTypes).stream().map(Class::getCanonicalName).collect(Collectors.toList()));
}
// TODO: filter.setTaskTypes(...)
disallowConcurrentTaskTypes.forEach(concurrentTaskType -> {
IdmLongRunningTaskFilter filter = new IdmLongRunningTaskFilter();
filter.setTaskType(concurrentTaskType);
filter.setOperationState(OperationState.RUNNING);
// ignore waiting tasks
filter.setRunning(Boolean.TRUE);
List<UUID> runningTasks = longRunningTaskService.findIds(filter, null).getContent().stream().filter(t -> {
// not self
return !t.equals(task.getId());
}).collect(Collectors.toList());
if (!runningTasks.isEmpty()) {
throw new AcceptedException(CoreResultCode.LONG_RUNNING_TASK_ACCEPTED, ImmutableMap.of("taskId", getName()));
}
});
}
}
use of eu.bcvsolutions.idm.core.scheduler.api.exception.ConcurrentExecutionException in project CzechIdMng by bcvsolutions.
the class DefaultLongRunningTaskManager method execute.
@Override
@Transactional(noRollbackFor = AcceptedException.class)
public synchronized <V> LongRunningFutureTask<V> execute(LongRunningTaskExecutor<V> taskExecutor) {
if (!isAsynchronous()) {
V result = executeSync(taskExecutor);
// construct simple "sync" task
return new LongRunningFutureTask<>(taskExecutor, new FutureTask<V>(() -> {
return result;
}) {
@Override
public V get() {
return result;
}
});
}
//
// autowire task properties
AutowireHelper.autowire(taskExecutor);
// persist LRT as running => prevent to scheduler process the created tasks
IdmLongRunningTaskDto persistTask = resolveLongRunningTask(taskExecutor, null, OperationState.RUNNING);
//
try {
taskExecutor.validate(persistTask);
} catch (ConcurrentExecutionException ex) {
// task can be executed later, e.g. after previous task ends
markTaskAsCreated(persistTask);
//
throw ex;
} catch (ResultCodeException ex) {
// task can be executed later, e.g. after previous task ends
if (ex.getStatus() == HttpStatus.ACCEPTED) {
markTaskAsCreated(persistTask);
} else {
// mark task as failed => prevent to stuck task type execution from queue
persistTask.setResult(new OperationResult.Builder(OperationState.EXCEPTION).setException(ex).build());
service.save(persistTask);
}
//
throw ex;
}
//
LongRunningFutureTask<V> longRunnigFutureTask = new LongRunningFutureTask<>(taskExecutor, new FutureTask<>(taskExecutor));
// execute - after original transaction is commited
entityEventManager.publishEvent(longRunnigFutureTask);
//
return longRunnigFutureTask;
}
Aggregations