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.PlayerCommandListener;
|
||||||
import com.songoda.epicvouchers.listeners.PlayerInteractListener;
|
import com.songoda.epicvouchers.listeners.PlayerInteractListener;
|
||||||
import com.songoda.epicvouchers.settings.Settings;
|
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.CoolDownManager;
|
||||||
import com.songoda.epicvouchers.voucher.Voucher;
|
import com.songoda.epicvouchers.voucher.Voucher;
|
||||||
import com.songoda.epicvouchers.voucher.VoucherExecutor;
|
import com.songoda.epicvouchers.voucher.VoucherExecutor;
|
||||||
@ -101,18 +103,33 @@ public class EpicVouchers extends SongodaPlugin {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onDataLoad() {
|
public void onDataLoad() {
|
||||||
if (!new File(this.getDataFolder(), "vouchers.yml").exists())
|
if (!new File(this.getDataFolder(), "vouchers.yml").exists()) {
|
||||||
saveResource("vouchers.yml", false);
|
saveResource("vouchers.yml", false);
|
||||||
|
}
|
||||||
|
|
||||||
|
synchronized (vouchersConfig) {
|
||||||
vouchersConfig.load();
|
vouchersConfig.load();
|
||||||
|
}
|
||||||
|
|
||||||
loadVouchersFromFile();
|
loadVouchersFromFile();
|
||||||
|
|
||||||
connections.openMySQL();
|
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() {
|
private void loadVouchersFromFile() {
|
||||||
|
synchronized (vouchersConfig) {
|
||||||
voucherManager.clearVouchers();
|
voucherManager.clearVouchers();
|
||||||
|
|
||||||
if (vouchersConfig.contains("vouchers")) {
|
if (vouchersConfig.contains("vouchers")) {
|
||||||
@ -165,15 +182,36 @@ public class EpicVouchers extends SongodaPlugin {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private void saveVouchers() {
|
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();
|
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))) {
|
if (voucherList.stream().noneMatch(voucher -> voucher.getKey().equals(voucherName))) {
|
||||||
vouchersConfig.set("vouchers." + voucherName, null);
|
vouchersConfig.set("vouchers." + voucherName, null);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
for (Voucher voucher : voucherList) {
|
for (Voucher voucher : voucherList) {
|
||||||
String prefix = "vouchers." + voucher.getKey() + ".";
|
String prefix = "vouchers." + voucher.getKey() + ".";
|
||||||
@ -211,11 +249,20 @@ public class EpicVouchers extends SongodaPlugin {
|
|||||||
}
|
}
|
||||||
|
|
||||||
vouchersConfig.saveChanges();
|
vouchersConfig.saveChanges();
|
||||||
|
|
||||||
|
callback.accept(null);
|
||||||
|
}
|
||||||
|
} catch (Exception ex) {
|
||||||
|
callback.accept(ex);
|
||||||
|
}
|
||||||
|
}, getName() + "-AsyncConfigSave").start();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onConfigReload() {
|
public void onConfigReload() {
|
||||||
|
synchronized (vouchersConfig) {
|
||||||
vouchersConfig.load();
|
vouchersConfig.load();
|
||||||
|
}
|
||||||
|
|
||||||
loadVouchersFromFile();
|
loadVouchersFromFile();
|
||||||
|
|
||||||
@ -240,10 +287,6 @@ public class EpicVouchers extends SongodaPlugin {
|
|||||||
return this.voucherExecutor;
|
return this.voucherExecutor;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Config getVouchersConfig() {
|
|
||||||
return this.vouchersConfig;
|
|
||||||
}
|
|
||||||
|
|
||||||
public CommandManager getCommandManager() {
|
public CommandManager getCommandManager() {
|
||||||
return commandManager;
|
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