replaced a bunch of places where the database loaded objects were referenced across threads, this might have lead to problems when lazy loading them

fixed starboard post template
fixed starboard post deletion
This commit is contained in:
Sheldan
2020-05-09 16:15:07 +02:00
parent 8db1cead57
commit da8fea34da
23 changed files with 181 additions and 122 deletions

View File

@@ -37,8 +37,11 @@ public class MessageEmbedListener implements MessageReceivedListener {
List<MessageEmbedLink> links = messageEmbedService.getLinksInMessage(messageRaw);
for (MessageEmbedLink messageEmbedLink : links) {
messageRaw = messageRaw.replace(messageEmbedLink.getWholeUrl(), "");
AUserInAServer cause = userInServerManagementService.loadUser(message.getMember());
Consumer<CachedMessage> cachedMessageConsumer = cachedMessage -> messageEmbedService.embedLink(cachedMessage, message.getTextChannel(), cause, message);
Long cause = userInServerManagementService.loadUser(message.getMember()).getUserInServerId();
Consumer<CachedMessage> cachedMessageConsumer = cachedMessage -> {
AUserInAServer userInAServer = userInServerManagementService.loadUser(cause);
messageEmbedService.embedLink(cachedMessage, message.getTextChannel(), userInAServer , message);
};
messageCache.getMessageFromCache(messageEmbedLink.getServerId(), messageEmbedLink.getChannelId(), messageEmbedLink.getMessageId()).thenAccept(cachedMessageConsumer)
.exceptionally(throwable -> {
log.error("Error when embedding link for message {}", message.getId(), throwable);

View File

@@ -55,9 +55,10 @@ public class MessageEmbedRemovalReactionListener implements ReactedAddedListener
if(embeddedMessage.getEmbeddedUser().getUserReference().getId().equals(userReacting.getId())
|| embeddedMessage.getEmbeddingUser().getUserReference().getId().equals(userReacting.getId())
) {
messageService.deleteMessageInChannelInServer(message.getServerId(), message.getChannelId(), message.getMessageId()).thenAccept(aVoid ->
messageEmbedPostManagementService.deleteEmbeddedMessageTransactional(embeddedMessage)
);
messageService.deleteMessageInChannelInServer(message.getServerId(), message.getChannelId(), message.getMessageId()).thenAccept(aVoid ->{
Optional<EmbeddedMessage> innerOptional = messageEmbedPostManagementService.findEmbeddedPostByMessageId(message.getMessageId());
innerOptional.ifPresent(value -> messageEmbedPostManagementService.deleteEmbeddedMessageTransactional(value));
});
}
}

View File

@@ -6,7 +6,6 @@ import dev.sheldan.abstracto.core.listener.ReactedRemovedListener;
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.models.database.AUser;
import dev.sheldan.abstracto.core.models.database.AUserInAServer;
import dev.sheldan.abstracto.core.service.BotService;
import dev.sheldan.abstracto.core.service.EmoteService;
@@ -76,40 +75,43 @@ public class StarboardListener implements ReactedAddedListener, ReactedRemovedLi
private void updateStarboardPost(CachedMessage message, CachedReaction reaction, AUserInAServer userReacting, boolean adding) {
Optional<StarboardPost> starboardPostOptional = starboardPostManagementService.findByMessageId(message.getMessageId());
if(reaction != null) {
List<AUser> userExceptAuthor = getUsersExcept(reaction.getUsers(), message.getAuthorId());
AUserInAServer author = userInServerManagementService.loadUser(message.getServerId(), message.getAuthorId());
List<AUserInAServer> userExceptAuthor = getUsersExcept(reaction.getUserInServersIds(), author);
Double starMinimum = getFromConfig("starLvl1", message.getServerId());
if (userExceptAuthor.size() >= starMinimum) {
log.info("Post reached starboard minimum. Message {} in channel {} in server {} will be starred/updated.",
message.getMessageId(), message.getChannelId(), message.getServerId());
AUserInAServer author = userInServerManagementService.loadUser(message.getServerId(), message.getAuthorId());
if(starboardPostOptional.isPresent()) {
StarboardPost starboardPost = starboardPostOptional.get();
starboardPost.setIgnored(false);
starboardService.updateStarboardPost(starboardPost, message, userExceptAuthor);
if(adding) {
log.trace("Adding reactor {} from message {}", userReacting.getUserReference().getId(), message.getMessageId());
starboardPostReactorManagementService.addReactor(starboardPost, userReacting.getUserReference());
starboardPostReactorManagementService.addReactor(starboardPost, userReacting);
} else {
log.trace("Removing reactor {} from message {}", userReacting.getUserReference().getId(), message.getMessageId());
starboardPostReactorManagementService.removeReactor(starboardPost, userReacting.getUserReference());
starboardPostReactorManagementService.removeReactor(starboardPost, userReacting);
}
} else {
log.info("Creating starboard post for message {} in channel {} in server {}", message.getMessageId(), message.getChannelId(), message.getServerId());
starboardService.createStarboardPost(message, userExceptAuthor, userReacting, author);
}
} else {
log.info("Removing starboard post for message {} in channel {} in server {}. It fell under the threshold {}", message.getMessageId(), message.getChannelId(), message.getServerId(), starMinimum);
starboardPostOptional.ifPresent(this::completelyRemoveStarboardPost);
if(starboardPostOptional.isPresent()) {
log.info("Removing starboard post for message {} in channel {} in server {}. It fell under the threshold {}", message.getMessageId(), message.getChannelId(), message.getServerId(), starMinimum);
starboardPostOptional.ifPresent(this::completelyRemoveStarboardPost);
}
}
} else {
log.info("Removing starboard post for message {} in channel {} in server {}", message.getMessageId(), message.getChannelId(), message.getServerId());
starboardPostOptional.ifPresent(this::completelyRemoveStarboardPost);
if(starboardPostOptional.isPresent()) {
log.info("Removing starboard post for message {} in channel {} in server {}", message.getMessageId(), message.getChannelId(), message.getServerId());
starboardPostOptional.ifPresent(this::completelyRemoveStarboardPost);
}
}
}
private void completelyRemoveStarboardPost(StarboardPost starboardPost) {
starboardPostReactorManagementService.removeReactors(starboardPost);
starboardService.removeStarboardPost(starboardPost);
starboardService.deleteStarboardMessagePost(starboardPost);
starboardPostManagementService.removePost(starboardPost);
}
@@ -127,7 +129,7 @@ public class StarboardListener implements ReactedAddedListener, ReactedRemovedLi
log.trace("User {} in server {} removed star reaction from message {} on starboard.",
userRemoving.getUserReference().getId(), userRemoving.getServerReference().getId(), message.getMessageId());
Optional<CachedReaction> reactionOptional = EmoteUtils.getReactionFromMessageByEmote(message, aEmote);
updateStarboardPost(message, reactionOptional.orElse(null), userRemoving, false);
updateStarboardPost(message, reactionOptional.orElse(null), userRemoving, false);
}
}
@@ -135,8 +137,8 @@ public class StarboardListener implements ReactedAddedListener, ReactedRemovedLi
return configManagementService.loadConfig(guildId, key).getDoubleValue();
}
private List<AUser> getUsersExcept(List<AUser> users, Long userId) {
return users.stream().filter(user -> !user.getId().equals(userId)).collect(Collectors.toList());
private List<AUserInAServer> getUsersExcept(List<Long> users, AUserInAServer author) {
return users.stream().filter(user -> !user.equals(author.getUserInServerId())).map(aLong -> userInServerManagementService.loadUser(aLong)).collect(Collectors.toList());
}
@Override

View File

@@ -1,6 +1,6 @@
package dev.sheldan.abstracto.utility.repository;
import dev.sheldan.abstracto.core.models.database.AUser;
import dev.sheldan.abstracto.core.models.database.AUserInAServer;
import dev.sheldan.abstracto.utility.models.database.StarboardPost;
import dev.sheldan.abstracto.utility.models.database.StarboardPostReaction;
import org.springframework.data.jpa.repository.JpaRepository;
@@ -13,7 +13,7 @@ import java.util.List;
public interface StarboardPostReactionRepository extends JpaRepository<StarboardPostReaction, Long> {
@QueryHints(@QueryHint(name = org.hibernate.annotations.QueryHints.CACHEABLE, value = "true"))
void deleteByReactorAndStarboardPost(AUser user, StarboardPost post);
void deleteByReactorAndStarboardPost(AUserInAServer user, StarboardPost post);
@QueryHints(@QueryHint(name = org.hibernate.annotations.QueryHints.CACHEABLE, value = "true"))
void deleteByStarboardPost(StarboardPost post);

View File

@@ -97,15 +97,18 @@ public class MessageEmbedServiceBean implements MessageEmbedService {
@Override
public void embedLinks(List<MessageEmbedLink> linksToEmbed, TextChannel target, AUserInAServer reason, Message embeddingMessage) {
linksToEmbed.forEach(messageEmbedLink ->
linksToEmbed.forEach(messageEmbedLink -> {
Long userInServerId = reason.getUserInServerId();
messageCache.getMessageFromCache(messageEmbedLink.getServerId(), messageEmbedLink.getChannelId(), messageEmbedLink.getMessageId())
.thenAccept(cachedMessage ->
self.embedLink(cachedMessage, target, reason, embeddingMessage)
.thenAccept(cachedMessage -> {
AUserInAServer cause = userInServerManagementService.loadUser(userInServerId);
self.embedLink(cachedMessage, target, cause, embeddingMessage);
}
).exceptionally(throwable -> {
log.error("Message retrieval from cache failed for message {}.", messageEmbedLink.getMessageId(), throwable);
return null;
})
);
});
});
}
@Override
@@ -116,10 +119,11 @@ public class MessageEmbedServiceBean implements MessageEmbedService {
List<CompletableFuture<Message>> completableFutures = channelService.sendMessageToSendToChannel(embed, target);
log.trace("Embedding message {} from channel {} from server {}, because of user {}", cachedMessage.getMessageId(),
cachedMessage.getChannelId(), cachedMessage.getServerId(), cause.getUserReference().getId());
Long userInServerId = cause.getUserInServerId();
CompletableFuture.allOf(completableFutures.toArray(new CompletableFuture[0])).thenAccept(aVoid -> {
try {
Message createdMessage = completableFutures.get(0).get();
messageEmbedPostManagementService.createMessageEmbed(cachedMessage, createdMessage, cause);
messageEmbedPostManagementService.createMessageEmbed(cachedMessage, createdMessage, userInServerManagementService.loadUser(userInServerId));
messageService.addReactionToMessage(REMOVAL_EMOTE, cachedMessage.getServerId(), createdMessage);
} catch (InterruptedException | ExecutionException e) {
log.error("Failed to post message embed.", e);

View File

@@ -1,9 +1,11 @@
package dev.sheldan.abstracto.utility.service;
import dev.sheldan.abstracto.core.service.management.ChannelManagementService;
import dev.sheldan.abstracto.core.service.management.PostTargetManagement;
import dev.sheldan.abstracto.core.models.AServerAChannelMessage;
import dev.sheldan.abstracto.core.models.cache.CachedMessage;
import dev.sheldan.abstracto.core.models.database.*;
import dev.sheldan.abstracto.core.service.management.UserInServerManagementService;
import dev.sheldan.abstracto.templating.model.MessageToSend;
import dev.sheldan.abstracto.core.service.BotService;
import dev.sheldan.abstracto.core.service.ConfigService;
@@ -22,6 +24,7 @@ import lombok.extern.slf4j.Slf4j;
import net.dv8tion.jda.api.entities.*;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Transactional;
import java.util.ArrayList;
import java.util.List;
@@ -62,31 +65,33 @@ public class StarboardServiceBean implements StarboardService {
@Autowired
private PostTargetManagement postTargetManagement;
@Autowired
private ChannelManagementService channelManagementService;
@Autowired
private UserInServerManagementService userInServerManagementService;
@Autowired
private EmoteService emoteService;
@Autowired
private StarboardServiceBean self;
@Override
public void createStarboardPost(CachedMessage message, List<AUser> userExceptAuthor, AUserInAServer userReacting, AUserInAServer starredUser) {
public void createStarboardPost(CachedMessage message, List<AUserInAServer> userExceptAuthor, AUserInAServer userReacting, AUserInAServer starredUser) {
StarboardPostModel starboardPostModel = buildStarboardPostModel(message, userExceptAuthor.size());
List<Long> userExceptAuthorIds = new ArrayList<>();
userExceptAuthor.forEach(aUserInAServer -> {
userExceptAuthorIds.add(aUserInAServer.getUserInServerId());
});
MessageToSend messageToSend = templateService.renderEmbedTemplate(STARBOARD_POST_TEMPLATE, starboardPostModel);
PostTarget starboard = postTargetManagement.getPostTarget(STARBOARD_POSTTARGET, message.getServerId());
List<CompletableFuture<Message>> completableFutures = postTargetService.sendEmbedInPostTarget(messageToSend, STARBOARD_POSTTARGET, message.getServerId());
Long starboardChannelId = starboard.getChannelReference().getId();
Long starredUserId = starredUser.getUserInServerId();
Long userReactingId = userReacting.getUserInServerId();
CompletableFuture.allOf(completableFutures.toArray(new CompletableFuture[0])).thenAccept(aVoid -> {
try {
Message message1 = completableFutures.get(0).get();
AServerAChannelMessage aServerAChannelMessage = AServerAChannelMessage
.builder()
.messageId(message1.getIdLong())
.channel(starboard.getChannelReference())
.server(userReacting.getServerReference())
.build();
StarboardPost starboardPost = starboardPostManagementService.createStarboardPost(message, starredUser, userReacting, aServerAChannelMessage);
userExceptAuthor.forEach(user ->
starboardPostReactorManagementService.addReactor(starboardPost, user)
);
} catch (InterruptedException | ExecutionException e) {
log.error("Failed to post messages.", e);
}
self.persistPost(message, userExceptAuthorIds, completableFutures, starboardChannelId, starredUserId, userReactingId);
}) .exceptionally(throwable -> {
log.error("Failed to create starboard post for message {} in channel {} in server {}", message.getMessageId(), message.getChannelId(), message.getServerId(), throwable);
return null;
@@ -94,6 +99,29 @@ public class StarboardServiceBean implements StarboardService {
}
@Transactional
public void persistPost(CachedMessage message, List<Long> userExceptAuthorIds, List<CompletableFuture<Message>> completableFutures, Long starboardChannelId, Long starredUserId, Long userReactingId) {
AUserInAServer innerStarredUser = userInServerManagementService.loadUser(starredUserId);
AUserInAServer innerUserReacting = userInServerManagementService.loadUser(userReactingId);
try {
AChannel starboardChannel = channelManagementService.loadChannel(starboardChannelId);
Message message1 = completableFutures.get(0).get();
AServerAChannelMessage aServerAChannelMessage = AServerAChannelMessage
.builder()
.messageId(message1.getIdLong())
.channel(starboardChannel)
.server(starboardChannel.getServer())
.build();
StarboardPost starboardPost = starboardPostManagementService.createStarboardPost(message, innerStarredUser, innerUserReacting, aServerAChannelMessage);
userExceptAuthorIds.forEach(aLong -> {
AUserInAServer user = userInServerManagementService.loadUser(aLong);
starboardPostReactorManagementService.addReactor(starboardPost, user);
});
} catch (InterruptedException | ExecutionException e) {
log.error("Failed to post messages.", e);
}
}
private StarboardPostModel buildStarboardPostModel(CachedMessage message, Integer starCount) {
Member member = botService.getMemberInServer(message.getServerId(), message.getAuthorId());
Optional<TextChannel> channel = botService.getTextChannelFromServer(message.getServerId(), message.getChannelId());
@@ -117,14 +145,19 @@ public class StarboardServiceBean implements StarboardService {
}
@Override
public void updateStarboardPost(StarboardPost post, CachedMessage message, List<AUser> userExceptAuthor) {
public void updateStarboardPost(StarboardPost post, CachedMessage message, List<AUserInAServer> userExceptAuthor) {
StarboardPostModel starboardPostModel = buildStarboardPostModel(message, userExceptAuthor.size());
MessageToSend messageToSend = templateService.renderEmbedTemplate(STARBOARD_POST_TEMPLATE, starboardPostModel);
List<CompletableFuture<Message>> futures = new ArrayList<>();
futures.add(new CompletableFuture<>());
postTargetService.editOrCreatedInPostTarget(post.getStarboardMessageId(), messageToSend, STARBOARD_POSTTARGET, message.getServerId(), futures);
Long starboardPostId = post.getId();
CompletableFuture.allOf(futures.toArray(new CompletableFuture[0])).thenAccept(aVoid -> {
try {
starboardPostManagementService.setStarboardPostMessageId(post, futures.get(0).get().getIdLong());
Optional<StarboardPost> innerPost = starboardPostManagementService.findByStarboardPostId(starboardPostId);
if(innerPost.isPresent()) {
starboardPostManagementService.setStarboardPostMessageId(innerPost.get(), futures.get(0).get().getIdLong());
}
} catch (InterruptedException | ExecutionException e) {
log.error("Failed to post starboard post.", e);
}
@@ -135,7 +168,7 @@ public class StarboardServiceBean implements StarboardService {
}
@Override
public void removeStarboardPost(StarboardPost message) {
public void deleteStarboardMessagePost(StarboardPost message) {
AChannel starboardChannel = message.getStarboardChannel();
botService.deleteMessage(starboardChannel.getServer().getId(), starboardChannel.getId(), message.getStarboardMessageId());
}

View File

@@ -56,6 +56,7 @@ public class SuggestionServiceBean implements SuggestionService {
Suggestion suggestion = suggestionManagementService.createSuggestion(member, text);
suggestionLog.setSuggestion(suggestion);
suggestionLog.setText(text);
Long suggestionId = suggestion.getId();
MessageToSend messageToSend = templateService.renderEmbedTemplate(SUGGESTION_LOG_TEMPLATE, suggestionLog);
long guildId = member.getGuild().getIdLong();
JDA instance = botService.getInstance();
@@ -63,16 +64,17 @@ public class SuggestionServiceBean implements SuggestionService {
if(guildById != null) {
List<CompletableFuture<Message>> completableFutures = postTargetService.sendEmbedInPostTarget(messageToSend, SUGGESTIONS_TARGET, guildId);
CompletableFuture.allOf(completableFutures.toArray(new CompletableFuture[0])).thenAccept(aVoid -> {
Suggestion innerSuggestion = suggestionManagementService.getSuggestion(suggestionId);
try {
Message message = completableFutures.get(0).get();
suggestionManagementService.setPostedMessage(suggestion, message);
suggestionManagementService.setPostedMessage(innerSuggestion, message);
messageService.addReactionToMessage(SUGGESTION_YES_EMOTE, guildId, message);
messageService.addReactionToMessage(SUGGESTION_NO_EMOTE, guildId, message);
} catch (InterruptedException | ExecutionException e) {
log.warn("Failed to post suggestion", e);
}
}) .exceptionally(throwable -> {
log.error("Failed to post suggestion {}", suggestion.getId(), throwable);
log.error("Failed to post suggestion {}", suggestionId, throwable);
return null;
});
} else {

View File

@@ -84,7 +84,7 @@ public class StarboardPostManagementServiceBean implements StarboardPostManageme
@Override
public void removePost(StarboardPost starboardPost) {
repository.deleteById(starboardPost.getId());
repository.delete(starboardPost);
}

View File

@@ -1,6 +1,6 @@
package dev.sheldan.abstracto.utility.service.management;
import dev.sheldan.abstracto.core.models.database.AUser;
import dev.sheldan.abstracto.core.models.database.AUserInAServer;
import dev.sheldan.abstracto.utility.models.database.StarboardPost;
import dev.sheldan.abstracto.utility.models.database.StarboardPostReaction;
import dev.sheldan.abstracto.utility.models.template.commands.starboard.StarStatsUser;
@@ -22,7 +22,7 @@ public class StarboardPostReactorManagementServiceBean implements StarboardPostR
private StarStatsUserConverter converter;
@Override
public void addReactor(StarboardPost post, AUser user) {
public void addReactor(StarboardPost post, AUserInAServer user) {
StarboardPostReaction reactor = StarboardPostReaction
.builder()
.starboardPost(post)
@@ -32,7 +32,7 @@ public class StarboardPostReactorManagementServiceBean implements StarboardPostR
}
@Override
public void removeReactor(StarboardPost post, AUser user) {
public void removeReactor(StarboardPost post, AUserInAServer user) {
repository.deleteByReactorAndStarboardPost(user, post);
}

View File

@@ -11,37 +11,37 @@
"r": 200,
"g": 0,
"b": 255
},
}
<#if message.content?has_content || message.embeds?size gt 0>
"description": "${message.content}
,"description": "${message.content}
<#list message.embeds>
<#include "starboard_post_embed_embeds_name">:
<#items as embed>
<#include "starboard_post_embed_description">: ${embed.description} <#if embed.imageUrl?has_content> <#include "starboard_post_embed_image_url">: ${embed.imageUrl} </#if>
</#items>
</#list>
",
"
</#if>
<#assign emote>${starLevelEmote}</#assign>
<#assign count>${starCount}</#assign>
<#assign messageId>${message.messageId?c}</#assign>
<#if channel?has_content>
<#assign channel>${channel.asMention}</#assign>
"additionalMessage": "<#include "starboard_post_embed_additional_message">",
<#assign channelMention>${channel.asMention}</#assign>
,"additionalMessage": "<#include "starboard_post_embed_additional_message">"
<#else>
<#assign channel>${aChannel.id?c}</#assign>
"additionalMessage": "<#include "starboard_post_embed_additional_message">",
<#assign channelMention>${aChannel.id?c}</#assign>
,"additionalMessage": "<#include "starboard_post_embed_additional_message">"
</#if>
<#if message.attachmentUrls?size gt 0>
"imageUrl": "${message.attachmentUrls[0]}",
,"imageUrl": "${message.attachmentUrls[0]}"
</#if>
"fields": [
,"fields": [
{
"name": "<#include "starboard_post_embed_original_field_title">",
"name": "<#include "starboard_post_embed_original_field_title">"
<#if channel?has_content>
"value": "[${channel.name}](${message.messageUrl})"
,"value": "[${channel.name}](${message.messageUrl})"
<#else>
"value": "[${aChannel.id?c}](${message.messageUrl})"
,"value": "[${aChannel.id?c}](${message.messageUrl})"
</#if>
}
],