Skip to content

Commit

Permalink
Limit island/player saves per tick (#1578)
Browse files Browse the repository at this point in the history
* limit island/player saves per tick

* Whoops

* 20 players/islands per tick should be enough

20 players/islands * 20 tick * 60 seconds * 5 minutes (default interval) = 120000 saved entries :)
  • Loading branch information
sgdc3 authored Nov 27, 2020
1 parent 2e00602 commit 232d909
Show file tree
Hide file tree
Showing 4 changed files with 120 additions and 29 deletions.
4 changes: 2 additions & 2 deletions src/main/java/world/bentobox/bentobox/BentoBox.java
Original file line number Diff line number Diff line change
Expand Up @@ -203,8 +203,8 @@ public void onEnable(){

// Save islands & players data every X minutes
Bukkit.getScheduler().runTaskTimer(instance, () -> {
playersManager.saveAll();
islandsManager.saveAll();
playersManager.saveAll(true);
islandsManager.saveAll(true);
}, getSettings().getDatabaseBackupPeriod() * 20 * 60L, getSettings().getDatabaseBackupPeriod() * 20 * 60L);

// Make sure all flag listeners are registered.
Expand Down
40 changes: 40 additions & 0 deletions src/main/java/world/bentobox/bentobox/Settings.java
Original file line number Diff line number Diff line change
Expand Up @@ -95,6 +95,18 @@ public class Settings implements ConfigObject {
@ConfigEntry(path = "general.database.backup-period")
private int databaseBackupPeriod = 5;

@ConfigComment("How many players will be saved in one tick. Default is 200")
@ConfigComment("Reduce if you experience lag while saving.")
@ConfigComment("Do not set this too low or data might get lost!")
@ConfigEntry(path = "general.database.max-saved-players-per-tick")
private int maxSavedPlayersPerTick = 20;

@ConfigComment("How many islands will be saved in one tick. Default is 200")
@ConfigComment("Reduce if you experience lag while saving.")
@ConfigComment("Do not set this too low or data might get lost!")
@ConfigEntry(path = "general.database.max-saved-islands-per-tick")
private int maxSavedIslandsPerTick = 20;

@ConfigComment("Enable SSL connection to MongoDB, MariaDB, MySQL and PostgreSQL databases.")
@ConfigEntry(path = "general.database.use-ssl", since = "1.12.0")
private boolean useSSL = false;
Expand Down Expand Up @@ -379,6 +391,34 @@ public void setDatabaseBackupPeriod(int databaseBackupPeriod) {
this.databaseBackupPeriod = databaseBackupPeriod;
}

/**
* @since 1.15.3
*/
public int getMaxSavedPlayersPerTick() {
return maxSavedPlayersPerTick;
}

/**
* @since 1.15.3
*/
public void setMaxSavedPlayersPerTick(int maxSavedPlayersPerTick) {
this.maxSavedPlayersPerTick = maxSavedPlayersPerTick;
}

/**
* @since 1.15.3
*/
public int getMaxSavedIslandsPerTick() {
return maxSavedIslandsPerTick;
}

/**
* @since 1.15.3
*/
public void setMaxSavedIslandsPerTick(int maxSavedIslandsPerTick) {
this.maxSavedIslandsPerTick = maxSavedIslandsPerTick;
}

public Set<String> getFakePlayers() {
return fakePlayers;
}
Expand Down
56 changes: 38 additions & 18 deletions src/main/java/world/bentobox/bentobox/managers/IslandsManager.java
Original file line number Diff line number Diff line change
@@ -1,17 +1,7 @@
package world.bentobox.bentobox.managers;

import java.io.IOException;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Optional;
import java.util.Set;
import java.util.UUID;
import java.util.*;
import java.util.concurrent.CompletableFuture;
import java.util.stream.Collectors;

Expand All @@ -29,6 +19,7 @@
import org.bukkit.entity.PufferFish;
import org.bukkit.inventory.ItemStack;
import org.bukkit.permissions.PermissionAttachmentInfo;
import org.bukkit.scheduler.BukkitRunnable;
import org.bukkit.util.Vector;
import org.eclipse.jdt.annotation.NonNull;
import org.eclipse.jdt.annotation.Nullable;
Expand Down Expand Up @@ -1221,15 +1212,44 @@ public void removePlayersFromIsland(Island island) {
/**
* Save the all the islands to the database
*/
public void saveAll(){
Collection<Island> collection = islandCache.getIslands();
for(Island island : collection){
try {
handler.saveObjectAsync(island);
} catch (Exception e) {
plugin.logError("Could not save island to database when running sync! " + e.getMessage());
public void saveAll() {
saveAll(false);
}

/**
* Save the all the islands to the database
* @param schedule true if we should let the task run over multiple ticks to reduce lag spikes
*/
public void saveAll(boolean schedule){
if (!schedule) {
for(Island island : islandCache.getIslands()){
try {
handler.saveObjectAsync(island);
} catch (Exception e) {
plugin.logError("Could not save island to database when running sync! " + e.getMessage());
}
}
return;
}

Queue<Island> queue = new LinkedList<>(islandCache.getIslands());
new BukkitRunnable() {
@Override
public void run() {
for (int i = 0; i < plugin.getSettings().getMaxSavedIslandsPerTick(); i++) {
Island island = queue.poll();
if (island == null) {
cancel();
return;
}
try {
handler.saveObjectAsync(island);
} catch (Exception e) {
plugin.logError("Could not save island to database when running sync! " + e.getMessage());
}
}
}
}.runTaskTimer(plugin, 0, 1);
}

/**
Expand Down
49 changes: 40 additions & 9 deletions src/main/java/world/bentobox/bentobox/managers/PlayersManager.java
Original file line number Diff line number Diff line change
@@ -1,16 +1,11 @@
package world.bentobox.bentobox.managers;

import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
import java.util.UUID;
import java.util.*;

import org.bukkit.Location;
import org.bukkit.World;
import org.bukkit.entity.Player;
import org.bukkit.scheduler.BukkitRunnable;
import org.eclipse.jdt.annotation.NonNull;
import org.eclipse.jdt.annotation.Nullable;

Expand Down Expand Up @@ -67,8 +62,44 @@ public void load(){
/**
* Save all players
*/
public void saveAll(){
Collections.unmodifiableCollection(playerCache.values()).forEach(handler::saveObjectAsync);
public void saveAll() {
saveAll(false);
}

/**
* Save all players
* @param schedule true if we should let the task run over multiple ticks to reduce lag spikes
*/
public void saveAll(boolean schedule){
if (!schedule) {
for (Players player : playerCache.values()) {
try {
handler.saveObjectAsync(player);
} catch (Exception e) {
plugin.logError("Could not save player to database when running sync! " + e.getMessage());
}
}
return;
}

Queue<Players> queue = new LinkedList<>(playerCache.values());
new BukkitRunnable() {
@Override
public void run() {
for (int i = 0; i < plugin.getSettings().getMaxSavedPlayersPerTick(); i++) {
Players player = queue.poll();
if (player == null) {
cancel();
return;
}
try {
handler.saveObjectAsync(player);
} catch (Exception e) {
plugin.logError("Could not save player to database when running sync! " + e.getMessage());
}
}
}
}.runTaskTimer(plugin, 0, 1);
}

public void shutdown(){
Expand Down

0 comments on commit 232d909

Please sign in to comment.