Skip to content

Commit

Permalink
♻️ refactor scheduling to use injected TaskScheduler instance
Browse files Browse the repository at this point in the history
Signed-off-by: Marcus Fihlon <[email protected]>
  • Loading branch information
McPringle committed Mar 27, 2024
1 parent b378f33 commit 79f0a8c
Show file tree
Hide file tree
Showing 6 changed files with 69 additions and 26 deletions.
18 changes: 13 additions & 5 deletions src/main/java/swiss/fihlon/apus/service/ConferenceService.java
Original file line number Diff line number Diff line change
Expand Up @@ -17,32 +17,40 @@
*/
package swiss.fihlon.apus.service;

import org.springframework.scheduling.annotation.Scheduled;
import jakarta.annotation.PreDestroy;
import org.jetbrains.annotations.NotNull;
import org.springframework.scheduling.TaskScheduler;
import org.springframework.stereotype.Service;
import swiss.fihlon.apus.conference.Session;

import java.time.Duration;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.temporal.ChronoUnit;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.UUID;
import java.util.concurrent.ScheduledFuture;

import static java.util.stream.Collectors.groupingBy;

@Service
public final class ConferenceService {

private static final Duration UPDATE_FREQUENCY = Duration.ofMinutes(5);

private final ScheduledFuture<?> updateScheduler;
private List<Session> sessions;

public ConferenceService() {
public ConferenceService(@NotNull final TaskScheduler taskScheduler) {
updateSessions();
updateScheduler = taskScheduler.scheduleAtFixedRate(this::updateSessions, UPDATE_FREQUENCY);
}

@Scheduled(fixedRate = 300_000) // every five minutes
private void scheduler() {
updateSessions();
@PreDestroy
public void stopUpdateScheduler() {
updateScheduler.cancel(true);
}

private void updateSessions() {
Expand Down
29 changes: 20 additions & 9 deletions src/main/java/swiss/fihlon/apus/service/SocialService.java
Original file line number Diff line number Diff line change
Expand Up @@ -17,41 +17,52 @@
*/
package swiss.fihlon.apus.service;

import org.springframework.scheduling.annotation.Scheduled;
import jakarta.annotation.PreDestroy;
import org.jetbrains.annotations.NotNull;
import org.springframework.scheduling.TaskScheduler;
import org.springframework.stereotype.Service;
import swiss.fihlon.apus.social.Message;
import swiss.fihlon.apus.social.mastodon.MastodonAPI;

import java.time.Duration;
import java.util.Collections;
import java.util.List;
import java.util.concurrent.ScheduledFuture;

@Service
public final class SocialService {

private static final Duration UPDATE_FREQUENCY = Duration.ofMinutes(1);

private final ScheduledFuture<?> updateScheduler;
private final MastodonAPI mastodonAPI;
private List<Message> messages;
private List<Message> messages = List.of();

public SocialService() {
public SocialService(@NotNull final TaskScheduler taskScheduler) {
mastodonAPI = new MastodonAPI("ijug.social");
updateMessages();
updateScheduler = taskScheduler.scheduleAtFixedRate(this::updateMessages, UPDATE_FREQUENCY);
}

@Scheduled(fixedRate = 60_000)
private void scheduler() {
updateMessages();
@PreDestroy
public void stopUpdateScheduler() {
updateScheduler.cancel(true);
}

private void updateMessages() {
final var newMessages = mastodonAPI.getMessages("hackergarten");
final var newMessages = mastodonAPI.getMessages("duke");
synchronized (this) {
messages = newMessages;
}
}

public List<Message> getMessages(final int limit) {
synchronized (this) {
final int toIndex = limit > 0 && limit < messages.size() ? limit : messages.size() - 1;
return Collections.unmodifiableList(limit == 0 ? messages : messages.subList(0, toIndex));
if (limit <= 0 || messages.isEmpty()) {
return Collections.unmodifiableList(messages);
}
final int toIndex = limit < messages.size() ? limit : messages.size() - 1;
return Collections.unmodifiableList(messages.subList(0, toIndex));
}
}

Expand Down
19 changes: 15 additions & 4 deletions src/main/java/swiss/fihlon/apus/ui/view/ConferenceView.java
Original file line number Diff line number Diff line change
Expand Up @@ -21,39 +21,48 @@
import com.vaadin.flow.component.html.Div;
import com.vaadin.flow.component.html.H2;
import org.jetbrains.annotations.NotNull;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.scheduling.TaskScheduler;
import org.springframework.stereotype.Component;
import swiss.fihlon.apus.conference.Session;
import swiss.fihlon.apus.service.ConferenceService;

import java.time.Duration;
import java.util.concurrent.ScheduledFuture;
import java.util.concurrent.atomic.AtomicInteger;

@Component
@CssImport(value = "./themes/apus/views/conference-view.css")
public final class ConferenceView extends Div {

private static final int MAX_SESSIONS_IN_VIEW = 15;
private static final Duration UPDATE_FREQUENCY = Duration.ofMinutes(1);

private final transient ConferenceService conferenceService;
private final Div sessionContainer = new Div();

public ConferenceView(@NotNull final ConferenceService conferenceService) {
public ConferenceView(@NotNull final ConferenceService conferenceService,
@NotNull final TaskScheduler taskScheduler) {
this.conferenceService = conferenceService;
setId("conference-view");
add(new H2("Agenda"));
add(sessionContainer);
updateConferenceSessions();
final ScheduledFuture<?> updateScheduler = taskScheduler.scheduleAtFixedRate(this::updateScheduler, UPDATE_FREQUENCY);
addDetachListener(event -> updateScheduler.cancel(true));
}

@Scheduled(fixedRate = 60_000)
private void scheduler() {
private void updateScheduler() {
getUI().ifPresent(ui -> ui.access(this::updateConferenceSessions));
}

private void updateConferenceSessions() {
sessionContainer.removeAll();
var sessionCounter = new AtomicInteger(0);
addRunningSessions(sessionCounter);
addNextSessions(sessionCounter);
}

private void addRunningSessions(@NotNull final AtomicInteger sessionCounter) {
final var runningSessions = conferenceService.getRunningSessions();
for (final Session session : runningSessions) {
final var sessionView = new SessionView(session);
Expand All @@ -63,7 +72,9 @@ private void updateConferenceSessions() {
break;
}
}
}

private void addNextSessions(@NotNull final AtomicInteger sessionCounter) {
// There is space for 15 sessions on the screen, 5 rows with 3 sessions each.
// Fill up free space with next sessions.
if (sessionCounter.get() < MAX_SESSIONS_IN_VIEW) {
Expand Down
15 changes: 11 additions & 4 deletions src/main/java/swiss/fihlon/apus/ui/view/SocialView.java
Original file line number Diff line number Diff line change
Expand Up @@ -21,28 +21,35 @@
import com.vaadin.flow.component.html.Div;
import com.vaadin.flow.component.html.H2;
import org.jetbrains.annotations.NotNull;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.scheduling.TaskScheduler;
import org.springframework.stereotype.Component;
import swiss.fihlon.apus.service.SocialService;
import swiss.fihlon.apus.social.Message;

import java.time.Duration;
import java.util.concurrent.ScheduledFuture;

@Component
@CssImport(value = "./themes/apus/views/social-view.css")
public final class SocialView extends Div {

private static final Duration UPDATE_FREQUENCY = Duration.ofMinutes(1);

private final transient SocialService socialService;
private final Div messageContainer = new Div();

public SocialView(@NotNull final SocialService socialService) {
public SocialView(@NotNull final SocialService socialService,
@NotNull final TaskScheduler taskScheduler) {
this.socialService = socialService;
setId("social-view");
add(new H2("#JavaLand on Mastodon"));
add(messageContainer);
updateMessages();
final ScheduledFuture<?> updateScheduler = taskScheduler.scheduleAtFixedRate(this::updateScheduler, UPDATE_FREQUENCY);
addDetachListener(event -> updateScheduler.cancel(true));
}

@Scheduled(fixedRate = 60_000)
private void scheduler() {
private void updateScheduler() {
getUI().ifPresent(ui -> ui.access(this::updateMessages));
}

Expand Down
11 changes: 8 additions & 3 deletions src/main/java/swiss/fihlon/apus/ui/view/SocialWallView.java
Original file line number Diff line number Diff line change
Expand Up @@ -21,15 +21,20 @@
import com.vaadin.flow.component.html.Div;
import com.vaadin.flow.router.Route;
import org.jetbrains.annotations.NotNull;
import org.springframework.scheduling.TaskScheduler;
import swiss.fihlon.apus.service.ConferenceService;
import swiss.fihlon.apus.service.SocialService;

@Route("")
@CssImport(value = "./themes/apus/views/social-wall-view.css")
public final class SocialWallView extends Div {

public SocialWallView(@NotNull final ConferenceView conferenceview,
@NotNull final SocialView socialView) {
public SocialWallView(@NotNull final ConferenceService conferenceService,
@NotNull final SocialService socialService,
@NotNull final TaskScheduler taskScheduler) {
setId("social-wall-view");
add(conferenceview, socialView);
add(new ConferenceView(conferenceService, taskScheduler),
new SocialView(socialService, taskScheduler));
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -18,14 +18,15 @@
package swiss.fihlon.apus.service;

import org.junit.jupiter.api.Test;
import org.springframework.scheduling.support.NoOpTaskScheduler;

import static org.junit.jupiter.api.Assertions.assertEquals;

class ConferenceServiceTest {

@Test
void displaySampleData() {
final ConferenceService conferenceService = new ConferenceService();
final ConferenceService conferenceService = new ConferenceService(new NoOpTaskScheduler());
final var runningSessions = conferenceService.getRunningSessions();
assertEquals(15, runningSessions.size());
final var nextSessions = conferenceService.getNextSessions();
Expand Down

0 comments on commit 79f0a8c

Please sign in to comment.