mirror of
https://github.com/WiIIiam278/HuskSync.git
synced 2025-12-19 14:59:21 +00:00
feat: various logical improvements to data syncing
* Update data in Redis during world saves & commands * Always set data time to 1 year regardless of sync mode
This commit is contained in:
@@ -23,7 +23,6 @@ import de.themoep.minedown.adventure.MineDown;
|
||||
import net.william278.husksync.HuskSync;
|
||||
import net.william278.husksync.data.Data;
|
||||
import net.william278.husksync.data.DataSnapshot;
|
||||
import net.william278.husksync.redis.RedisKeyType;
|
||||
import net.william278.husksync.redis.RedisManager;
|
||||
import net.william278.husksync.user.OnlineUser;
|
||||
import net.william278.husksync.user.User;
|
||||
@@ -84,18 +83,17 @@ public class EnderChestCommand extends ItemsCommand {
|
||||
|
||||
// Create and pack the snapshot with the updated enderChest
|
||||
final DataSnapshot.Packed snapshot = latestData.get().copy();
|
||||
boolean pin = plugin.getSettings().getSynchronization().doAutoPin(DataSnapshot.SaveCause.ENDERCHEST_COMMAND);
|
||||
snapshot.edit(plugin, (data) -> {
|
||||
data.getEnderChest().ifPresent(enderChest -> enderChest.setContents(items));
|
||||
data.setSaveCause(DataSnapshot.SaveCause.ENDERCHEST_COMMAND);
|
||||
data.setPinned(
|
||||
plugin.getSettings().getSynchronization().doAutoPin(DataSnapshot.SaveCause.ENDERCHEST_COMMAND)
|
||||
);
|
||||
data.setPinned(pin);
|
||||
});
|
||||
|
||||
// Save data
|
||||
final RedisManager redis = plugin.getRedisManager();
|
||||
plugin.getDataSyncer().saveData(holder, snapshot, (user, data) -> {
|
||||
redis.getUserData(user).ifPresent(d -> redis.setUserData(user, snapshot, RedisKeyType.TTL_1_YEAR));
|
||||
redis.getUserData(user).ifPresent(d -> redis.setUserData(user, snapshot));
|
||||
redis.sendUserDataUpdate(user, data);
|
||||
});
|
||||
}
|
||||
|
||||
@@ -23,7 +23,6 @@ import de.themoep.minedown.adventure.MineDown;
|
||||
import net.william278.husksync.HuskSync;
|
||||
import net.william278.husksync.data.Data;
|
||||
import net.william278.husksync.data.DataSnapshot;
|
||||
import net.william278.husksync.redis.RedisKeyType;
|
||||
import net.william278.husksync.redis.RedisManager;
|
||||
import net.william278.husksync.user.OnlineUser;
|
||||
import net.william278.husksync.user.User;
|
||||
@@ -85,18 +84,17 @@ public class InventoryCommand extends ItemsCommand {
|
||||
|
||||
// Create and pack the snapshot with the updated inventory
|
||||
final DataSnapshot.Packed snapshot = latestData.get().copy();
|
||||
boolean pin = plugin.getSettings().getSynchronization().doAutoPin(DataSnapshot.SaveCause.INVENTORY_COMMAND);
|
||||
snapshot.edit(plugin, (data) -> {
|
||||
data.getInventory().ifPresent(inventory -> inventory.setContents(items));
|
||||
data.setSaveCause(DataSnapshot.SaveCause.INVENTORY_COMMAND);
|
||||
data.setPinned(
|
||||
plugin.getSettings().getSynchronization().doAutoPin(DataSnapshot.SaveCause.INVENTORY_COMMAND)
|
||||
);
|
||||
data.setPinned(pin);
|
||||
});
|
||||
|
||||
// Save data
|
||||
final RedisManager redis = plugin.getRedisManager();
|
||||
plugin.getDataSyncer().saveData(holder, snapshot, (user, data) -> {
|
||||
redis.getUserData(user).ifPresent(d -> redis.setUserData(user, snapshot, RedisKeyType.TTL_1_YEAR));
|
||||
redis.getUserData(user).ifPresent(d -> redis.setUserData(user, snapshot));
|
||||
redis.sendUserDataUpdate(user, data);
|
||||
});
|
||||
}
|
||||
|
||||
@@ -77,6 +77,7 @@ public abstract class PluginCommand extends Command {
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@SuppressWarnings("SameParameterValue")
|
||||
protected <S> ArgumentElement<S, OnlineUser> onlineUser(@NotNull String name) {
|
||||
return new ArgumentElement<>(name, reader -> {
|
||||
final String username = reader.readString();
|
||||
|
||||
@@ -22,7 +22,6 @@ package net.william278.husksync.command;
|
||||
import com.mojang.brigadier.exceptions.CommandSyntaxException;
|
||||
import net.william278.husksync.HuskSync;
|
||||
import net.william278.husksync.data.DataSnapshot;
|
||||
import net.william278.husksync.redis.RedisKeyType;
|
||||
import net.william278.husksync.redis.RedisManager;
|
||||
import net.william278.husksync.user.CommandUser;
|
||||
import net.william278.husksync.user.OnlineUser;
|
||||
@@ -154,7 +153,7 @@ public class UserDataCommand extends PluginCommand {
|
||||
// Save data
|
||||
final RedisManager redis = plugin.getRedisManager();
|
||||
plugin.getDataSyncer().saveData(user, data, (u, s) -> {
|
||||
redis.getUserData(u).ifPresent(d -> redis.setUserData(u, s, RedisKeyType.TTL_1_YEAR));
|
||||
redis.getUserData(u).ifPresent(d -> redis.setUserData(u, s));
|
||||
redis.sendUserDataUpdate(u, s);
|
||||
plugin.getLocales().getLocale("data_restored", u.getName(), u.getUuid().toString(),
|
||||
s.getShortId(), s.getId().toString()).ifPresent(executor::sendMessage);
|
||||
|
||||
@@ -80,8 +80,8 @@ public abstract class EventListener {
|
||||
}
|
||||
usersInWorld.stream()
|
||||
.filter(user -> !plugin.isLocked(user.getUuid()) && !user.isNpc())
|
||||
.forEach(user -> plugin.getDataSyncer().saveData(
|
||||
user, user.createSnapshot(DataSnapshot.SaveCause.WORLD_SAVE)
|
||||
.forEach(user -> plugin.getDataSyncer().saveCurrentUserData(
|
||||
user, DataSnapshot.SaveCause.WORLD_SAVE
|
||||
));
|
||||
}
|
||||
|
||||
@@ -94,12 +94,13 @@ public abstract class EventListener {
|
||||
protected void saveOnPlayerDeath(@NotNull OnlineUser user, @NotNull Data.Items items) {
|
||||
final SaveOnDeathSettings settings = plugin.getSettings().getSynchronization().getSaveOnDeath();
|
||||
if (plugin.isDisabling() || !settings.isEnabled() || plugin.isLocked(user.getUuid())
|
||||
|| user.isNpc() || (!settings.isSaveEmptyItems() && items.isEmpty())) {
|
||||
|| user.isNpc() || (!settings.isSaveEmptyItems() && items.isEmpty())) {
|
||||
return;
|
||||
}
|
||||
|
||||
// We don't persist this to Redis for syncing, as this snapshot is from a state they won't be in post-respawn
|
||||
final DataSnapshot.Packed snapshot = user.createSnapshot(DataSnapshot.SaveCause.DEATH);
|
||||
snapshot.edit(plugin, (data -> data.getInventory().ifPresent(inventory -> inventory.setContents(items))));
|
||||
snapshot.edit(plugin, (data -> data.getInventory().ifPresent(inv -> inv.setContents(items))));
|
||||
plugin.getDataSyncer().saveData(user, snapshot);
|
||||
}
|
||||
|
||||
@@ -108,16 +109,12 @@ public abstract class EventListener {
|
||||
* Handle the plugin disabling
|
||||
*/
|
||||
public void handlePluginDisable() {
|
||||
// Save for all online players
|
||||
// Save for all online players.
|
||||
plugin.getOnlineUsers().stream()
|
||||
.filter(user -> !plugin.isLocked(user.getUuid()) && !user.isNpc())
|
||||
.forEach(user -> {
|
||||
plugin.lockPlayer(user.getUuid());
|
||||
plugin.getDataSyncer().saveData(
|
||||
user,
|
||||
user.createSnapshot(DataSnapshot.SaveCause.SERVER_SHUTDOWN),
|
||||
(saved, data) -> plugin.getRedisManager().clearUserData(saved)
|
||||
);
|
||||
plugin.getDataSyncer().saveCurrentUserData(user, DataSnapshot.SaveCause.SERVER_SHUTDOWN);
|
||||
});
|
||||
|
||||
// Close outstanding connections
|
||||
|
||||
@@ -93,7 +93,7 @@ public class RedisManager extends JedisPubSub {
|
||||
jedisPool.getResource().ping();
|
||||
} catch (JedisException e) {
|
||||
throw new IllegalStateException("Failed to establish connection with Redis. "
|
||||
+ "Please check the supplied credentials in the config file", e);
|
||||
+ "Please check the supplied credentials in the config file", e);
|
||||
}
|
||||
|
||||
// Subscribe using a thread (rather than a task)
|
||||
@@ -213,6 +213,8 @@ public class RedisManager extends JedisPubSub {
|
||||
|
||||
public void sendUserDataUpdate(@NotNull User user, @NotNull DataSnapshot.Packed data) {
|
||||
plugin.runAsync(() -> {
|
||||
this.setUserData(user, data);
|
||||
|
||||
final RedisMessage redisMessage = RedisMessage.create(user.getUuid(), data.asBytes(plugin));
|
||||
redisMessage.dispatch(plugin, RedisMessage.Type.UPDATE_USER_DATA);
|
||||
});
|
||||
@@ -226,6 +228,7 @@ public class RedisManager extends JedisPubSub {
|
||||
.orElse(this.requestData(requestId, user));
|
||||
}
|
||||
|
||||
// Request a user's dat x-server
|
||||
private CompletableFuture<Optional<DataSnapshot.Packed>> requestData(@NotNull UUID requestId, @NotNull User user) {
|
||||
final CompletableFuture<Optional<DataSnapshot.Packed>> future = new CompletableFuture<>();
|
||||
pendingRequests.put(requestId, future);
|
||||
@@ -247,19 +250,13 @@ public class RedisManager extends JedisPubSub {
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Set a user's data to Redis
|
||||
*
|
||||
* @param user the user to set data for
|
||||
* @param data the user's data to set
|
||||
* @param timeToLive The time to cache the data for
|
||||
*/
|
||||
// Set a user's data to Redis
|
||||
@Blocking
|
||||
public void setUserData(@NotNull User user, @NotNull DataSnapshot.Packed data, int timeToLive) {
|
||||
public void setUserData(@NotNull User user, @NotNull DataSnapshot.Packed data) {
|
||||
try (Jedis jedis = jedisPool.getResource()) {
|
||||
jedis.setex(
|
||||
getKey(RedisKeyType.LATEST_SNAPSHOT, user.getUuid(), clusterId),
|
||||
timeToLive,
|
||||
RedisKeyType.TTL_1_YEAR,
|
||||
data.asBytes(plugin)
|
||||
);
|
||||
plugin.debug(String.format("[%s] Set %s key on Redis", user.getName(), RedisKeyType.LATEST_SNAPSHOT));
|
||||
|
||||
@@ -23,7 +23,6 @@ import net.william278.husksync.HuskSync;
|
||||
import net.william278.husksync.api.HuskSyncAPI;
|
||||
import net.william278.husksync.data.DataSnapshot;
|
||||
import net.william278.husksync.database.Database;
|
||||
import net.william278.husksync.redis.RedisKeyType;
|
||||
import net.william278.husksync.redis.RedisManager;
|
||||
import net.william278.husksync.user.OnlineUser;
|
||||
import net.william278.husksync.user.User;
|
||||
@@ -104,7 +103,7 @@ public abstract class DataSyncer {
|
||||
public void saveCurrentUserData(@NotNull OnlineUser onlineUser, @NotNull DataSnapshot.SaveCause cause) {
|
||||
this.saveData(
|
||||
onlineUser, onlineUser.createSnapshot(cause),
|
||||
(user, data) -> getRedis().setUserData(user, data, RedisKeyType.TTL_10_SECONDS)
|
||||
(user, data) -> getRedis().setUserData(user, data)
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
@@ -21,7 +21,6 @@ package net.william278.husksync.sync;
|
||||
|
||||
import net.william278.husksync.HuskSync;
|
||||
import net.william278.husksync.data.DataSnapshot;
|
||||
import net.william278.husksync.redis.RedisKeyType;
|
||||
import net.william278.husksync.user.OnlineUser;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
@@ -63,7 +62,7 @@ public class DelayDataSyncer extends DataSyncer {
|
||||
getRedis().setUserServerSwitch(onlineUser);
|
||||
saveData(
|
||||
onlineUser, onlineUser.createSnapshot(DataSnapshot.SaveCause.DISCONNECT),
|
||||
(user, data) -> getRedis().setUserData(user, data, RedisKeyType.TTL_10_SECONDS)
|
||||
(user, data) -> getRedis().setUserData(user, data)
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
@@ -21,7 +21,6 @@ package net.william278.husksync.sync;
|
||||
|
||||
import net.william278.husksync.HuskSync;
|
||||
import net.william278.husksync.data.DataSnapshot;
|
||||
import net.william278.husksync.redis.RedisKeyType;
|
||||
import net.william278.husksync.user.OnlineUser;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
@@ -62,7 +61,7 @@ public class LockstepDataSyncer extends DataSyncer {
|
||||
plugin.runAsync(() -> saveData(
|
||||
onlineUser, onlineUser.createSnapshot(DataSnapshot.SaveCause.DISCONNECT),
|
||||
(user, data) -> {
|
||||
getRedis().setUserData(user, data, RedisKeyType.TTL_1_YEAR);
|
||||
getRedis().setUserData(user, data);
|
||||
getRedis().setUserCheckedOut(user, false);
|
||||
}
|
||||
));
|
||||
|
||||
Reference in New Issue
Block a user