Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,6 @@
import com.bencodez.simpleapi.sql.DataType;
import com.bencodez.simpleapi.sql.data.DataValue;
import com.bencodez.simpleapi.sql.data.DataValueInt;
import com.bencodez.simpleapi.folialib.enums.EntityTaskResult;
import com.bencodez.votingplugin.VotingPluginMain;
import com.bencodez.votingplugin.util.BukkitCompletionScheduler;

Expand Down Expand Up @@ -634,10 +633,10 @@ private void runTransferApprovalEntityTask(org.bukkit.entity.Player player, Runn
BukkitCompletionScheduler.run(plugin, player, task, rejected);
return;
}
CompletableFuture<EntityTaskResult> result = plugin.getBukkitScheduler().getFoliaLib().getImpl()
CompletableFuture<?> result = plugin.getBukkitScheduler().getFoliaLib().getImpl()
.runAtEntityWithFallback(player, ignored -> task.run(), rejected);
result.whenComplete((status, failure) -> {
if (failure != null || status != EntityTaskResult.SUCCESS) rejected.run();
if (failure != null || !BukkitCompletionScheduler.isSuccessfulEntityTaskResult(status)) rejected.run();
});
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,11 +5,19 @@

import org.bukkit.entity.Player;

import com.bencodez.simpleapi.folialib.enums.EntityTaskResult;
import com.bencodez.votingplugin.VotingPluginMain;

