[AB-209] adding cleanup job for old embedded messages, this job deletes the entries from the database and removes reactions

reducing thread count for listener executor and scheduling
fixing channel deletion listener not being part of a transaction
This commit is contained in:
Sheldan
2021-04-06 20:23:26 +02:00
parent 61d16d5985
commit e7b1fbe9d1
21 changed files with 280 additions and 10 deletions

View File

@@ -10,6 +10,7 @@ import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.core.task.TaskExecutor;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.transaction.event.TransactionalEventListener;
import javax.annotation.Nonnull;
@@ -32,8 +33,16 @@ public class AsyncAChannelDeletedListenerBean extends ListenerAdapter {
@Qualifier("aChannelDeletedExecutor")
private TaskExecutor channelDeletedExecutor;
@Autowired
private AsyncAChannelDeletedListenerBean self;
@Override
public void onTextChannelDelete(@Nonnull TextChannelDeleteEvent event) {
self.deleteChannelInDb(event);
}
@Transactional
public void deleteChannelInDb(TextChannelDeleteEvent event) {
channelManagementService.markAsDeleted(event.getChannel().getIdLong());
}

View File

@@ -3,6 +3,7 @@ package dev.sheldan.abstracto.core.service;
import dev.sheldan.abstracto.core.metric.service.CounterMetric;
import dev.sheldan.abstracto.core.metric.service.MetricService;
import dev.sheldan.abstracto.core.metric.service.MetricTag;
import dev.sheldan.abstracto.core.models.ServerChannelMessage;
import dev.sheldan.abstracto.core.models.cache.CachedMessage;
import dev.sheldan.abstracto.core.models.database.AChannel;
import dev.sheldan.abstracto.core.models.database.AUserInAServer;
@@ -18,8 +19,12 @@ import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import javax.annotation.PostConstruct;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Map;
import java.util.concurrent.CompletableFuture;
import java.util.stream.Collectors;
import static dev.sheldan.abstracto.core.config.MetricConstants.DISCORD_API_INTERACTION_METRIC;
import static dev.sheldan.abstracto.core.config.MetricConstants.INTERACTION_TYPE;
@@ -40,6 +45,9 @@ public class MessageServiceBean implements MessageService {
@Autowired
private MetricService metricService;
@Autowired
private GuildService guildService;
public static final CounterMetric MESSAGE_SEND_METRIC = CounterMetric
.builder()
.name(DISCORD_API_INTERACTION_METRIC)
@@ -110,6 +118,26 @@ public class MessageServiceBean implements MessageService {
.thenCompose(o -> channelService.sendTextToChannel(text, o));
}
@Override
public List<CompletableFuture<Message>> retrieveMessages(List<ServerChannelMessage> messages) {
List<CompletableFuture<Message>> messageFutures = new ArrayList<>();
Map<Long, List<ServerChannelMessage>> serverMessages = messages
.stream()
.collect(Collectors.groupingBy(ServerChannelMessage::getServerId));
serverMessages.forEach((serverId, channelMessagesNonGrouped) -> {
Guild guild = guildService.getGuildById(serverId);
Map<Long, List<ServerChannelMessage>> channelMessages = channelMessagesNonGrouped
.stream()
.collect(Collectors.groupingBy(ServerChannelMessage::getChannelId));
channelMessages.forEach((channelId, serverChannelMessages) -> {
MessageChannel channel = guild.getTextChannelById(channelId);
serverChannelMessages.forEach(serverChannelMessage ->
messageFutures.add(channelService.retrieveMessageInChannel(channel, serverChannelMessage.getMessageId())));
});
});
return messageFutures;
}
@Override
public CompletableFuture<Message> sendTemplateToUser(User user, String template, Object model) {
String message = templateService.renderTemplate(template, model);

View File

@@ -11,6 +11,7 @@ import dev.sheldan.abstracto.core.models.cache.CachedMessage;
import dev.sheldan.abstracto.core.models.cache.CachedReaction;
import dev.sheldan.abstracto.core.models.database.AEmote;
import dev.sheldan.abstracto.core.service.management.EmoteManagementService;
import dev.sheldan.abstracto.core.utils.CompletableFutureList;
import dev.sheldan.abstracto.core.utils.FutureUtils;
import lombok.extern.slf4j.Slf4j;
import net.dv8tion.jda.api.entities.*;
@@ -316,6 +317,15 @@ public class ReactionServiceBean implements ReactionService {
);
}
@Override
public CompletableFuture<Void> removeReactionOfUserFromMessageWithFuture(AEmote emote, Long serverId, Long channelId, Long messageId) {
Integer emoteId = emote.getId();
CompletableFuture<Message> messageFuture = channelService.retrieveMessageInChannel(serverId, channelId, messageId);
return messageFuture.thenCompose(message ->
self.removeReactionFromMessageWithFuture(emoteId, message)
);
}
@Override
public CompletableFuture<Void> removeReactionOfUserFromMessageWithFuture(AEmote emote, Long serverId, Long channelId, Long messageId, Member member) {
Integer emoteId = emote.getId();
@@ -374,6 +384,44 @@ public class ReactionServiceBean implements ReactionService {
return futures;
}
@Override
public List<CompletableFuture<Void>> removeReactionFromMessagesWithFuture(List<Message> messages, Integer emoteId) {
AEmote emote = emoteManagementService.loadEmote(emoteId);
return removeReactionFromMessagesWithFuture(messages, emote);
}
@Override
public List<CompletableFuture<Void>> removeReactionFromMessagesWithFuture(List<Message> messages, AEmote emote) {
List<CompletableFuture<Void>> removalFutures = new ArrayList<>();
messages.forEach(message -> removalFutures.add(removeReactionFromMessageWithFuture(emote, message)));
return removalFutures;
}
@Override
public CompletableFutureList<Void> removeReactionFromMessagesWithFutureWithFutureList(List<Message> messages, Integer emoteId) {
List<CompletableFuture<Void>> allFutures = removeReactionFromMessagesWithFuture(messages, emoteId);
return new CompletableFutureList<>(allFutures);
}
@Override
public CompletableFutureList<Void> removeReactionFromMessagesWithFutureWithFutureList(List<Message> messages, String emoteKey) {
List<CompletableFuture<Void>> allFutures = removeReactionFromMessagesWithFuture(messages, emoteKey);
return new CompletableFutureList<>(allFutures);
}
@Override
public List<CompletableFuture<Void>> removeReactionFromMessagesWithFuture(List<Message> messages, String emoteKey) {
AEmote emote = emoteService.getEmoteOrDefaultEmote(emoteKey, messages.get(0).getGuild().getIdLong());
return removeReactionFromMessagesWithFuture(messages, emote);
}
@Override
public CompletableFutureList<Void> removeReactionFromMessagesWithFutureWithFutureList(List<Message> messages, AEmote emote) {
List<CompletableFuture<Void>> removalFutures = new ArrayList<>();
messages.forEach(message -> removalFutures.add(removeReactionFromMessageWithFuture(emote, message)));
return new CompletableFutureList<>(removalFutures);
}
@PostConstruct
public void postConstruct() {
metricService.registerCounter(REACTION_ADDED_METRIC, "Reactions added");

View File

@@ -1,8 +1,3 @@
abstracto.listener.default.maxPoolSize=5
abstracto.listener.default.maxPoolSize=2
abstracto.listener.default.corePoolSize=1
abstracto.listener.default.keepAliveSeconds=60
abstracto.listener.joinListener.maxPoolSize=5
abstracto.listener.joinListener.corePoolSize=1
abstracto.listener.joinListener.keepAliveSeconds=60

View File

@@ -1,5 +1,6 @@
package dev.sheldan.abstracto.core.service;
import dev.sheldan.abstracto.core.models.ServerChannelMessage;
import dev.sheldan.abstracto.core.models.cache.CachedMessage;
import dev.sheldan.abstracto.core.models.database.AChannel;
import dev.sheldan.abstracto.core.models.database.AUserInAServer;
@@ -11,6 +12,7 @@ import net.dv8tion.jda.api.entities.User;
import net.dv8tion.jda.api.requests.restaction.AuditableRestAction;
import net.dv8tion.jda.api.requests.restaction.MessageAction;
import java.util.List;
import java.util.concurrent.CompletableFuture;
public interface MessageService {
@@ -22,6 +24,7 @@ public interface MessageService {
void updateStatusMessage(MessageChannel channel, Long messageId, MessageToSend messageToSend);
CompletableFuture<Message> sendMessageToUser(AUserInAServer userInAServer, String text);
CompletableFuture<Message> sendSimpleTemplateToUser(Long userId, String templateKey);
List<CompletableFuture<Message>> retrieveMessages(List<ServerChannelMessage> messages);
CompletableFuture<Message> sendTemplateToUser(User user, String template, Object model);
CompletableFuture<Void> sendEmbedToUser(User user, String template, Object model);
CompletableFuture<Message> sendEmbedToUserWithMessage(User user, String template, Object model);

View File

@@ -5,6 +5,7 @@ import dev.sheldan.abstracto.core.models.cache.CachedEmote;
import dev.sheldan.abstracto.core.models.cache.CachedMessage;
import dev.sheldan.abstracto.core.models.cache.CachedReaction;
import dev.sheldan.abstracto.core.models.database.AEmote;
import dev.sheldan.abstracto.core.utils.CompletableFutureList;
import net.dv8tion.jda.api.entities.*;
import java.util.List;
@@ -42,6 +43,7 @@ public interface ReactionService {
CompletableFuture<Void> clearReactionFromMessageWithFuture(Integer emoteId, Message message);
CompletableFuture<Void> removeReactionFromMessageWithFuture(AEmote emote, Long serverId, Long channelId, Long messageId);
CompletableFuture<Void> removeReactionOfUserFromMessageWithFuture(AEmote emote, Long serverId, Long channelId, Long messageId, Long userId);
CompletableFuture<Void> removeReactionOfUserFromMessageWithFuture(AEmote emote, Long serverId, Long channelId, Long messageId);
CompletableFuture<Void> removeReactionOfUserFromMessageWithFuture(AEmote emote, Long serverId, Long channelId, Long messageId, Member member);
CompletableFuture<Void> removeReactionOfUserFromMessageWithFuture(AEmote emote, Message message, Member member);
CompletableFuture<Void> removeReactionOfUserFromMessageWithFuture(Integer emoteId, Message message, Member member);
@@ -49,4 +51,10 @@ public interface ReactionService {
CompletableFuture<Void> removeReactionOfUserFromMessageWithFuture(Integer emoteId, Message message, Long userId);
CompletableFuture<Void> clearReactionFromMessageWithFuture(AEmote emote, Long serverId, Long channelId, Long messageId);
List<CompletableFuture<Void>> addReactionsToMessageWithFuture(List<String> emoteKeys, Long serverId, Message message);
List<CompletableFuture<Void>> removeReactionFromMessagesWithFuture(List<Message> messages, Integer emoteId);
List<CompletableFuture<Void>> removeReactionFromMessagesWithFuture(List<Message> messages, AEmote emote);
CompletableFutureList<Void> removeReactionFromMessagesWithFutureWithFutureList(List<Message> messages, Integer emoteId);
CompletableFutureList<Void> removeReactionFromMessagesWithFutureWithFutureList(List<Message> messages, String emoteKey);
List<CompletableFuture<Void>> removeReactionFromMessagesWithFuture(List<Message> messages, String emoteKey);
CompletableFutureList<Void> removeReactionFromMessagesWithFutureWithFutureList(List<Message> messages, AEmote emote);
}

View File

@@ -40,7 +40,11 @@ public class CompletableFutureList<T> {
if(!future.isCompletedExceptionally()) {
result.add(future.join());
} else {
log.warn("Future completed with exception {}.", future.join());
try {
future.join();
} catch (Exception exception) {
log.warn("Future completed with exception.", exception);
}
}
});
return result;