Skip to content

Commit

Permalink
Improve event update scheduling
Browse files Browse the repository at this point in the history
  • Loading branch information
Alf-Melmac committed Aug 4, 2023
1 parent f536ffc commit 09e82a5
Show file tree
Hide file tree
Showing 2 changed files with 41 additions and 16 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ public class EventUpdateService {
private final MessageSource messageSource;

public void update(@NonNull EventUpdateSetting eventUpdateSetting) {
log.trace("Update");
log.trace("Update {}", eventUpdateSetting);
final Event event = eventUpdateSetting.event();

event.getDiscordInformation().forEach(discordInformation -> {
Expand Down
55 changes: 40 additions & 15 deletions src/main/java/de/webalf/slotbot/service/bot/EventUpdater.java
Original file line number Diff line number Diff line change
@@ -1,40 +1,50 @@
package de.webalf.slotbot.service.bot;

import de.webalf.slotbot.model.Event;
import de.webalf.slotbot.model.NotificationMap;
import de.webalf.slotbot.service.SchedulerService;
import lombok.Builder;
import lombok.NonNull;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;

import java.util.Map;
import java.util.concurrent.ScheduledFuture;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.Future;
import java.util.concurrent.TimeUnit;

import static de.webalf.slotbot.service.bot.EventUpdater.EventUpdateIdentifier.buildIdentifier;

/**
* Collects all event updates within a second and executes them in a single operation to prevent spamming the bot
* Delays and collects all updates to an event. The event is updated 5 seconds after the last update was received.
*
* @author Alf
* @since 10.05.2023
*/
@Service
@RequiredArgsConstructor
@Slf4j
public class EventUpdater {
private final SchedulerService schedulerService;
private final EventUpdateService eventUpdateService;

private static final Map<EventUpdateIdentifier, ScheduledFuture<?>> SCHEDULED_UPDATE = new NotificationMap<>();
private static final Map<Long, EventUpdate> SCHEDULED_UPDATE = new ConcurrentHashMap<>();

@Builder
record EventUpdateIdentifier(long eventId, boolean embed, boolean slotlist) {
static EventUpdateIdentifier buildIdentifier(@NonNull EventUpdateSetting eventUpdateSetting) {
return new EventUpdateIdentifier(eventUpdateSetting.event().getId(), eventUpdateSetting.embed(), eventUpdateSetting.slotlist());
private record EventUpdate(Future<?> future, boolean embed, boolean slotlist) {
/**
* Creates a new event update setting based on the current scheduled update and the given setting.
* This adds embed and slotlist updates to update everything at once.
*/
private EventUpdateSetting createSetting(@NonNull EventUpdateSetting setting) {
log.trace("Creating new event update setting {} - {} : {}", setting.event().getId(), embed || setting.embed(), slotlist || setting.slotlist());
return EventUpdateSetting.builder()
.event(setting.event())
.embed(embed || setting.embed())
.slotlist(slotlist || setting.slotlist())
.build();
}
}

/**
* Schedules an update for the given event (with settings) if it is {@link Event#isAssigned() assigned}.
*/
public void update(EventUpdateSetting eventUpdateSetting) {
if (eventUpdateSetting == null) {
return;
Expand All @@ -43,10 +53,25 @@ public void update(EventUpdateSetting eventUpdateSetting) {
if (event == null || !event.isAssigned()) {
return;
}
final long eventId = event.getId();

SCHEDULED_UPDATE.computeIfAbsent(buildIdentifier(eventUpdateSetting), k -> schedulerService.schedule(
() -> eventUpdateService.update(eventUpdateSetting),
() -> SCHEDULED_UPDATE.remove(k),
1, TimeUnit.SECONDS));
final EventUpdateSetting newSetting;
final EventUpdate update = SCHEDULED_UPDATE.get(eventId);
if (update != null) {
final Future<?> future = update.future();
if (future != null && !future.isDone()) {
log.trace("Cancel scheduled update for event {}", eventId);
future.cancel(false);
}
newSetting = update.createSetting(eventUpdateSetting);
} else {
newSetting = eventUpdateSetting;
}
SCHEDULED_UPDATE.put(eventId, new EventUpdate(schedulerService.schedule(
() -> eventUpdateService.update(newSetting),
() -> SCHEDULED_UPDATE.remove(eventId),
5, TimeUnit.SECONDS),
newSetting.embed(),
newSetting.slotlist()));
}
}

0 comments on commit 09e82a5

Please sign in to comment.