/** Schedules exactly-once completion work with an entity-retirement fallback. */
public final class BukkitCompletionScheduler {

/**
* Checks Folia's entity-task completion without depending on its relocated enum type.
* The enum is shaded by SimpleAPI, so naming it directly breaks Eclipse workspace
* resolution when SimpleAPI is open as a source project.
*/
public static boolean isSuccessfulEntityTaskResult(Object status) {
return status instanceof Enum<?> result && "SUCCESS".equals(result.name());
}
private BukkitCompletionScheduler() {
}

Expand Down Expand Up @@ -49,12 +57,12 @@ public static void run(VotingPluginMain plugin, Player player, Runnable entityTa
runLegacyEntity(plugin, player, entityOnce, fallback);
return;
}
CompletableFuture<EntityTaskResult> result = plugin.getBukkitScheduler().getFoliaLib().getImpl()
CompletableFuture<?> result = plugin.getBukkitScheduler().getFoliaLib().getImpl()
.runAtEntityWithFallback(player, ignored -> entityOnce.run(), fallback);
result.whenComplete((status, failure) -> {
// ENTITY_RETIRED invokes fallback itself. A scheduler that was already
// retired returns SCHEDULER_RETIRED without invoking it.
if (failure != null || status != EntityTaskResult.SUCCESS) {
if (failure != null || !isSuccessfulEntityTaskResult(status)) {
fallback.run();
} else if (!executed.get()) {
// Compatibility with scheduler adapters that report admission but do
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,6 @@
import com.bencodez.advancedcore.api.user.UserStorage;
import com.bencodez.advancedcore.api.user.usercache.UserDataCache;
import com.bencodez.advancedcore.api.user.userstorage.mysql.MySQL;
import com.bencodez.simpleapi.folialib.enums.EntityTaskResult;
import com.bencodez.simpleapi.sql.DataType;
import com.bencodez.simpleapi.sql.mysql.DbType;
import com.bencodez.votingplugin.VotingPluginMain;
Expand Down Expand Up @@ -406,10 +405,10 @@ private void runPurchaseEntityTask(Player player, Runnable task, Runnable reject
BukkitCompletionScheduler.run(plugin, player, task, rejected);
return;
}
CompletableFuture<EntityTaskResult> result = plugin.getBukkitScheduler().getFoliaLib().getImpl()
CompletableFuture<?> result = plugin.getBukkitScheduler().getFoliaLib().getImpl()
.runAtEntityWithFallback(player, ignored -> task.run(), rejected);
result.whenComplete((status, failure) -> {
if (failure != null || status != EntityTaskResult.SUCCESS) rejected.run();
if (failure != null || !BukkitCompletionScheduler.isSuccessfulEntityTaskResult(status)) rejected.run();
});
}

Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package com.bencodez.votingplugin.commands;

import com.bencodez.votingplugin.util.EntityTaskResultTestCompat;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.Mockito.mock;
Expand All @@ -19,7 +20,6 @@

import com.bencodez.simpleapi.scheduler.BukkitScheduler;
import com.bencodez.simpleapi.folialib.FoliaLib;
import com.bencodez.simpleapi.folialib.enums.EntityTaskResult;
import com.bencodez.simpleapi.folialib.impl.ServerImplementation;
import com.bencodez.votingplugin.VotingPluginMain;
import com.bencodez.votingplugin.config.Config;
Expand Down Expand Up @@ -213,6 +213,6 @@ private static void configureEntityScheduler(BukkitScheduler scheduler) {
when(scheduler.getFoliaLib()).thenReturn(folia);
when(folia.getImpl()).thenReturn(entityScheduler);
when(entityScheduler.runAtEntityWithFallback(any(), any(), any(Runnable.class)))
.thenReturn(CompletableFuture.completedFuture(EntityTaskResult.SUCCESS));
.thenReturn(EntityTaskResultTestCompat.success());
}
}
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package com.bencodez.votingplugin.placeholders;

import com.bencodez.votingplugin.util.EntityTaskResultTestCompat;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertFalse;
import static org.junit.jupiter.api.Assertions.assertTrue;
Expand Down Expand Up @@ -34,7 +35,6 @@
import com.bencodez.advancedcore.api.user.AdvancedCoreUser;
import com.bencodez.advancedcore.api.user.usercache.UserDataManager;
import com.bencodez.simpleapi.folialib.FoliaLib;
import com.bencodez.simpleapi.folialib.enums.EntityTaskResult;
import com.bencodez.simpleapi.folialib.impl.ServerImplementation;
import com.bencodez.simpleapi.scheduler.BukkitScheduler;
import com.bencodez.votingplugin.VotingPluginMain;
Expand Down Expand Up @@ -227,7 +227,7 @@ void retiredEntityFallsBackToOfflineWorkerUpdate() {
when(entityScheduler.runAtEntityWithFallback(eq(fixture.player), any(), any(Runnable.class)))
.thenAnswer(call -> {
call.getArgument(2, Runnable.class).run();
return CompletableFuture.completedFuture(EntityTaskResult.ENTITY_RETIRED);
return EntityTaskResultTestCompat.entityRetired();
});
doAnswer(call -> { call.getArgument(1, Runnable.class).run(); return null; })
.when(fixture.scheduler).runTask(eq(fixture.plugin), any(Runnable.class));
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package com.bencodez.votingplugin.tests.backgroundtask;

import com.bencodez.votingplugin.util.EntityTaskResultTestCompat;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertFalse;
import static org.junit.jupiter.api.Assertions.assertTrue;
Expand Down Expand Up @@ -99,8 +100,7 @@ public void retiredFoliaPlayerStillCompletesOnlineSnapshot() {
when(scheduler.getFoliaLib()).thenReturn(folia);
when(folia.getImpl()).thenReturn(implementation);
when(implementation.runAtEntityWithFallback(eq(player), any(), any(Runnable.class)))
.thenReturn(java.util.concurrent.CompletableFuture.completedFuture(
com.bencodez.simpleapi.folialib.enums.EntityTaskResult.SCHEDULER_RETIRED));
.thenReturn(EntityTaskResultTestCompat.schedulerRetired());
doAnswer(call -> { call.getArgument(1, Runnable.class).run(); return null; })
.when(scheduler).runTask(eq(plugin), any(Runnable.class));
java.util.concurrent.atomic.AtomicReference<java.util.Map<java.util.UUID, Boolean>> result =
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package com.bencodez.votingplugin.tests.reminders;

import com.bencodez.votingplugin.util.EntityTaskResultTestCompat;
import static org.junit.jupiter.api.Assertions.assertFalse;
import static org.junit.jupiter.api.Assertions.assertTrue;
import static org.mockito.ArgumentMatchers.any;
Expand Down Expand Up @@ -33,7 +34,6 @@
import com.bencodez.simpleapi.time.ParsedDuration;
import com.bencodez.simpleapi.scheduler.BukkitScheduler;
import com.bencodez.simpleapi.folialib.FoliaLib;
import com.bencodez.simpleapi.folialib.enums.EntityTaskResult;
import com.bencodez.simpleapi.folialib.impl.ServerImplementation;
import com.bencodez.advancedcore.api.rewards.RewardBuilder;
import com.bencodez.votingplugin.VotingPluginMain;
Expand Down Expand Up @@ -271,7 +271,7 @@ void reminderDeliveryReleasesReservationsWhenTheEntitySchedulerRetires() throws
when(implementation.runAtEntityWithFallback(eq(player), any(), any(Runnable.class)))
.thenAnswer(invocation -> {
invocation.getArgument(2, Runnable.class).run();
return CompletableFuture.completedFuture(EntityTaskResult.ENTITY_RETIRED);
return EntityTaskResultTestCompat.entityRetired();
});
org.mockito.Mockito.doAnswer(invocation -> {
invocation.getArgument(1, Runnable.class).run();
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package com.bencodez.votingplugin.user;

import com.bencodez.votingplugin.util.EntityTaskResultTestCompat;
import static org.junit.jupiter.api.Assertions.assertTrue;
import static org.junit.jupiter.api.Assertions.assertFalse;
import static org.junit.jupiter.api.Assertions.assertEquals;
Expand Down Expand Up @@ -52,7 +53,6 @@
import com.bencodez.simpleapi.sql.mysql.ConnectionManager;
import com.bencodez.simpleapi.scheduler.BukkitScheduler;
import com.bencodez.simpleapi.folialib.FoliaLib;
import com.bencodez.simpleapi.folialib.enums.EntityTaskResult;
import com.bencodez.simpleapi.folialib.impl.ServerImplementation;
import com.bencodez.votingplugin.VotingPluginMain;
import com.bencodez.votingplugin.events.PlayerReceivePointsEvent;
Expand Down Expand Up @@ -803,7 +803,7 @@ void perServerPointAdditionFailsWithoutWritingWhenBukkitHandoffIsRejected() thro
when(fixture.connection.prepareStatement(anyString())).thenReturn(schema, schema, schema, schema, lookup,
claimInsert, releaseSelect, releaseDelete);
when(fixture.entityScheduler.runAtEntityWithFallback(eq(fixture.player), any(), any(Runnable.class)))
.thenReturn(CompletableFuture.completedFuture(EntityTaskResult.SCHEDULER_RETIRED));
.thenReturn(EntityTaskResultTestCompat.schedulerRetired());
doThrow(new RejectedExecutionException("stopping")).when(fixture.scheduler)
.runTask(eq(fixture.plugin), any(Runnable.class));
PluginManager pluginManager = mock(PluginManager.class);
Expand All @@ -829,7 +829,7 @@ void perServerPointAdditionFailsWithoutWritingWhenBukkitHandoffIsRejected() thro
@Test
void retiredEntitySchedulerQueuesUnstartedHookReleaseWithoutJdbcOnCompletionLane() throws Exception {
PointFixture fixture = pointFixture();
CompletableFuture<EntityTaskResult> entityCompletion = new CompletableFuture<>();
CompletableFuture entityCompletion = EntityTaskResultTestCompat.pending();
when(fixture.entityScheduler.runAtEntityWithFallback(eq(fixture.player), any(), any(Runnable.class)))
.thenReturn(entityCompletion);
PreparedStatement statement = fixture.statement;
Expand Down Expand Up @@ -866,7 +866,7 @@ void retiredEntitySchedulerQueuesUnstartedHookReleaseWithoutJdbcOnCompletionLane

com.bencodez.simpleapi.sql.mysql.ConnectionManager manager = fixture.sql.getConnectionManager();
org.mockito.Mockito.clearInvocations(fixture.persistence, manager, fixture.connection, statement);
entityCompletion.complete(EntityTaskResult.SCHEDULER_RETIRED);
EntityTaskResultTestCompat.completeSchedulerRetired(entityCompletion);

ArgumentCaptor<Runnable> releaseWork = ArgumentCaptor.forClass(Runnable.class);
verify(fixture.persistence).execute(releaseWork.capture());
Expand All @@ -883,7 +883,7 @@ void retiredEntitySchedulerQueuesUnstartedHookReleaseWithoutJdbcOnCompletionLane
@Test
void retiredEntitySchedulerRetainsClaimWhenNoDatabaseSafeReleaseWorkerAcceptsWork() throws Exception {
PointFixture fixture = pointFixture();
CompletableFuture<EntityTaskResult> entityCompletion = new CompletableFuture<>();
CompletableFuture entityCompletion = EntityTaskResultTestCompat.pending();
when(fixture.entityScheduler.runAtEntityWithFallback(eq(fixture.player), any(), any(Runnable.class)))
.thenReturn(entityCompletion);
PreparedStatement statement = fixture.statement;
Expand Down Expand Up @@ -923,7 +923,7 @@ void retiredEntitySchedulerRetainsClaimWhenNoDatabaseSafeReleaseWorkerAcceptsWor
doThrow(new RejectedExecutionException("stopping")).when(fixture.persistence).execute(any(Runnable.class));
doThrow(new RejectedExecutionException("disabling")).when(fixture.scheduler)
.runTaskAsynchronously(eq(fixture.plugin), any(Runnable.class));
entityCompletion.complete(EntityTaskResult.SCHEDULER_RETIRED);
EntityTaskResultTestCompat.completeSchedulerRetired(entityCompletion);

assertTrue(completion.isCompletedExceptionally());
verify(fixture.scheduler).runTaskAsynchronously(eq(fixture.plugin), any(Runnable.class));
Expand Down Expand Up @@ -1348,7 +1348,7 @@ void retiredApprovalSchedulerRefundsClaimedTransferBeforeTheHookCanRun() throws
SagaFixture fixture = sagaFixture(true);
configureRejectedSagaConnections(fixture);
when(fixture.entityScheduler.runAtEntityWithFallback(any(), any(), any(Runnable.class)))
.thenReturn(CompletableFuture.completedFuture(EntityTaskResult.SCHEDULER_RETIRED));
.thenReturn(EntityTaskResultTestCompat.schedulerRetired());
AtomicReference<Boolean> result = new AtomicReference<>();

fixture.user.transferPoints(fixture.target, 10, result::set);
Expand Down Expand Up @@ -1378,7 +1378,7 @@ void rejectedClaimedTransferCompensationUsesAsyncFallback() throws Exception {
SagaFixture fixture = sagaFixture(true);
configureRejectedSagaConnections(fixture);
when(fixture.entityScheduler.runAtEntityWithFallback(any(), any(), any(Runnable.class)))
.thenReturn(CompletableFuture.completedFuture(EntityTaskResult.SCHEDULER_RETIRED));
.thenReturn(EntityTaskResultTestCompat.schedulerRetired());
AtomicReference<Boolean> result = new AtomicReference<>();

fixture.user.transferPoints(fixture.target, 10, result::set);
Expand Down Expand Up @@ -1412,7 +1412,7 @@ void rejectedClaimedTransferRetainsDurableCompensationWhenBothFallbackSchedulers
when(fixture.plugin.getDataFolder()).thenReturn(temporaryDirectory.toFile());
configureRejectedSagaConnections(fixture);
when(fixture.entityScheduler.runAtEntityWithFallback(any(), any(), any(Runnable.class)))
.thenReturn(CompletableFuture.completedFuture(EntityTaskResult.SCHEDULER_RETIRED));
.thenReturn(EntityTaskResultTestCompat.schedulerRetired());
AtomicReference<Boolean> result = new AtomicReference<>();

fixture.user.transferPoints(fixture.target, 10, result::set);
Expand Down Expand Up @@ -1446,7 +1446,7 @@ void failedClaimedTransferCompensationKeepsRecoveryMarkerWhenMysqlFenceAndRefund
when(fixture.plugin.getDataFolder()).thenReturn(temporaryDirectory.toFile());
configureRejectedSagaConnections(fixture);
when(fixture.entityScheduler.runAtEntityWithFallback(any(), any(), any(Runnable.class)))
.thenReturn(CompletableFuture.completedFuture(EntityTaskResult.SCHEDULER_RETIRED));
.thenReturn(EntityTaskResultTestCompat.schedulerRetired());

fixture.user.transferPoints(fixture.target, 10, ignored -> { });
ArgumentCaptor<Runnable> persistence = ArgumentCaptor.forClass(Runnable.class);
Expand Down Expand Up @@ -1968,7 +1968,7 @@ private static ServerImplementation configureEntityScheduler(VotingPluginMain pl
when(scheduler.getFoliaLib()).thenReturn(folia);
when(folia.getImpl()).thenReturn(entityScheduler);
when(entityScheduler.runAtEntityWithFallback(any(), any(), any(Runnable.class)))
.thenReturn(CompletableFuture.completedFuture(EntityTaskResult.SUCCESS));
.thenReturn(EntityTaskResultTestCompat.success());
return entityScheduler;
}

Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package com.bencodez.votingplugin.util;

import com.bencodez.votingplugin.util.EntityTaskResultTestCompat;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.eq;
Expand All @@ -17,7 +18,6 @@
import org.junit.jupiter.api.Test;

import com.bencodez.simpleapi.folialib.FoliaLib;
import com.bencodez.simpleapi.folialib.enums.EntityTaskResult;
import com.bencodez.simpleapi.folialib.impl.ServerImplementation;
import com.bencodez.simpleapi.scheduler.BukkitScheduler;
import com.bencodez.votingplugin.VotingPluginMain;
Expand All @@ -29,7 +29,7 @@ void retiredEntityRunsCompletionOnceOnGlobalFallback() {
when(fixture.entityScheduler.runAtEntityWithFallback(eq(fixture.player), any(), any(Runnable.class)))
.thenAnswer(invocation -> {
invocation.getArgument(2, Runnable.class).run();
return CompletableFuture.completedFuture(EntityTaskResult.ENTITY_RETIRED);
return EntityTaskResultTestCompat.entityRetired();
});
AtomicInteger completions = new AtomicInteger();

Expand All @@ -43,7 +43,7 @@ void retiredEntityRunsCompletionOnceOnGlobalFallback() {
void alreadyRetiredSchedulerRunsCompletionOnceOnGlobalFallback() {
Fixture fixture = fixture();
when(fixture.entityScheduler.runAtEntityWithFallback(eq(fixture.player), any(), any(Runnable.class)))
.thenReturn(CompletableFuture.completedFuture(EntityTaskResult.SCHEDULER_RETIRED));
.thenReturn(EntityTaskResultTestCompat.schedulerRetired());
AtomicInteger completions = new AtomicInteger();

BukkitCompletionScheduler.run(fixture.plugin, fixture.player, completions::incrementAndGet);
Expand All @@ -69,7 +69,7 @@ void missingSchedulerStatusRunsCompletionOnceOnGlobalFallback() {
void rejectedEveryFallbackCallsRejectedOnlyWhenTaskNeverBegan() {
Fixture fixture = fixture();
when(fixture.entityScheduler.runAtEntityWithFallback(eq(fixture.player), any(), any(Runnable.class)))
.thenReturn(CompletableFuture.completedFuture(EntityTaskResult.SCHEDULER_RETIRED));
.thenReturn(EntityTaskResultTestCompat.schedulerRetired());
doThrow(new RejectedExecutionException("stopping")).when(fixture.scheduler).runTask(eq(fixture.plugin),
any(Runnable.class));
AtomicInteger completed = new AtomicInteger();
Expand All @@ -87,7 +87,7 @@ void retiredEntityRunsDistinctGlobalSafeFallback() {
when(fixture.entityScheduler.runAtEntityWithFallback(eq(fixture.player), any(), any(Runnable.class)))
.thenAnswer(invocation -> {
invocation.getArgument(2, Runnable.class).run();
return CompletableFuture.completedFuture(EntityTaskResult.ENTITY_RETIRED);
return EntityTaskResultTestCompat.entityRetired();
});
AtomicInteger entity = new AtomicInteger();
AtomicInteger fallback = new AtomicInteger();
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
package com.bencodez.votingplugin.util;

import java.util.concurrent.CompletableFuture;

/**
* Test statuses for code that intentionally treats Folia's shaded entity-task result
* as an opaque enum. Keeping tests independent of the relocated FoliaLib enum lets
* Eclipse resolve the project whether SimpleAPI comes from the workspace or Maven.
*/
public final class EntityTaskResultTestCompat {

private enum Status {
SUCCESS,
ENTITY_RETIRED,
SCHEDULER_RETIRED
}

private EntityTaskResultTestCompat() {
}

@SuppressWarnings("rawtypes")
public static CompletableFuture success() {
return CompletableFuture.completedFuture(Status.SUCCESS);
}

@SuppressWarnings("rawtypes")
public static CompletableFuture entityRetired() {
return CompletableFuture.completedFuture(Status.ENTITY_RETIRED);
}

@SuppressWarnings("rawtypes")
public static CompletableFuture schedulerRetired() {
return CompletableFuture.completedFuture(Status.SCHEDULER_RETIRED);
}

@SuppressWarnings("rawtypes")
public static CompletableFuture pending() {
return new CompletableFuture();
}

@SuppressWarnings({ "rawtypes", "unchecked" })
public static void completeSchedulerRetired(CompletableFuture future) {
future.complete(Status.SCHEDULER_RETIRED);
}
}
Loading
Loading