mirror of
https://github.com/songoda/EpicVouchers.git
synced 2024-11-25 11:35:30 +01:00
Hotfix async vouchers.yml write task as large files cause lag [SD-8155]
I've some a TODO/FIXME explaining what to do. Wanna focus on bringing the tickets down first
This commit is contained in:
parent
063f7b0fee
commit
d7801dd64f
@ -20,6 +20,8 @@ import com.songoda.epicvouchers.libraries.inventory.IconInv;
|
||||
import com.songoda.epicvouchers.listeners.PlayerCommandListener;
|
||||
import com.songoda.epicvouchers.listeners.PlayerInteractListener;
|
||||
import com.songoda.epicvouchers.settings.Settings;
|
||||
import com.songoda.epicvouchers.utils.Callback;
|
||||
import com.songoda.epicvouchers.utils.ThreadSync;
|
||||
import com.songoda.epicvouchers.voucher.CoolDownManager;
|
||||
import com.songoda.epicvouchers.voucher.Voucher;
|
||||
import com.songoda.epicvouchers.voucher.VoucherExecutor;
|
||||
@ -101,18 +103,33 @@ public class EpicVouchers extends SongodaPlugin {
|
||||
|
||||
@Override
|
||||
public void onDataLoad() {
|
||||
if (!new File(this.getDataFolder(), "vouchers.yml").exists())
|
||||
if (!new File(this.getDataFolder(), "vouchers.yml").exists()) {
|
||||
saveResource("vouchers.yml", false);
|
||||
}
|
||||
|
||||
synchronized (vouchersConfig) {
|
||||
vouchersConfig.load();
|
||||
}
|
||||
|
||||
loadVouchersFromFile();
|
||||
|
||||
connections.openMySQL();
|
||||
|
||||
Bukkit.getScheduler().scheduleSyncRepeatingTask(this, this::saveVouchers, 6000, 6000);
|
||||
// FIXME: Config system needs to be greatly redone and only write changes when changes were made - Maybe even split it into multiple smaler files
|
||||
// Issue https://support.songoda.com/browse/SD-8155 has been hotfixed by writing changes to the file async and blocking the main thread when needed. This requires the use of `synchronized`
|
||||
// and expects every modifying code to use it (thread-safety)
|
||||
// Large vouchers.yml files cause huge performance problems otherwise...
|
||||
// Example file for testing: https://support.songoda.com/secure/attachment/17258/17258_vouchers.yml
|
||||
Bukkit.getScheduler().scheduleSyncRepeatingTask(this,
|
||||
() -> saveVouchersAsync(ex -> {
|
||||
if (ex != null) {
|
||||
ex.printStackTrace();
|
||||
}
|
||||
}), 5 * 60 * 20, 5 * 60 * 20); // 5 minutes
|
||||
}
|
||||
|
||||
private void loadVouchersFromFile() {
|
||||
synchronized (vouchersConfig) {
|
||||
voucherManager.clearVouchers();
|
||||
|
||||
if (vouchersConfig.contains("vouchers")) {
|
||||
@ -165,15 +182,36 @@ public class EpicVouchers extends SongodaPlugin {
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void saveVouchers() {
|
||||
ThreadSync tSync = new ThreadSync();
|
||||
|
||||
saveVouchersAsync(ex -> {
|
||||
if (ex != null) {
|
||||
ex.printStackTrace();
|
||||
}
|
||||
|
||||
tSync.release();
|
||||
});
|
||||
|
||||
tSync.waitForRelease();
|
||||
}
|
||||
|
||||
private void saveVouchersAsync(Callback callback) {
|
||||
new Thread(() -> {
|
||||
try {
|
||||
synchronized (vouchersConfig) {
|
||||
Collection<Voucher> voucherList = voucherManager.getVouchers();
|
||||
|
||||
for (String voucherName : vouchersConfig.getConfigurationSection("vouchers").getKeys(false)) {
|
||||
ConfigurationSection cfgSec = vouchersConfig.getConfigurationSection("vouchers");
|
||||
if (cfgSec != null) {
|
||||
for (String voucherName : cfgSec.getKeys(false)) {
|
||||
if (voucherList.stream().noneMatch(voucher -> voucher.getKey().equals(voucherName))) {
|
||||
vouchersConfig.set("vouchers." + voucherName, null);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (Voucher voucher : voucherList) {
|
||||
String prefix = "vouchers." + voucher.getKey() + ".";
|
||||
@ -211,11 +249,20 @@ public class EpicVouchers extends SongodaPlugin {
|
||||
}
|
||||
|
||||
vouchersConfig.saveChanges();
|
||||
|
||||
callback.accept(null);
|
||||
}
|
||||
} catch (Exception ex) {
|
||||
callback.accept(ex);
|
||||
}
|
||||
}, getName() + "-AsyncConfigSave").start();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onConfigReload() {
|
||||
synchronized (vouchersConfig) {
|
||||
vouchersConfig.load();
|
||||
}
|
||||
|
||||
loadVouchersFromFile();
|
||||
|
||||
@ -240,10 +287,6 @@ public class EpicVouchers extends SongodaPlugin {
|
||||
return this.voucherExecutor;
|
||||
}
|
||||
|
||||
public Config getVouchersConfig() {
|
||||
return this.vouchersConfig;
|
||||
}
|
||||
|
||||
public CommandManager getCommandManager() {
|
||||
return commandManager;
|
||||
}
|
||||
|
@ -0,0 +1,6 @@
|
||||
package com.songoda.epicvouchers.utils;
|
||||
|
||||
// TODO: Copied from EpicAnchors - Move to SongodaCore (maybe rename too?)
|
||||
public interface Callback {
|
||||
void accept(Exception ex);
|
||||
}
|
31
src/main/java/com/songoda/epicvouchers/utils/ThreadSync.java
Normal file
31
src/main/java/com/songoda/epicvouchers/utils/ThreadSync.java
Normal file
@ -0,0 +1,31 @@
|
||||
package com.songoda.epicvouchers.utils;
|
||||
|
||||
import java.util.concurrent.atomic.AtomicReference;
|
||||
|
||||
// TODO: Copied from EpicAnchors - Move to SongodaCore
|
||||
public class ThreadSync {
|
||||
private final Object syncObj = new Object();
|
||||
private final AtomicReference<Boolean> waiting = new AtomicReference<>(true);
|
||||
|
||||
public void waitForRelease() {
|
||||
synchronized (syncObj) {
|
||||
while (waiting.get()) {
|
||||
try {
|
||||
syncObj.wait();
|
||||
} catch (Exception ignore) {
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void release() {
|
||||
synchronized (syncObj) {
|
||||
waiting.set(false);
|
||||
syncObj.notifyAll();
|
||||
}
|
||||
}
|
||||
|
||||
public void reset() {
|
||||
waiting.set(true);
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user