Skip to content

Commit a2a7db9

Browse files
committed
fix(economy): serialize balance saves
1 parent 6c8e2c3 commit a2a7db9

2 files changed

Lines changed: 47 additions & 31 deletions

File tree

src/main/java/fr/openmc/core/features/economy/EconomyManager.java

Lines changed: 39 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@ public class EconomyManager extends Feature implements DatabaseFeature, HasComma
3636
private static Dao<EconomyPlayer, String> playersDao;
3737
private static final Set<UUID> dirtyBalances = new HashSet<>();
3838
private static final Object balancesLock = new Object();
39+
private static final Object saveLock = new Object();
3940
private static final long AUTO_SAVE_INTERVAL_TICKS = 20L * 60L * 5L;
4041
private static BukkitTask autoSaveTask;
4142

@@ -79,8 +80,8 @@ protected void save() {
7980

8081
public static double getBalance(UUID playerUUID) {
8182
synchronized (balancesLock) {
82-
EconomyPlayer bank = getPlayerBank(playerUUID);
83-
return bank.getBalance();
83+
EconomyPlayer bank = balances.get(playerUUID);
84+
return bank == null ? 0 : bank.getBalance();
8485
}
8586
}
8687

@@ -90,7 +91,7 @@ public static void addBalance(UUID playerUUID, double amount) {
9091

9192
public static void addBalance(UUID playerUUID, double amount, @Nullable String reason) {
9293
synchronized (balancesLock) {
93-
EconomyPlayer bank = getPlayerBank(playerUUID);
94+
EconomyPlayer bank = getOrCreatePlayerBank(playerUUID);
9495
bank.deposit(amount);
9596
savePlayerBank(bank);
9697
}
@@ -112,7 +113,7 @@ public static boolean withdrawBalance(UUID playerUUID, double amount) {
112113

113114
public static boolean withdrawBalance(UUID playerUUID, double amount, @Nullable String reason) {
114115
synchronized (balancesLock) {
115-
EconomyPlayer bank = getPlayerBank(playerUUID);
116+
EconomyPlayer bank = getOrCreatePlayerBank(playerUUID);
116117

117118
if (!bank.withdraw(amount)) {
118119
return false;
@@ -175,7 +176,7 @@ public static boolean transferBalance(UUID fromPlayer, UUID toPlayer, double amo
175176

176177
public static void setBalance(UUID playerUUID, double amount) {
177178
synchronized (balancesLock) {
178-
EconomyPlayer bank = getPlayerBank(playerUUID);
179+
EconomyPlayer bank = getOrCreatePlayerBank(playerUUID);
179180
bank.setBalance(amount);
180181
savePlayerBank(bank);
181182
}
@@ -196,42 +197,49 @@ public static void savePlayerBank(EconomyPlayer player) {
196197

197198
public static EconomyPlayer getPlayerBank(UUID playerUUID) {
198199
synchronized (balancesLock) {
199-
return balances.computeIfAbsent(playerUUID, EconomyPlayer::new);
200+
EconomyPlayer bank = balances.get(playerUUID);
201+
return bank == null ? new EconomyPlayer(playerUUID) : bank;
200202
}
201203
}
202204

205+
private static EconomyPlayer getOrCreatePlayerBank(UUID playerUUID) {
206+
return balances.computeIfAbsent(playerUUID, EconomyPlayer::new);
207+
}
208+
203209
public static void saveAllBalances() {
204-
List<EconomyPlayer> playersToSave;
210+
synchronized (saveLock) {
211+
List<EconomyPlayer> playersToSave;
205212

206-
synchronized (balancesLock) {
207-
if (dirtyBalances.isEmpty()) {
208-
return;
209-
}
213+
synchronized (balancesLock) {
214+
if (dirtyBalances.isEmpty()) {
215+
return;
216+
}
210217

211-
playersToSave = dirtyBalances.stream()
212-
.map(balances::get)
213-
.filter(Objects::nonNull)
214-
.map(player -> new EconomyPlayer(player.getPlayerUUID(), player.getBalance()))
215-
.toList();
216-
dirtyBalances.clear();
217-
}
218+
playersToSave = dirtyBalances.stream()
219+
.map(balances::get)
220+
.filter(Objects::nonNull)
221+
.map(player -> new EconomyPlayer(player.getPlayerUUID(), player.getBalance()))
222+
.toList();
223+
dirtyBalances.clear();
224+
}
218225

219-
try {
220-
playersDao.callBatchTasks(() -> {
221-
for (EconomyPlayer player : playersToSave) {
222-
playersDao.createOrUpdate(player);
226+
try {
227+
playersDao.callBatchTasks(() -> {
228+
for (EconomyPlayer player : playersToSave) {
229+
playersDao.createOrUpdate(player);
230+
}
231+
232+
return null;
233+
});
234+
} catch (Exception e) {
235+
synchronized (balancesLock) {
236+
for (EconomyPlayer player : playersToSave) {
237+
dirtyBalances.add(player.getPlayerUUID());
238+
}
223239
}
224240

225-
return null;
226-
});
227-
} catch (Exception e) {
228-
synchronized (balancesLock) {
229-
for (EconomyPlayer player : playersToSave) {
230-
dirtyBalances.add(player.getPlayerUUID());
231-
}
241+
OMCLogger.error("Failed to save economy balances", e);
232242
}
233-
234-
OMCLogger.error("Failed to save economy balances", e);
235243
}
236244
}
237245

src/test/java/fr/openmc/core/features/economy/EconomyManagerTest.java

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -74,6 +74,14 @@ public void testSetBalance() {
7474
assertEquals(EconomyManager.getBalance(player1.getUniqueId()), 500.0);
7575
}
7676

77+
@Test
78+
public void testGetBalanceDoesNotCreateCachedAccount() {
79+
UUID unknownPlayerUUID = UUID.randomUUID();
80+
81+
assertEquals(0.0, EconomyManager.getBalance(unknownPlayerUUID));
82+
assertFalse(EconomyManager.getBalances().containsKey(unknownPlayerUUID));
83+
}
84+
7785
@Test
7886
public void testBalanceChangesAreSavedOnSaveAll() {
7987
UUID playerUUID = player1.getUniqueId();

0 commit comments

Comments
 (0)