Skip to content

Commit be83676

Browse files
Merge pull request #151 from wttech/every-x-in-range
Every X in range + Idle/Not running hardening
2 parents f21cffa + 28ae6a3 commit be83676

File tree

22 files changed

+275
-98
lines changed

22 files changed

+275
-98
lines changed

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -301,7 +301,7 @@ void describeRun() {
301301
}
302302
303303
boolean canRun() {
304-
return conditions.notRunning()
304+
return conditions.notRunningSelf()
305305
}
306306
307307
void doRun() {

core/src/main/java/dev/vml/es/acm/core/code/Conditions.java

Lines changed: 227 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -7,8 +7,11 @@
77
import dev.vml.es.acm.core.script.ScriptType;
88
import dev.vml.es.acm.core.util.DateUtils;
99
import java.time.*;
10+
import java.time.temporal.ChronoUnit;
11+
import java.util.Date;
1012
import java.util.Iterator;
1113
import java.util.Locale;
14+
import java.util.Optional;
1215
import java.util.stream.Stream;
1316
import org.apache.commons.io.FilenameUtils;
1417
import org.apache.commons.lang3.StringUtils;
@@ -58,24 +61,30 @@ public Stream<Execution> passedExecutions() {
5861
return executionHistory.findAll(query);
5962
}
6063

61-
public boolean idle() {
62-
return noneRunning();
63-
}
64-
6564
public boolean idleSelf() {
66-
return notRunning();
65+
if (executionContext.getExecutor().isLocking() && lockedSelf()) {
66+
return false;
67+
}
68+
return !queuedSelfExecutions().findAny().isPresent();
6769
}
6870

69-
public boolean notRunning() {
70-
if (executionContext.getExecutor().isLocking()) {
71-
return unlockedSelf();
71+
public boolean notRunningSelf() {
72+
if (executionContext.getExecutor().isLocking() && lockedSelf()) {
73+
return false;
7274
}
7375
return noneRunning(queuedSelfExecutions());
7476
}
7577

76-
public boolean noneRunning() {
77-
if (executionContext.getExecutor().isLocking()) {
78-
return unlockedAll();
78+
public boolean idle() {
79+
if (executionContext.getExecutor().isLocking() && lockedAny()) {
80+
return false;
81+
}
82+
return !queuedExecutions().findAny().isPresent();
83+
}
84+
85+
public boolean notRunning() {
86+
if (executionContext.getExecutor().isLocking() && lockedAny()) {
87+
return false;
7988
}
8089
return noneRunning(queuedExecutions());
8190
}
@@ -125,8 +134,10 @@ public boolean isDate(ZonedDateTime zonedDateTime) {
125134
}
126135

127136
public boolean isDate(LocalDateTime localDateTime) {
128-
long intervalMillis = getScriptScheduler().getIntervalMillis();
129-
return DateUtils.isInRange(localDateTime, LocalDateTime.now(), intervalMillis);
137+
LocalDateTime now = LocalDateTime.now();
138+
LocalDateTime from = localDateTime;
139+
LocalDateTime to = from.plus(getScriptScheduler().getIntervalMillis(), ChronoUnit.MILLIS);
140+
return !now.isBefore(from) && !now.isAfter(to);
130141
}
131142

132143
private ScriptScheduler getScriptScheduler() {
@@ -188,85 +199,85 @@ public LocalTime dayEndTime() {
188199
return LocalTime.of(23, 59, 59, 999999999);
189200
}
190201

191-
public boolean everyMinute() {
192-
return everyMinute(0);
202+
public boolean everyMinuteStart() {
203+
return everyMinuteAt(0);
193204
}
194205

195-
public boolean everyMinute(int second) {
206+
public boolean everyMinuteAt(int second) {
196207
LocalTime now = LocalTime.now();
197208
LocalDateTime scheduledDateTime =
198209
LocalDate.now().atTime(now.withSecond(second).withNano(0));
199210
return isDate(scheduledDateTime);
200211
}
201212

202-
public boolean everyHour() {
203-
return everyHour(0);
213+
public boolean everyHourStart() {
214+
return everyHourAt(0);
204215
}
205216

206-
public boolean everyHour(int minute) {
217+
public boolean everyHourAt(int minute) {
207218
LocalTime now = LocalTime.now();
208219
LocalDateTime scheduledDateTime =
209220
LocalDate.now().atTime(now.withMinute(minute).withSecond(0).withNano(0));
210221
return isDate(scheduledDateTime);
211222
}
212223

213-
public boolean everyDay() {
214-
return everyDay(LocalTime.MIDNIGHT);
224+
public boolean everyDayStart() {
225+
return everyDayAt(LocalTime.MIDNIGHT);
215226
}
216227

217-
public boolean everyDay(LocalTime time) {
228+
public boolean everyDayAt(LocalTime time) {
218229
LocalDateTime scheduledDateTime = LocalDate.now().atTime(time);
219230
return isDate(scheduledDateTime);
220231
}
221232

222-
public boolean everyDay(String time) {
223-
return everyDay(parseTime(time));
233+
public boolean everyDayAt(String time) {
234+
return everyDayAt(parseTime(time));
224235
}
225236

226-
public boolean everyWeek() {
227-
return everyWeek(DayOfWeek.MONDAY, LocalTime.MIDNIGHT);
237+
public boolean everyWeekStart() {
238+
return everyWeekAt(DayOfWeek.MONDAY, LocalTime.MIDNIGHT);
228239
}
229240

230-
public boolean everyWeek(DayOfWeek dayOfWeek, LocalTime time) {
241+
public boolean everyWeekAt(DayOfWeek dayOfWeek, LocalTime time) {
231242
LocalDate startOfWeek = LocalDate.now().with(dayOfWeek);
232243
LocalDateTime scheduledDateTime = startOfWeek.atTime(time);
233244
return isDate(scheduledDateTime);
234245
}
235246

236-
public boolean everyWeek(String dayOfWeek, String time) {
237-
return everyWeek(parseDayOfWeek(dayOfWeek), parseTime(time));
247+
public boolean everyWeekAt(String dayOfWeek, String time) {
248+
return everyWeekAt(parseDayOfWeek(dayOfWeek), parseTime(time));
238249
}
239250

240-
public boolean everyMonth() {
241-
return everyMonth(1, LocalTime.MIDNIGHT);
251+
public boolean everyMonthStart() {
252+
return everyMonthAt(1, LocalTime.MIDNIGHT);
242253
}
243254

244-
public boolean everyMonth(int dayOfMonth) {
245-
return everyMonth(dayOfMonth, LocalTime.MIDNIGHT);
255+
public boolean everyMonthAt(int dayOfMonth) {
256+
return everyMonthAt(dayOfMonth, LocalTime.MIDNIGHT);
246257
}
247258

248-
public boolean everyMonth(int dayOfMonth, LocalTime time) {
259+
public boolean everyMonthAt(int dayOfMonth, LocalTime time) {
249260
LocalDate startOfMonth = LocalDate.now().withDayOfMonth(dayOfMonth);
250261
LocalDateTime scheduledDateTime = startOfMonth.atTime(time);
251262
return isDate(scheduledDateTime);
252263
}
253264

254-
public boolean everyMonth(int dayOfMonth, String time) {
255-
return everyMonth(dayOfMonth, parseTime(time));
265+
public boolean everyMonthAt(int dayOfMonth, String time) {
266+
return everyMonthAt(dayOfMonth, parseTime(time));
256267
}
257268

258-
public boolean everyYear() {
259-
return everyYear(Month.JANUARY, 1, LocalTime.MIDNIGHT);
269+
public boolean everyYearStart() {
270+
return everyYearAt(Month.JANUARY, 1, LocalTime.MIDNIGHT);
260271
}
261272

262-
public boolean everyYear(Month month, int dayOfMonth, LocalTime time) {
273+
public boolean everyYearAt(Month month, int dayOfMonth, LocalTime time) {
263274
LocalDate targetDay = LocalDate.now().withMonth(month.getValue()).withDayOfMonth(dayOfMonth);
264275
LocalDateTime scheduledDateTime = targetDay.atTime(time);
265276
return isDate(scheduledDateTime);
266277
}
267278

268-
public boolean everyYear(String month, int dayOfMonth, String time) {
269-
return everyYear(parseMonth(month), dayOfMonth, parseTime(time));
279+
public boolean everyYearAt(String month, int dayOfMonth, String time) {
280+
return everyYearAt(parseMonth(month), dayOfMonth, parseTime(time));
270281
}
271282

272283
private LocalTime parseTime(String time) {
@@ -281,6 +292,175 @@ private DayOfWeek parseDayOfWeek(String dayOfWeek) {
281292
return DayOfWeek.valueOf(dayOfWeek.trim().toUpperCase(Locale.ENGLISH));
282293
}
283294

295+
public boolean everyMinuteInRange() {
296+
LocalTime now = LocalTime.now();
297+
LocalTime startTime = now.withSecond(0).withNano(0);
298+
LocalTime endTime = now.withSecond(59).withNano(999999999);
299+
checkStartAndEndTime(startTime, endTime);
300+
if (now.isBefore(startTime) || now.isAfter(endTime)) {
301+
return false;
302+
}
303+
return !executedInRange(LocalDate.now(), startTime, endTime);
304+
}
305+
306+
public boolean everyMinuteInRange(int startSecond, int endSecond) {
307+
LocalTime now = LocalTime.now();
308+
LocalTime startTime = now.withSecond(startSecond).withNano(0);
309+
LocalTime endTime = now.withSecond(endSecond).withNano(999999999);
310+
checkStartAndEndTime(startTime, endTime);
311+
if (now.isBefore(startTime) || now.isAfter(endTime)) {
312+
return false;
313+
}
314+
return !executedInRange(LocalDate.now(), startTime, endTime);
315+
}
316+
317+
public boolean everyHourInRange() {
318+
LocalTime now = LocalTime.now();
319+
LocalTime startTime = now.withMinute(0).withSecond(0).withNano(0);
320+
LocalTime endTime = now.withMinute(59).withSecond(59).withNano(999999999);
321+
checkStartAndEndTime(startTime, endTime);
322+
if (now.isBefore(startTime) || now.isAfter(endTime)) {
323+
return false;
324+
}
325+
return !executedInRange(LocalDate.now(), startTime, endTime);
326+
}
327+
328+
public boolean everyHourInRange(int startMinute, int endMinute) {
329+
LocalTime now = LocalTime.now();
330+
LocalTime startTime = now.withMinute(startMinute).withSecond(0).withNano(0);
331+
LocalTime endTime = now.withMinute(endMinute).withSecond(59).withNano(999999999);
332+
checkStartAndEndTime(startTime, endTime);
333+
if (now.isBefore(startTime) || now.isAfter(endTime)) {
334+
return false;
335+
}
336+
return !executedInRange(LocalDate.now(), startTime, endTime);
337+
}
338+
339+
public boolean everyDayInRange() {
340+
return everyDayInRange(dayStartTime(), dayEndTime());
341+
}
342+
343+
public boolean everyDayInRange(LocalTime startTime, LocalTime endTime) {
344+
checkStartAndEndTime(startTime, endTime);
345+
LocalTime now = LocalTime.now();
346+
if (now.isBefore(startTime) || now.isAfter(endTime)) {
347+
return false;
348+
}
349+
return !executedInRange(LocalDate.now(), startTime, endTime);
350+
}
351+
352+
public boolean everyDayInRange(String startTime, String endTime) {
353+
return everyDayInRange(LocalTime.parse(startTime), LocalTime.parse(endTime));
354+
}
355+
356+
public boolean everyWeekInRange() {
357+
return everyWeekInRange(dayStartTime(), dayEndTime());
358+
}
359+
360+
public boolean everyWeekInRange(LocalTime startTime, LocalTime endTime) {
361+
checkStartAndEndTime(startTime, endTime);
362+
LocalTime now = LocalTime.now();
363+
if (now.isBefore(startTime) || now.isAfter(endTime)) {
364+
return false;
365+
}
366+
LocalDate today = LocalDate.now();
367+
LocalDate startOfWeek = today.with(DayOfWeek.MONDAY);
368+
LocalDate endOfWeek = today.with(DayOfWeek.SUNDAY);
369+
return !executedInRange(startOfWeek, startTime, endOfWeek, endTime);
370+
}
371+
372+
public boolean everyWeekInRange(String startTime, String endTime) {
373+
return everyWeekInRange(LocalTime.parse(startTime), LocalTime.parse(endTime));
374+
}
375+
376+
public boolean everyMonthInRange() {
377+
return everyMonthInRange(dayStartTime(), dayEndTime());
378+
}
379+
380+
public boolean everyMonthInRange(LocalTime startTime, LocalTime endTime) {
381+
checkStartAndEndTime(startTime, endTime);
382+
LocalTime now = LocalTime.now();
383+
if (now.isBefore(startTime) || now.isAfter(endTime)) {
384+
return false;
385+
}
386+
LocalDate today = LocalDate.now();
387+
LocalDate startOfMonth = today.withDayOfMonth(1);
388+
LocalDate endOfMonth = today.withDayOfMonth(today.lengthOfMonth());
389+
return !executedInRange(startOfMonth, startTime, endOfMonth, endTime);
390+
}
391+
392+
public boolean everyMonthInRange(String startTime, String endTime) {
393+
return everyMonthInRange(LocalTime.parse(startTime), LocalTime.parse(endTime));
394+
}
395+
396+
public boolean everyYearInRange() {
397+
return everyYearInRange(dayStartTime(), dayEndTime());
398+
}
399+
400+
public boolean everyYearInRange(LocalTime startTime, LocalTime endTime) {
401+
checkStartAndEndTime(startTime, endTime);
402+
LocalTime now = LocalTime.now();
403+
if (now.isBefore(startTime) || now.isAfter(endTime)) {
404+
return false;
405+
}
406+
LocalDate today = LocalDate.now();
407+
LocalDate startOfYear = today.withDayOfYear(1);
408+
LocalDate endOfYear = today.withDayOfYear(today.lengthOfYear());
409+
return !executedInRange(startOfYear, startTime, endOfYear, endTime);
410+
}
411+
412+
public boolean everyYearInRange(String startTime, String endTime) {
413+
return everyYearInRange(LocalTime.parse(startTime), LocalTime.parse(endTime));
414+
}
415+
416+
public boolean executedInRange(LocalDate date, LocalTime startTime, LocalTime endTime) {
417+
return executedInRange(date, startTime, date, endTime);
418+
}
419+
420+
public boolean executedInRange(LocalDate startDate, LocalTime startTime, LocalDate endDate, LocalTime endTime) {
421+
ExecutionQuery query = new ExecutionQuery();
422+
query.setExecutableId(executionContext.getExecutable().getId());
423+
query.setStartDate(Date.from(
424+
startDate.atTime(startTime).atZone(ZoneId.systemDefault()).toInstant()));
425+
query.setEndDate(
426+
Date.from(endDate.atTime(endTime).atZone(ZoneId.systemDefault()).toInstant()));
427+
Optional<Execution> executionInTimeRange =
428+
executionHistory.findAll(query).findAny();
429+
return executionInTimeRange.isPresent();
430+
}
431+
432+
public boolean executedInRange(String startDateTime, String endDateTime) {
433+
return executedInRange(LocalDateTime.parse(startDateTime), LocalDateTime.parse(endDateTime));
434+
}
435+
436+
public boolean executedInRange(LocalDateTime startDateTime, LocalDateTime endDateTime) {
437+
return passedExecutionsInTimeRange(startDateTime, endDateTime).findAny().isPresent();
438+
}
439+
440+
public Stream<Execution> passedExecutionsInTimeRange(LocalDateTime startDateTime, LocalDateTime endDateTime) {
441+
checkStartAndEndDateTime(startDateTime, endDateTime);
442+
ExecutionQuery query = new ExecutionQuery();
443+
query.setExecutableId(executionContext.getExecutable().getId());
444+
query.setStartDate(
445+
Date.from(startDateTime.atZone(ZoneId.systemDefault()).toInstant()));
446+
query.setEndDate(Date.from(endDateTime.atZone(ZoneId.systemDefault()).toInstant()));
447+
return executionHistory.findAll(query);
448+
}
449+
450+
private void checkStartAndEndTime(LocalTime start, LocalTime end) {
451+
if (start.isAfter(end)) {
452+
throw new IllegalArgumentException(
453+
String.format("Start time '%s' must be before end time '%s'!", start, end));
454+
}
455+
}
456+
457+
private void checkStartAndEndDateTime(LocalDateTime start, LocalDateTime end) {
458+
if (start.isAfter(end)) {
459+
throw new IllegalArgumentException(
460+
String.format("Start date-time '%s' must be before end date-time '%s'!", start, end));
461+
}
462+
}
463+
284464
// Duration-based since the last execution
285465

286466
public boolean passed(Duration duration) {
@@ -330,6 +510,10 @@ public boolean unlockedSelf() {
330510
return !lockedSelf();
331511
}
332512

513+
public boolean unlockedAll() {
514+
return !lockedAny();
515+
}
516+
333517
public boolean lockedSelf() {
334518
return locked(executionContext.getExecutable().getId());
335519
}
@@ -343,9 +527,9 @@ public boolean locked(String name) {
343527
return executionContext.getCodeContext().getLocker().isLocked(name);
344528
}
345529

346-
public boolean unlockedAll() {
530+
public boolean lockedAny() {
347531
requireLocking();
348-
return !executionContext.getCodeContext().getLocker().anyLocked();
532+
return executionContext.getCodeContext().getLocker().anyLocked();
349533
}
350534

351535
private void requireLocking() {

core/src/main/java/dev/vml/es/acm/core/code/Executor.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@ public class Executor {
3434
@AttributeDefinition(
3535
name = "Locking",
3636
description =
37-
"Prevents concurrent execution of the same executable. Especially useful for scripts running on clustered author instances on AEMaaCS. Use together with 'conditions.notRunning()' or 'conditions.noneRunning() in the script.")
37+
"Prevents concurrent execution of the same executable. Especially useful for scripts running on clustered author instances on AEMaaCS. Use together with idle and not running conditions in the script.")
3838
boolean locking() default true;
3939

4040
@AttributeDefinition(

0 commit comments

Comments
 (0)