Skip to content

Commit db38285

Browse files
committed
Temp action bugfix and code improvement
* database returns multiple results, forgot limit(1) * logic mistake of using last expired action instead of last temp action (implicitly given by last action that passes the "not permanent" check) * can use `fetchOptional` with database * added note regarding startup race condition issue
1 parent a9c520a commit db38285

2 files changed

Lines changed: 21 additions & 22 deletions

File tree

application/src/main/java/org/togetherjava/tjbot/commands/moderation/ModerationActionsStore.java

Lines changed: 12 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -95,13 +95,15 @@ public ModerationActionsStore(@NotNull Database database) {
9595
// FIXME javadoc
9696
public @NotNull Optional<ActionRecord> findLastActionAgainstTargetByType(long guildId,
9797
long targetId, @NotNull ModerationAction actionType) {
98-
return Optional.of(database.read(context -> context
99-
.selectFrom(ModerationActions.MODERATION_ACTIONS)
100-
.where(ModerationActions.MODERATION_ACTIONS.GUILD_ID.eq(guildId)
101-
.and(ModerationActions.MODERATION_ACTIONS.TARGET_ID.eq(targetId)
102-
.and(ModerationActions.MODERATION_ACTIONS.ACTION_TYPE.eq(actionType.name()))))
103-
.orderBy(ModerationActions.MODERATION_ACTIONS.ISSUED_AT.desc())
104-
.fetchOne())).map(ActionRecord::of);
98+
return database
99+
.read(context -> context.selectFrom(ModerationActions.MODERATION_ACTIONS)
100+
.where(ModerationActions.MODERATION_ACTIONS.GUILD_ID.eq(guildId)
101+
.and(ModerationActions.MODERATION_ACTIONS.TARGET_ID.eq(targetId))
102+
.and(ModerationActions.MODERATION_ACTIONS.ACTION_TYPE.eq(actionType.name())))
103+
.orderBy(ModerationActions.MODERATION_ACTIONS.ISSUED_AT.desc())
104+
.limit(1)
105+
.fetchOptional())
106+
.map(ActionRecord::of);
105107
}
106108

107109
/**
@@ -111,10 +113,10 @@ public ModerationActionsStore(@NotNull Database database) {
111113
* @return the action with the given case id, if present
112114
*/
113115
public @NotNull Optional<ActionRecord> findActionByCaseId(int caseId) {
114-
return Optional
115-
.of(database.read(context -> context.selectFrom(ModerationActions.MODERATION_ACTIONS)
116+
return database
117+
.read(context -> context.selectFrom(ModerationActions.MODERATION_ACTIONS)
116118
.where(ModerationActions.MODERATION_ACTIONS.CASE_ID.eq(caseId))
117-
.fetchOne()))
119+
.fetchOptional())
118120
.map(ActionRecord::of);
119121
}
120122

application/src/main/java/org/togetherjava/tjbot/commands/moderation/temp/TemporaryModerationRoutine.java

Lines changed: 9 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -55,27 +55,22 @@ private void checkExpiredActions() {
5555
actionsStore.getExpiredActionsAscending()
5656
.stream()
5757
.filter(action -> typeToRevocableAction.containsKey(action.actionType()))
58-
.collect(Collectors.groupingBy(RevocationGroupIdentifier::of))
58+
.map(RevocationGroupIdentifier::of)
59+
.collect(Collectors.toSet())
5960
.forEach(this::processGroupedActions);
6061

6162
logger.debug("Finished checking expired temporary moderation actions to revoke.");
6263
}
6364

64-
private void processGroupedActions(@NotNull RevocationGroupIdentifier groupIdentifier,
65-
@NotNull Collection<ActionRecord> expiredActions) {
66-
// Last issued temporary action takes priority
67-
ActionRecord actionToRevoke = expiredActions.stream()
68-
.max(Comparator.comparing(ActionRecord::issuedAt))
69-
.orElseThrow();
70-
65+
private void processGroupedActions(@NotNull RevocationGroupIdentifier groupIdentifier) {
7166
// Do not revoke an action which was overwritten by a permanent action that was issued
7267
// afterwards
7368
// For example if a user was perm-banned after being temp-banned
74-
ActionRecord lastAction = actionsStore
69+
ActionRecord lastApplyAction = actionsStore
7570
.findLastActionAgainstTargetByType(groupIdentifier.guildId, groupIdentifier.targetId,
7671
groupIdentifier.type)
7772
.orElseThrow();
78-
if (lastAction.actionExpiresAt() == null) {
73+
if (lastApplyAction.actionExpiresAt() == null) {
7974
return;
8075
}
8176

@@ -88,7 +83,7 @@ private void processGroupedActions(@NotNull RevocationGroupIdentifier groupIdent
8883
.findLastActionAgainstTargetByType(groupIdentifier.guildId, groupIdentifier.targetId,
8984
revokeActionType)
9085
.orElseThrow();
91-
if (lastRevokeAction.issuedAt().isAfter(actionToRevoke.issuedAt())
86+
if (lastRevokeAction.issuedAt().isAfter(lastApplyAction.issuedAt())
9287
&& (lastRevokeAction.actionExpiresAt() == null
9388
|| lastRevokeAction.actionExpiresAt().isAfter(Instant.now()))) {
9489
return;
@@ -149,7 +144,9 @@ private void handleFailure(@NotNull Throwable failure,
149144
public void start() {
150145
// TODO This should be registered at some sort of routine system instead (see GH issue #235
151146
// which adds support for routines)
152-
checkExpiredActionsService.scheduleWithFixedDelay(this::checkExpiredActions, 0, 5,
147+
// NOTE The initial run has to be delayed until after the guild cache has been updated
148+
// (during CommandSystem startup)
149+
checkExpiredActionsService.scheduleWithFixedDelay(this::checkExpiredActions, 5, 5,
153150
TimeUnit.MINUTES);
154151
}
155152

0 commit comments

Comments
 (0)