Skip to content

3.8.8.4

Choose a tag to compare

@MrPippi MrPippi released this 08 May 17:39

Changes

  • fix: use plugin.runAsync() in runTrackedAsync() instead of bare CompletableFuture.runAsync()
  • fix: log ExecutionException (failed save) at WARNING level in awaitPendingSaves(); restore interrupt flag on InterruptedException
  • fix: remove redundant pendingSaves.isEmpty() early return

Fix Details

ForkJoinPool / Folia compatibility
runTrackedAsync() previously submitted work to the bare JVM ForkJoinPool via CompletableFuture.runAsync(task). On shutdown, if awaitPendingSaves() timed out, those tasks could continue running after redisManager.terminate() closed the Jedis pool, causing JedisConnectionException that was silently swallowed — re-introducing the WiIIiam278#654 data-loss scenario. On Folia, the bare pool also lacked region context. The fix pre-creates a CompletableFuture and completes it inside the plugin.runAsync() lambda (MorePaperLib AsynchronousScheduler on Bukkit, ASYNC_EXEC on Fabric), ensuring tasks are bounded to the plugin lifecycle and Folia-safe.

Exception handling in awaitPendingSaves()
The previous catch (Exception ignored) silently discarded both ExecutionException (a player save failed mid-shutdown) and InterruptedException (interrupt flag lost). The fix logs a WARNING for failed saves and correctly restores Thread.currentThread().interrupt() on interruption.

Based On

Upstream HuskSync — includes all fixes through 3.8.8 with additional Paper 26.1.2 support.