Skip to content

Commit

Permalink
fix missing JavaDoc and lower logging again
Browse files Browse the repository at this point in the history
  • Loading branch information
krusche committed Feb 2, 2025
1 parent 9d3f143 commit 32a1f48
Show file tree
Hide file tree
Showing 4 changed files with 44 additions and 12 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,11 @@ public class TaskSchedulingConfiguration {

private static final Logger log = LoggerFactory.getLogger(TaskSchedulingConfiguration.class);

/**
* Create a Task Scheduler with virtual threads and a pool size of 4.
*
* @return the Task Scheduler bean that can be injected into any service to schedule tasks
*/
@Bean(name = "taskScheduler")
public TaskScheduler taskScheduler() {
log.debug("Creating Task Scheduler ");
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -86,6 +86,12 @@ public ScheduleService(ExerciseLifecycleService exerciseLifecycleService, Partic
this.taskScheduler = scheduler;
}

/**
* Get all scheduled exercise events.
*
* @param pageable the pagination information
* @return a page of scheduled exercise events
*/
public Page<ScheduledExerciseEvent> findAllExerciseEvents(Pageable pageable) {
// Flatten the map into a list of ScheduledExerciseEvent
var allEvents = scheduledExerciseTasks.entrySet().stream().flatMap(entry -> entry.getValue().stream().map(task -> {
Expand All @@ -102,22 +108,42 @@ public Page<ScheduledExerciseEvent> findAllExerciseEvents(Pageable pageable) {
return new PageImpl<>(paginatedEvents, pageable, allEvents.size());
}

/**
* Initializes and schedules periodic logging and cleanup tasks for scheduled exercises
* and participation tasks. This method is triggered automatically when the application
* is fully started.
*
* <p>
* Every 15 seconds, this method:
* <ul>
* <li>Logs the total number of scheduled exercise and participation tasks.</li>
* <li>Iterates through scheduled exercise tasks and logs their details, including
* execution time and state. It removes tasks that are no longer running.</li>
* <li>Iterates through scheduled participation tasks and logs their details,
* including execution time and state. It removes tasks that are no longer running.</li>
* <li>Cleans up empty entries from both task maps to avoid memory leaks.</li>
* </ul>
*
* <p>
* The scheduling mechanism ensures that outdated or completed tasks do not persist in
* memory unnecessarily while maintaining visibility into scheduled tasks.
*/
@EventListener(ApplicationReadyEvent.class)
public void startup() {
taskScheduler.scheduleAtFixedRate(() -> {
log.info("Number of scheduled Exercise Tasks: {}", scheduledExerciseTasks.values().stream().mapToLong(Set::size).sum());
log.debug("Number of scheduled Exercise Tasks: {}", scheduledExerciseTasks.values().stream().mapToLong(Set::size).sum());

// if the map is not empty and there is at least still one future in the values map, log the tasks and remove the ones that are not running anymore
if (!scheduledExerciseTasks.isEmpty() && scheduledExerciseTasks.values().stream().anyMatch(set -> !set.isEmpty())) {
log.info(" Scheduled Exercise Tasks:");
log.debug(" Scheduled Exercise Tasks:");
scheduledExerciseTasks.forEach((key, taskNames) -> {
taskNames.removeIf(taskName -> {
long delay = taskName.future().getDelay(TimeUnit.SECONDS);
var state = taskName.future().state();
Instant scheduledTime = Instant.now().plusSeconds(delay);
ZonedDateTime zonedScheduledTime = scheduledTime.atZone(systemDefault());
String formattedTime = zonedScheduledTime.format(formatter);
log.info(" Exercise: {}, Lifecycle: {}, Name: {}, Scheduled Run Time: {}, State: {}, Remaining Delay: {} s", key.exerciseId(), key.lifecycle(),
log.debug(" Exercise: {}, Lifecycle: {}, Name: {}, Scheduled Run Time: {}, State: {}, Remaining Delay: {} s", key.exerciseId(), key.lifecycle(),
taskName.name(), formattedTime, state, delay);
return state != Future.State.RUNNING;
});
Expand All @@ -127,19 +153,19 @@ public void startup() {
// clean up empty entries in the map
scheduledExerciseTasks.entrySet().removeIf(entry -> entry.getValue().isEmpty());

log.info("Number of scheduled Participation Tasks: {}", scheduledParticipationTasks.values().stream().mapToLong(Set::size).sum());
log.debug("Number of scheduled Participation Tasks: {}", scheduledParticipationTasks.values().stream().mapToLong(Set::size).sum());

// if the map is not empty and there is at least still one future in the values map, log the tasks and remove the ones that are not running anymore
if (!scheduledParticipationTasks.isEmpty() && scheduledParticipationTasks.values().stream().anyMatch(set -> !set.isEmpty())) {
log.info(" Scheduled Participation Tasks:");
log.debug(" Scheduled Participation Tasks:");
scheduledParticipationTasks.forEach((key, taskNames) -> {
taskNames.removeIf(taskName -> {
long delay = taskName.future().getDelay(TimeUnit.SECONDS);
var state = taskName.future().state();
Instant scheduledTime = Instant.now().plusSeconds(delay);
ZonedDateTime zonedScheduledTime = scheduledTime.atZone(systemDefault());
String formattedTime = zonedScheduledTime.format(formatter);
log.info(" Exercise: {}, Participation: {}, Lifecycle: {}, Name: {}, Scheduled Run Time: {}, State: {}, Remaining Delay: {} s", key.exerciseId(),
log.debug(" Exercise: {}, Participation: {}, Lifecycle: {}, Name: {}, Scheduled Run Time: {}, State: {}, Remaining Delay: {} s", key.exerciseId(),
key.participationId(), key.lifecycle(), taskName.name(), formattedTime, state, delay);
return state != Future.State.RUNNING;
});
Expand Down Expand Up @@ -215,6 +241,7 @@ public void scheduleExerciseTask(QuizExercise exercise, QuizBatch batch, Exercis
* @param exercise Exercise
* @param lifecycle ExerciseLifecycle
* @param scheduledTask One runnable tasks to be executed at the associated ZonedDateTimes
* @param name Name of the task
*/
public void scheduleExerciseTask(Exercise exercise, ExerciseLifecycle lifecycle, Tuple<ZonedDateTime, Runnable> scheduledTask, String name) {
// check if already scheduled for exercise. if so, cancel.
Expand Down Expand Up @@ -266,7 +293,7 @@ public void cancelScheduledTaskForLifecycle(Long exerciseId, ExerciseLifecycle l
var task = new ExerciseLifecycleKey(exerciseId, lifecycle);
var taskNames = scheduledExerciseTasks.get(task);
if (taskNames != null) {
log.info("Cancelling scheduled task {} for Exercise (#{}).", lifecycle, exerciseId);
log.debug("Cancelling scheduled task {} for Exercise (#{}).", lifecycle, exerciseId);
taskNames.forEach(taskName -> taskName.future().cancel(true));
removeScheduledExerciseTask(exerciseId, lifecycle);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ public ExerciseLifecycleService(@Qualifier("taskScheduler") TaskScheduler schedu
*/
public ScheduledFuture<?> scheduleTask(Exercise exercise, ZonedDateTime lifecycleDate, ExerciseLifecycle lifecycle, Runnable task) {
final ScheduledFuture<?> future = scheduler.schedule(task, lifecycleDate.toInstant());
log.info("Scheduled Task for Exercise \"{}\" (#{}) to trigger on {} - {}", exercise.getTitle(), exercise.getId(), lifecycle, lifecycleDate);
log.debug("Scheduled Task for Exercise \"{}\" (#{}) to trigger on {} - {}", exercise.getTitle(), exercise.getId(), lifecycle, lifecycleDate);
return future;
}

Expand Down Expand Up @@ -104,7 +104,7 @@ public Set<ScheduledFuture<?>> scheduleMultipleTasks(Exercise exercise, Exercise
var future = scheduler.schedule(task.second(), task.first().toInstant());
futures.add(future);
}
log.info("Scheduled {} Tasks for Exercise \"{}\" (#{}) to trigger on {}.", tasks.size(), exercise.getTitle(), exercise.getId(), lifecycle.toString());
log.debug("Scheduled {} Tasks for Exercise \"{}\" (#{}) to trigger on {}.", tasks.size(), exercise.getTitle(), exercise.getId(), lifecycle.toString());
return futures;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -297,7 +297,7 @@ private void scheduleTemplateCommitCombination(ProgrammingExercise exercise) {
if (exercise.getReleaseDate() != null) {
scheduleService.scheduleExerciseTask(exercise, ExerciseLifecycle.SHORTLY_BEFORE_RELEASE, () -> combineTemplateCommitsForExercise(exercise).run(),
"combine template commits");
log.info("Scheduled combining template commits before release date for Programming Exercise \"{}\" (#{}) for {}.", exercise.getTitle(), exercise.getId(),
log.info("Scheduled combining template commits before release date for programming exercise \"{}\" (#{}) for {}.", exercise.getTitle(), exercise.getId(),
exercise.getReleaseDate());
}
}
Expand Down Expand Up @@ -476,13 +476,13 @@ else if (now.isBefore(examDateService.getLatestIndividualExamEndDate(exam))) {
@NotNull
private Runnable combineTemplateCommitsForExercise(ProgrammingExercise exercise) {
return () -> {
log.info("Start combine template commits for programming exercise {}.", exercise.getId());
log.debug("Start combine template commits for programming exercise {}.", exercise.getId());
SecurityUtils.setAuthorizationObject();
try {
ProgrammingExercise programmingExerciseWithTemplateParticipation = programmingExerciseRepository
.findByIdWithTemplateAndSolutionParticipationElseThrow(exercise.getId());
gitService.combineAllCommitsOfRepositoryIntoOne(programmingExerciseWithTemplateParticipation.getTemplateParticipation().getVcsRepositoryUri());
log.info("Combined template repository commits of programming exercise {}.", programmingExerciseWithTemplateParticipation.getId());
log.debug("Combined template repository commits of programming exercise {}.", programmingExerciseWithTemplateParticipation.getId());
}
catch (GitAPIException e) {
log.error("Failed to communicate with GitService for combining template commits of exercise {}", exercise.getId(), e);
Expand Down

0 comments on commit 32a1f48

Please sign in to comment.