Optimisation des requêtes pour l'économie#1333
Conversation
6c8e2c3 to
70dde0d
Compare
70dde0d to
a2a7db9
Compare
|
au lieu de sauvegarder tout les x temps, pourquoi tu save pas juste a la db au moment ou le plugin se desactive |
|
C'était marqué dans l'issue |
C’est déjà fait xd au L’autosave est volontaire en plus du shutdown save ça évite de perdre toutes les modifications depuis le démarrage si le serveur crash/kill ou si l’arrêt ne va pas jusqu’au bout. Et il ne sauvegarde pas tous les balances à chaque fois, seulement les UUID marqués dirty depuis la dernière sauvegarde :) |
|
Le serveur n'est pas cense etre kill ou crash, meme il ne sera jamais kill... |
|
Ben après il peut crash oui. Mais il est tjr éteint à 2h donc cv |
|
Même si le serveur n’est pas censé crash il peut crash mdrrrrr l’autosave limite la perte si ça arrive et dans tous les cas le coût en perf est faible on ne save pas tous les comptes seulement les dirty en batch |
|
Tu appelles quoi un compte dirty? |
|
Dirty = modifié depuis le dernier save DB |
|
Le probleme, est que la le lag a lieu lors de la premiere connexion des joeurs, c'est un moment que l'on avait fait avec 50bots de souvenir, et le lag venait du save a la db, donc la si je comprends bien, a un moment, le serveur va lag parcequ'il save toutes les donne dans la db a un moment x |
|
Fin et déjà pour qu'on valide le problème, il faudra que tu donnes un jar de ton plugin, on fait un teste avec 50-100 joueurs, et on attends jusqu'au moment où le scheduler s'exécute pour save la db, et on tentera |
|
Bon @gtolontop, si c'est pour faire du vibecoding sur le projet ce n'est pas la peine de venir faire une PR. |
|
Le satan qui se réveille avec le full vibecoding qui fait mal |
MDRRRRR, elle est vraiment niquel ma PR je vois pas le soucis + c'est pas du vibecoding mais j'avoue que mon code a une vibe très propre :) |
Très propre se vibecoding en tous cas |
Dis-moi, qu'aurais-tu fait différemment ? |
|
Donc pourquoi il y a ecris |
Honnetement, bcp de chose, mais si tu "ne vibecode pas" chaque developpeur fait differemment donc je n'aurais pas fait pareil que toi |
Tu mets tout sur le principe de la raison? Pourquoi ? |
Bonjour, Il est préférable de passer la PR en ready si vous jugez qu’elle est prête pour la production. Étant donné que nous ne sommes pas nombreux à maintenir le projet, nous nous concentrons principalement sur celles qui sont en ready afin de fournir des retours. Concernant la réflexion, il serait préférable de la retirer, mais sans utiliser Mockito. Cela fera l’objet d’une autre PR. Concernant le clone, je laisse @PuppyTransGirl vérifier et nous donner son avis afin d’en discuter. De mon côté, je ne suis pas particulièrement favorable. |
Elle est déjà ouverte la PR ? J'ai pas compris |
Elle n'est pas en ready for review, elle est en draft |
C'est bon :) |
Pourquoi faudrait-il la retirer si c'est correct et que ça fonctionne bien ? Et ça n'utilise déjà pas Mockito. |
| @SuppressWarnings("unchecked") | ||
| private static Dao<EconomyPlayer, String> createPlayersDao(Map<UUID, Double> persistedBalances, Runnable onCreateOrUpdate) { | ||
| return (Dao<EconomyPlayer, String>) Proxy.newProxyInstance( | ||
| Dao.class.getClassLoader(), | ||
| new Class<?>[]{Dao.class}, | ||
| (proxy, method, args) -> switch (method.getName()) { | ||
| case "callBatchTasks" -> ((Callable<?>) args[0]).call(); | ||
| case "createOrUpdate" -> { | ||
| onCreateOrUpdate.run(); | ||
| EconomyPlayer player = (EconomyPlayer) args[0]; | ||
| persistedBalances.put(player.getPlayerUUID(), player.getBalance()); | ||
| yield null; | ||
| } | ||
| case "toString" -> "InMemoryEconomyPlayerDao"; | ||
| case "hashCode" -> System.identityHashCode(proxy); | ||
| case "equals" -> proxy == args[0]; | ||
| default -> null; | ||
| } | ||
| ); | ||
| } | ||
|
|
||
| @SuppressWarnings("unchecked") | ||
| private static Dao<EconomyPlayer, String> replacePlayersDao(Dao<EconomyPlayer, String> playersDao) throws Exception { | ||
| Field playersDaoField = EconomyManager.class.getDeclaredField("playersDao"); | ||
| playersDaoField.setAccessible(true); | ||
|
|
||
| Dao<EconomyPlayer, String> previousPlayersDao = (Dao<EconomyPlayer, String>) playersDaoField.get(null); | ||
| playersDaoField.set(null, playersDao); | ||
|
|
||
| return previousPlayersDao; | ||
| } | ||
|
|
||
| @SuppressWarnings("unchecked") | ||
| private static Map<UUID, EconomyPlayer> replaceBalances(Map<UUID, EconomyPlayer> balances) throws Exception { | ||
| Field balancesField = EconomyManager.class.getDeclaredField("balances"); | ||
| balancesField.setAccessible(true); | ||
|
|
||
| Map<UUID, EconomyPlayer> previousBalances = (Map<UUID, EconomyPlayer>) balancesField.get(null); | ||
| balancesField.set(null, balances); | ||
|
|
||
| return previousBalances; | ||
| } | ||
|
|
||
| @SuppressWarnings("unchecked") | ||
| private static Set<UUID> getDirtyBalances() throws Exception { | ||
| Field dirtyBalancesField = EconomyManager.class.getDeclaredField("dirtyBalances"); | ||
| dirtyBalancesField.setAccessible(true); | ||
|
|
||
| return (Set<UUID>) dirtyBalancesField.get(null); | ||
| } | ||
|
|
||
| private static void saveAllBalances(boolean finalSave) throws Exception { | ||
| Method saveAllBalancesMethod = EconomyManager.class.getDeclaredMethod("saveAllBalances", boolean.class); | ||
| saveAllBalancesMethod.setAccessible(true); | ||
| saveAllBalancesMethod.invoke(null, finalSave); | ||
| } |
There was a problem hiding this comment.
Fait gaffe a la rélfexion (reporté par Nirbose)
There was a problem hiding this comment.
Tu veux que je fasse quoi exactement dessus ?
There was a problem hiding this comment.
Attends @ltuffery, je ne sais pas ce qu'il voulait que tu fasses
There was a problem hiding this comment.
Pour moi, il faut retirer la réflexion. Ce n’est vraiment pas une bonne pratique de l’utiliser “à la dure” de cette manière, sans s’appuyer sur une librairie spécialement conçue pour ça.
There was a problem hiding this comment.
j'ai capté pour la reflexion
Je veux juste clarifier j'ai pas tous capté dans ton message précédent, tu disais qu’il fallait la retirer sans Mockito, mais que ça ferait l’objet d’une autre PR.
Du coup tu préfères que je le fasse directement dans cette PR, ou que je garde ça pour une autre PR ?
Si tu veux que je le fasse ici, je peux soit retirer le test qui dépend de l’état privé, soit essayer de le réécrire via l’API publique / H2.
There was a problem hiding this comment.
je ne pense pas qu'il va te répondre, ping le sur discord avec un lien de ton message
There was a problem hiding this comment.
quel channel pls ?
|
plop a review les gens |
|
@gtolontop possible d'avoir un jar stp |
|
OpenMC-dev.zip |
|
je teste |
faut que tu build le jar avec le shadowJar |
|
c'est pas possible tu n'as pas teste si tes modif fonctionnais |
|
Ok pas de soucis, juste ton lien ne fonctionne pas |
|
github me boycott bruhhh |
|
https://spark.lucko.me/xOiSgERLyM avec 50joueurs @iambibi |
T'es sûr d'avoir attendu le save des économies ? |
|
j'ai attendu 5minutes |
|
Y'a pas de bugs? Les joueurs ont bien leur thune de save? |
Oui j'ai déjà tester xd |
|
Mockito fera l’objet d’une autre PR, c’est ce que je voulais dire. Concernant ta réflexion, tu dois la retirer : soit tu arrives à remplacer les tests avec l’API actuelle (ce qui serait idéal), soit tu trouves une autre approche. |
|
C’est traité dans le commit juste au dessus J’ai retiré la réflexion du test y'a plus de vous pouvez testez avec ./gradlew test --tests fr.openmc.core.features.economy.EconomyManagerDirtySaveTest --no-daemon --rerun-tasks |
|
Attente de review |




Petit résumé de la PR:
Optimise la persistance des soldes économie en regroupant les écritures DB des balances modifiées.
Étape nécessaire afin que la PR soit fini (si PR en draft)
2.5.0à assigner)Fixes [BUG] Optimisation de EconomyManager.setBalance #1332
Decrivez vos changements
EconomyManagerécrivait en DB à chaque changement de solde viaplayersDao.createOrUpdate, notamment depuissetBalance,addBalanceetwithdrawBalance.Cette PR garde les soldes à jour en mémoire immédiatement, marque uniquement les comptes modifiés comme à sauvegarder, puis persiste ces comptes en batch avec
saveAllBalances():Le cache utilise aussi
computeIfAbsentpour conserver les nouveaux comptes en mémoire avant leur première sauvegarde. En cas d'erreur pendant la sauvegarde batch, les comptes concernés sont remis dans la liste à sauvegarder.