Skip to content

Commit 5253452

Browse files
committed
refactor(TriggerContext): refactor TriggerContext and update TriggerCondition#reasonCode
1 parent 8c0e5b1 commit 5253452

19 files changed

+149
-137
lines changed

core/src/main/java/io/github/zero88/schedulerx/JobData.java

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,6 @@
1212
* @param <T> Type of data
1313
* @since 1.0.0
1414
*/
15-
@FunctionalInterface
1615
public interface JobData<T> {
1716

1817
/**

core/src/main/java/io/github/zero88/schedulerx/JobExecutor.java

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
* @since 1.0.0
1111
*/
1212
@Internal
13+
@FunctionalInterface
1314
public interface JobExecutor<OUT> {
1415

1516
/**

core/src/main/java/io/github/zero88/schedulerx/JobExecutorContext.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
import org.jetbrains.annotations.NotNull;
55

66
/**
7-
* Shared immutable fields between JobExecutor and its builder.
7+
* Shared immutable fields between {@code JobExecutor} and its builder.
88
* <p/>
99
* This class is designed to internal usage, don't refer it in your code.
1010
*

core/src/main/java/io/github/zero88/schedulerx/SchedulerContext.java

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,15 @@
66
import io.github.zero88.schedulerx.trigger.Trigger;
77
import io.vertx.core.Vertx;
88

9+
/**
10+
* Shared immutable fields between {@code Scheduler} and its builder.
11+
* <p/>
12+
* This class is designed to internal usage, don't refer it in your code.
13+
*
14+
* @param <TRIGGER> Type of trigger
15+
* @param <OUT> Type of job result data
16+
* @since 2.0.0
17+
*/
918
@Internal
1019
interface SchedulerContext<TRIGGER extends Trigger, OUT> {
1120

core/src/main/java/io/github/zero88/schedulerx/impl/AbstractScheduler.java

Lines changed: 42 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -65,12 +65,12 @@ public abstract class AbstractScheduler<IN, OUT, T extends Trigger> implements S
6565
protected AbstractScheduler(@NotNull Vertx vertx, @NotNull SchedulingMonitor<OUT> monitor,
6666
@NotNull JobData<IN> jobData, @NotNull Job<IN, OUT> job, @NotNull T trigger,
6767
@NotNull TimeoutPolicy timeoutPolicy) {
68+
this.job = job;
69+
this.jobData = jobData;
70+
this.timeoutPolicy = timeoutPolicy;
6871
this.vertx = vertx;
6972
this.trigger = trigger;
7073
this.monitor = monitor;
71-
this.jobData = jobData;
72-
this.job = job;
73-
this.timeoutPolicy = timeoutPolicy;
7474
this.state = new SchedulerStateImpl<>();
7575
}
7676

@@ -147,7 +147,7 @@ public final void executeJob(@NotNull ExecutionContext<OUT> executionContext) {
147147
public final void cancel() {
148148
if (!state.completed()) {
149149
log(Instant.now(), "On cancel");
150-
doStop(state.timerId(), TriggerContextFactory.stop(trigger().type(), ReasonCode.STOP_BY_MANUAL));
150+
doStop(state.timerId(), TriggerContextFactory.cancel(trigger().type(), state.tick()));
151151
}
152152
}
153153

@@ -173,7 +173,7 @@ protected final void doStop(long timerId, TriggerContext context) {
173173
/**
174174
* Check a trigger kickoff context whether to be able to run new execution or not
175175
*/
176-
protected final TriggerTransitionContext shouldRun(@NotNull TriggerTransitionContext kickOffContext) {
176+
protected final TriggerContext shouldRun(@NotNull TriggerContext kickOffContext) {
177177
log(Instant.now(), "On evaluate");
178178
if (state.pending()) {
179179
return TriggerContextFactory.skip(kickOffContext, ReasonCode.NOT_YET_SCHEDULED);
@@ -190,8 +190,7 @@ protected final TriggerTransitionContext shouldRun(@NotNull TriggerTransitionCon
190190
/**
191191
* Check a trigger context whether to be able to stop by configuration or force stop
192192
*/
193-
protected final TriggerTransitionContext shouldStop(@NotNull TriggerTransitionContext triggerContext,
194-
boolean isForceStop, long round) {
193+
protected final TriggerContext shouldStop(@NotNull TriggerContext triggerContext, boolean isForceStop, long round) {
195194
if (isForceStop) {
196195
return TriggerContextFactory.stop(triggerContext, ReasonCode.STOP_BY_JOB);
197196
}
@@ -203,7 +202,7 @@ protected final TriggerTransitionContext shouldStop(@NotNull TriggerTransitionCo
203202
/**
204203
* Evaluate a trigger kickoff context on trigger rule
205204
*/
206-
protected TriggerTransitionContext evaluateTriggerRule(@NotNull TriggerTransitionContext triggerContext) {
205+
protected TriggerContext evaluateTriggerRule(@NotNull TriggerContext triggerContext) {
207206
if (!triggerContext.isKickoff()) {
208207
throw new IllegalStateException("Trigger condition status must be " + TriggerStatus.KICKOFF);
209208
}
@@ -228,48 +227,52 @@ protected final long onFire(long timerId) {
228227
}
229228

230229
/**
231-
* Processing the trigger when the system timer fires
230+
* Processing the trigger right away after the system timer fires
232231
*/
233-
protected final void onProcess(WorkerExecutor workerExecutor, TriggerTransitionContext kickoffContext) {
234-
log(Objects.requireNonNull(kickoffContext.firedAt()), "On fire");
235-
this.<TriggerTransitionContext>executeBlocking(workerExecutor,
236-
p -> wrapTimeout(timeoutPolicy().evaluationTimeout(),
237-
p).complete(shouldRun(kickoffContext)))
232+
protected final void onProcess(WorkerExecutor workerExecutor, TriggerContext ctx) {
233+
log(Objects.requireNonNull(ctx.firedAt()), "On fire");
234+
final Duration timeout = timeoutPolicy().evaluationTimeout();
235+
this.<TriggerContext>executeBlocking(workerExecutor,
236+
p -> wrapTimeout(timeoutPolicy().evaluationTimeout(), p).complete(
237+
shouldRun(ctx)))
238238
.onSuccess(context -> onTrigger(workerExecutor, context))
239-
.onFailure(t -> onMisfire(TriggerContextFactory.skip(kickoffContext, t instanceof TimeoutException
240-
? ReasonCode.EVALUATION_TIMEOUT
241-
: ReasonCode.UNEXPECTED_ERROR, t)));
239+
.onFailure(t -> onMisfire(TriggerContextFactory.skip(ctx, t instanceof TimeoutException
240+
? ReasonCode.EVALUATION_TIMEOUT
241+
: ReasonCode.UNEXPECTED_ERROR, t)));
242242
}
243243

244-
protected final void onTrigger(WorkerExecutor workerExecutor, TriggerTransitionContext triggerContext) {
244+
protected final void onTrigger(WorkerExecutor workerExecutor, TriggerContext triggerContext) {
245245
if (!triggerContext.isReady()) {
246246
onMisfire(triggerContext);
247247
return;
248248
}
249249
final ExecutionContextInternal<OUT> executionContext = new ExecutionContextImpl<>(vertx, triggerContext,
250250
state.increaseRound());
251+
final Duration timeout = timeoutPolicy().executionTimeout();
251252
log(executionContext.triggeredAt(), "On trigger", triggerContext.tick(), executionContext.round());
252-
this.executeBlocking(workerExecutor, p -> executeJob(
253-
executionContext.setup(wrapTimeout(timeoutPolicy().executionTimeout(), p))))
253+
this.executeBlocking(workerExecutor, p -> executeJob(executionContext.setup(wrapTimeout(timeout, p))))
254254
.onComplete(ar -> onResult(executionContext, ar.cause()));
255255
}
256256

257257
protected final void onSchedule(long timerId) {
258-
final TriggerContext context = TriggerContextFactory.scheduled(trigger().type());
259258
ExecutionResult<OUT> result;
260259
if (state.pending()) {
260+
final TriggerContext context = TriggerContextFactory.scheduled(trigger().type());
261261
result = ExecutionResultImpl.<OUT>builder()
262262
.setExternalId(jobData.externalId())
263263
.setAvailableAt(state.markAvailable())
264264
.setTriggerContext(context)
265+
.setTick(context.tick())
266+
.setRound(context.tick())
265267
.build();
266268
} else {
269+
final TriggerContext context = TriggerContextFactory.rescheduled(trigger().type(), state.tick());
267270
result = ExecutionResultImpl.<OUT>builder()
268271
.setExternalId(jobData.externalId())
269272
.setAvailableAt(state.availableAt())
270273
.setTriggerContext(context)
271274
.setRescheduledAt(Instant.now())
272-
.setTick(state.tick())
275+
.setTick(context.tick())
273276
.setRound(state.round())
274277
.build();
275278
}
@@ -282,32 +285,38 @@ protected final void onUnableSchedule(Throwable cause) {
282285
.setExternalId(jobData.externalId())
283286
.setTriggerContext(ctx)
284287
.setUnscheduledAt(Instant.now())
285-
.setTick(-1)
286-
.setRound(-1)
288+
.setTick(ctx.tick())
289+
.setRound(ctx.tick())
287290
.build());
288291
}
289292

290-
protected final void onMisfire(@NotNull TriggerTransitionContext triggerContext) {
291-
final Instant finishedAt = state.markFinished(triggerContext.tick());
292-
log(finishedAt, "On misfire::" + triggerContext.condition().reasonCode(), triggerContext.tick());
293+
protected final void onMisfire(@NotNull TriggerContext triggerCtx) {
294+
final Instant finishedAt = state.markFinished(triggerCtx.tick());
295+
final String reasonCode = triggerCtx.condition().reasonCode();
296+
final String event = "On misfire::" + reasonCode;
297+
if (ReasonCode.UNEXPECTED_ERROR.equals(reasonCode)) {
298+
LOGGER.error(genMsg(triggerCtx.tick(), state.round(), finishedAt, event), triggerCtx.condition().cause());
299+
} else {
300+
log(finishedAt, event, triggerCtx.tick());
301+
}
293302
monitor.onMisfire(ExecutionResultImpl.<OUT>builder()
294303
.setExternalId(jobData.externalId())
295304
.setAvailableAt(state.availableAt())
296-
.setTriggerContext(triggerContext)
297-
.setTick(triggerContext.tick())
298-
.setFiredAt(triggerContext.firedAt())
305+
.setTriggerContext(triggerCtx)
306+
.setTick(triggerCtx.tick())
307+
.setFiredAt(triggerCtx.firedAt())
299308
.setRound(state.round())
300309
.setFinishedAt(finishedAt)
301310
.build());
302311
}
303312

304313
protected final void onResult(@NotNull ExecutionContext<OUT> executionContext, @Nullable Throwable asyncCause) {
305314
final ExecutionContextInternal<OUT> ctx = (ExecutionContextInternal<OUT>) executionContext;
306-
final TriggerTransitionContext triggerContext = TriggerContextFactory.executed(ctx.triggerContext());
315+
final TriggerContext triggerContext = TriggerContextFactory.executed(ctx.triggerContext());
307316
final Instant finishedAt = state.markFinished(triggerContext.tick());
308317
log(finishedAt, "On result", triggerContext.tick(), ctx.round());
309318
if (asyncCause instanceof TimeoutException) {
310-
LOGGER.warn(genMsg(state.tick(), state.round(), finishedAt, asyncCause.getMessage()));
319+
LOGGER.warn(genMsg(triggerContext.tick(), ctx.round(), finishedAt, asyncCause.getMessage()));
311320
} else if (asyncCause != null) {
312321
LOGGER.error(genMsg(triggerContext.tick(), ctx.round(), finishedAt, "System error"), asyncCause);
313322
}
@@ -325,7 +334,7 @@ protected final void onResult(@NotNull ExecutionContext<OUT> executionContext, @
325334
.setError(state.addError(ctx.round(),
326335
Optional.ofNullable(ctx.error()).orElse(asyncCause)))
327336
.build());
328-
final TriggerTransitionContext transitionCtx = shouldStop(triggerContext, ctx.isForceStop(), ctx.round());
337+
final TriggerContext transitionCtx = shouldStop(triggerContext, ctx.isForceStop(), ctx.round());
329338
if (transitionCtx.isStopped()) {
330339
doStop(state.timerId(), transitionCtx);
331340
}

core/src/main/java/io/github/zero88/schedulerx/impl/ExecutionContextImpl.java

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -5,22 +5,23 @@
55

66
import org.jetbrains.annotations.NotNull;
77

8+
import io.github.zero88.schedulerx.trigger.TriggerContext;
89
import io.vertx.core.Promise;
910
import io.vertx.core.Vertx;
1011

1112
final class ExecutionContextImpl<OUTPUT> implements ExecutionContextInternal<OUTPUT> {
1213

1314
private final Vertx vertx;
1415
private final long round;
15-
private final TriggerTransitionContext triggerContext;
16+
private final TriggerContext triggerContext;
1617
private final Instant triggeredAt;
1718
private Instant executedAt;
1819
private Promise<Object> promise;
1920
private OUTPUT data;
2021
private Throwable error;
2122
private boolean forceStop = false;
2223

23-
ExecutionContextImpl(Vertx vertx, TriggerTransitionContext triggerContext, long round) {
24+
ExecutionContextImpl(Vertx vertx, TriggerContext triggerContext, long round) {
2425
this.vertx = vertx;
2526
this.round = round;
2627
this.triggerContext = triggerContext;
@@ -37,9 +38,11 @@ final class ExecutionContextImpl<OUTPUT> implements ExecutionContextInternal<OUT
3738
return this;
3839
}
3940

40-
public @NotNull Vertx vertx() { return this.vertx; }
41+
@Override
42+
public @NotNull Vertx vertx() { return this.vertx; }
4143

42-
public @NotNull TriggerTransitionContext triggerContext() { return this.triggerContext; }
44+
@Override
45+
public @NotNull TriggerContext triggerContext() { return this.triggerContext; }
4346

4447
@Override
4548
public @NotNull Instant triggeredAt() { return this.triggeredAt; }

core/src/main/java/io/github/zero88/schedulerx/impl/ExecutionContextInternal.java

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,8 +8,6 @@
88

99
interface ExecutionContextInternal<OUTPUT> extends ExecutionContext<OUTPUT> {
1010

11-
@NotNull TriggerTransitionContext triggerContext();
12-
1311
/**
1412
* Prepare to execute job
1513
*

core/src/main/java/io/github/zero88/schedulerx/impl/ExecutionResultImpl.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -147,7 +147,7 @@ public ExecutionResultBuilder<OUTPUT> setRound(long round) {
147147
}
148148

149149
public ExecutionResultBuilder<OUTPUT> setTriggerContext(TriggerContext triggerContext) {
150-
this.triggerContext = TriggerContextFactory.convert(triggerContext);
150+
this.triggerContext = triggerContext;
151151
return this;
152152
}
153153

0 commit comments

Comments
 (0)