-
Notifications
You must be signed in to change notification settings - Fork 2.5k
/
SchedulerUtils.java
137 lines (116 loc) · 4.85 KB
/
SchedulerUtils.java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
package io.quarkus.scheduler.runtime.util;
import static io.smallrye.common.expression.Expression.Flag.LENIENT_SYNTAX;
import static io.smallrye.common.expression.Expression.Flag.NO_TRIM;
import java.time.Duration;
import java.util.NoSuchElementException;
import java.util.Optional;
import java.util.OptionalLong;
import org.eclipse.microprofile.config.Config;
import org.eclipse.microprofile.config.spi.ConfigProviderResolver;
import io.quarkus.scheduler.Scheduled;
import io.smallrye.common.expression.Expression;
/**
* Utilities class for scheduler extensions.
*
*/
public class SchedulerUtils {
private static final String DELAYED = "delayed";
private static final String EVERY = "every";
private SchedulerUtils() {
}
/**
* Parse the `@Scheduled(delayed = "")` field into milliseconds.
*
* @param scheduled annotation
* @return returns the duration in milliseconds.
*/
public static long parseDelayedAsMillis(Scheduled scheduled) {
String value = lookUpPropertyValue(scheduled.delayed());
return parseDurationAsMillis(scheduled, value, DELAYED);
}
/**
* Parse the `@Scheduled(every = "")` field into milliseconds.
*
* @param scheduled annotation
* @return returns the duration in milliseconds or {@link OptionalLong#empty()} if the expression evaluates to "off" or
* "disabled".
*/
public static OptionalLong parseEveryAsMillis(Scheduled scheduled) {
String value = lookUpPropertyValue(scheduled.every());
OptionalLong optionalMillis = OptionalLong.empty();
if (!isOff(value)) {
optionalMillis = OptionalLong.of(parseDurationAsMillis(scheduled, value, EVERY));
}
return optionalMillis;
}
public static boolean isOff(String value) {
return value != null && (value.equalsIgnoreCase("off") || value.equalsIgnoreCase("disabled"));
}
/**
* Looks up the property value by checking whether the value is a configuration key and resolves it if so.
*
* @param propertyValue property value to look up.
* @return the resolved property value.
*/
public static String lookUpPropertyValue(String propertyValue) {
String value = propertyValue.trim();
if (!value.isEmpty()) {
// for backwards compatibility
if (isSimpleConfigValue(value)) {
value = ConfigProviderResolver.instance().getConfig().getValue(unwrapSimpleConfigProperty(value), String.class);
} else {
value = resolvePropertyExpression(value);
}
}
return value;
}
public static boolean isConfigValue(String val) {
return isSimpleConfigValue(val) || isConfigExpression(val);
}
private static boolean isSimpleConfigValue(String val) {
val = val.trim();
return val.startsWith("{") && val.endsWith("}");
}
private static String unwrapSimpleConfigProperty(String val) {
return val.substring(1, val.length() - 1);
}
/**
* Adapted from {@link io.smallrye.config.ExpressionConfigSourceInterceptor}
*/
private static String resolvePropertyExpression(String expr) {
final Config config = ConfigProviderResolver.instance().getConfig();
final Expression expression = compileExpression(expr);
final String expanded = expression.evaluate((resolveContext, stringBuilder) -> {
final Optional<String> resolve = config.getOptionalValue(resolveContext.getKey(), String.class);
if (resolve.isPresent()) {
stringBuilder.append(resolve.get());
} else if (resolveContext.hasDefault()) {
resolveContext.expandDefault();
} else {
throw new NoSuchElementException(String.format("Could not expand value %s in property %s",
resolveContext.getKey(), expr));
}
});
return expanded;
}
private static Expression compileExpression(String expr) {
return Expression.compile(expr, LENIENT_SYNTAX, NO_TRIM);
}
private static boolean isConfigExpression(String val) {
return val != null && compileExpression(val).getReferencedStrings().size() > 0;
}
private static long parseDurationAsMillis(Scheduled scheduled, String value, String memberName) {
return Math.abs(parseDuration(scheduled, value, memberName).toMillis());
}
private static Duration parseDuration(Scheduled scheduled, String value, String memberName) {
if (Character.isDigit(value.charAt(0))) {
value = "PT" + value;
}
try {
return Duration.parse(value);
} catch (Exception e) {
// This could only happen for config-based expressions
throw new IllegalStateException("Invalid " + memberName + "() expression on: " + scheduled, e);
}
}
}