use of io.kestra.core.models.conditions.ConditionContext in project kestra by kestra-io.
the class ConditionServiceTest method valid.
@Test
void valid() {
Flow flow = TestsUtils.mockFlow();
Execution execution = TestsUtils.mockExecution(flow, ImmutableMap.of());
RunContext runContext = runContextFactory.of(flow, execution);
ConditionContext conditionContext = conditionService.conditionContext(runContext, flow, execution);
List<Condition> conditions = Arrays.asList(ExecutionFlowCondition.builder().namespace(flow.getNamespace()).flowId(flow.getId()).build(), ExecutionNamespaceCondition.builder().namespace(flow.getNamespace()).build());
boolean valid = conditionService.valid(flow, conditions, conditionContext);
assertThat(valid, is(true));
}
use of io.kestra.core.models.conditions.ConditionContext in project kestra by kestra-io.
the class ConditionServiceTest method exception.
@Test
void exception() throws InterruptedException {
List<LogEntry> logs = new ArrayList<>();
logQueue.receive(logs::add);
Flow flow = TestsUtils.mockFlow();
Schedule schedule = Schedule.builder().id("unit").type(Schedule.class.getName()).cron("0 0 1 * *").build();
RunContext runContext = runContextFactory.of(flow, schedule);
ConditionContext conditionContext = conditionService.conditionContext(runContext, flow, null);
List<Condition> conditions = Collections.singletonList(ExecutionFlowCondition.builder().namespace(flow.getNamespace()).flowId(flow.getId()).build());
conditionService.valid(flow, conditions, conditionContext);
Thread.sleep(250);
assertThat(logs.stream().filter(logEntry -> logEntry.getNamespace().equals("io.kestra.core.services.ConditionServiceTest")).count(), greaterThan(0L));
assertThat(logs.stream().filter(logEntry -> logEntry.getFlowId().equals("exception")).count(), greaterThan(0L));
}
use of io.kestra.core.models.conditions.ConditionContext in project kestra by kestra-io.
the class MultipleCondition method test.
/**
* This conditions will only validate previously calculated value on
* {@link FlowService#multipleFlowTrigger(Stream, Flow, Execution, MultipleConditionStorageInterface)}} and save on {@link MultipleConditionStorageInterface}
* by the executor.
* The real validation is done here.
*/
@Override
public boolean test(ConditionContext conditionContext) throws InternalException {
Logger logger = conditionContext.getRunContext().logger();
MultipleConditionStorageInterface multipleConditionStorage = conditionContext.getMultipleConditionStorage();
Objects.requireNonNull(multipleConditionStorage);
Optional<MultipleConditionWindow> triggerExecutionWindow = multipleConditionStorage.get(conditionContext.getFlow(), this.getId());
Map<String, Boolean> results = conditions.keySet().stream().map(condition -> new AbstractMap.SimpleEntry<>(condition, (triggerExecutionWindow.isPresent() && triggerExecutionWindow.get().getResults() != null && triggerExecutionWindow.get().getResults().containsKey(condition) && triggerExecutionWindow.get().getResults().get(condition)))).collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue));
long validatedCount = results.entrySet().stream().filter(Map.Entry::getValue).count();
boolean result = conditions.size() == validatedCount;
if (result && logger.isDebugEnabled()) {
logger.debug("[namespace: {}] [flow: {}] Multiple conditions validated !", conditionContext.getFlow().getNamespace(), conditionContext.getFlow().getId());
} else if (logger.isTraceEnabled()) {
logger.trace("[namespace: {}] [flow: {}] Multiple conditions failed ({}/{}) with '{}'", conditionContext.getFlow().getNamespace(), conditionContext.getFlow().getId(), validatedCount, conditions.size(), results);
}
return result;
}
use of io.kestra.core.models.conditions.ConditionContext in project kestra by kestra-io.
the class Schedule method truePreviousNextDateWithCondition.
private Optional<ZonedDateTime> truePreviousNextDateWithCondition(ExecutionTime executionTime, ConditionContext conditionContext, ZonedDateTime toTestDate, boolean next) {
while ((next && toTestDate.getYear() < ZonedDateTime.now().getYear() + 10) || (!next && toTestDate.getYear() > ZonedDateTime.now().getYear() - 10)) {
Optional<ZonedDateTime> currentDate = next ? executionTime.nextExecution(toTestDate) : executionTime.lastExecution(toTestDate);
if (currentDate.isEmpty()) {
return currentDate;
}
Optional<Output> currentOutput = this.output(executionTime, currentDate.get());
if (currentOutput.isEmpty()) {
return Optional.empty();
}
ConditionContext currentConditionContext = this.conditionContext(conditionContext, currentOutput.get());
boolean conditionResults = this.validateScheduleCondition(currentConditionContext);
if (conditionResults) {
return currentDate;
}
toTestDate = currentDate.get();
}
return Optional.empty();
}
use of io.kestra.core.models.conditions.ConditionContext in project kestra by kestra-io.
the class AbstractScheduler method handle.
private void handle() {
if (!this.isReady) {
log.warn("Scheduler is not ready, waiting");
}
metricRegistry.counter(MetricRegistry.SCHEDULER_LOOP_COUNT).increment();
ZonedDateTime now = now();
synchronized (this) {
if (log.isDebugEnabled()) {
log.debug("Scheduler next iteration for {} with {} schedulables of {} flows", now, schedulable.size(), this.flowListeners.flows().size());
}
// get all that is ready from evaluation
List<FlowWithPollingTriggerNextDate> readyForEvaluate = schedulable.stream().filter(f -> conditionService.isValid(f.getFlow(), f.getTrigger(), f.getConditionContext())).map(flowWithTrigger -> FlowWithPollingTrigger.builder().flow(flowWithTrigger.getFlow()).trigger(flowWithTrigger.getTrigger()).pollingTrigger((PollingTriggerInterface) flowWithTrigger.getTrigger()).conditionContext(flowWithTrigger.getConditionContext()).triggerContext(TriggerContext.builder().namespace(flowWithTrigger.getFlow().getNamespace()).flowId(flowWithTrigger.getFlow().getId()).flowRevision(flowWithTrigger.getFlow().getRevision()).triggerId(flowWithTrigger.getTrigger().getId()).date(now()).build()).build()).filter(f -> this.isEvaluationInterval(f, now)).filter(f -> this.isExecutionNotRunning(f, now)).map(f -> {
synchronized (this) {
Trigger lastTrigger = this.getLastTrigger(f, now);
return FlowWithPollingTriggerNextDate.of(f, f.getPollingTrigger().nextEvaluationDate(f.getConditionContext(), Optional.of(lastTrigger)));
}
}).filter(Objects::nonNull).collect(Collectors.toList());
if (log.isDebugEnabled()) {
log.debug("Scheduler will evaluate for {} with {} readyForEvaluate of {} schedulables", now, readyForEvaluate.size(), schedulable.size());
}
metricRegistry.counter(MetricRegistry.SCHEDULER_EVALUATE_COUNT).increment(readyForEvaluate.size());
// submit ready one to cached thread pool
readyForEvaluate.forEach(f -> {
schedulableNextDate.put(f.getTriggerContext().uid(), f);
if (f.getPollingTrigger().getInterval() == null) {
try {
this.handleEvaluatePollingTriggerResult(this.evaluatePollingTrigger(f));
} catch (Exception e) {
AbstractScheduler.logError(f, e);
}
} else {
this.addToRunning(f.getTriggerContext(), now);
ListenableFuture<SchedulerExecutionWithTrigger> result = cachedExecutor.submit(() -> this.evaluatePollingTrigger(f));
Futures.addCallback(result, new EvaluateFuture(this, f), cachedExecutor);
}
});
}
}
Aggregations