|
|
|
@ -22,14 +22,20 @@ package net.william278.husksync.sync;
|
|
|
|
|
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.RedisManager;
|
|
|
|
|
import net.william278.husksync.user.OnlineUser;
|
|
|
|
|
import net.william278.husksync.user.User;
|
|
|
|
|
import net.william278.husksync.util.Task;
|
|
|
|
|
import org.jetbrains.annotations.ApiStatus;
|
|
|
|
|
import org.jetbrains.annotations.Blocking;
|
|
|
|
|
import org.jetbrains.annotations.NotNull;
|
|
|
|
|
import org.jetbrains.annotations.Nullable;
|
|
|
|
|
|
|
|
|
|
import java.util.concurrent.atomic.AtomicBoolean;
|
|
|
|
|
import java.util.concurrent.atomic.AtomicLong;
|
|
|
|
|
import java.util.concurrent.atomic.AtomicReference;
|
|
|
|
|
import java.util.function.BiConsumer;
|
|
|
|
|
import java.util.function.Function;
|
|
|
|
|
import java.util.function.Supplier;
|
|
|
|
|
|
|
|
|
@ -87,6 +93,42 @@ public abstract class DataSyncer {
|
|
|
|
|
*/
|
|
|
|
|
public abstract void saveUserData(@NotNull OnlineUser user);
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Save a {@link DataSnapshot.Packed user's data snapshot} to the database,
|
|
|
|
|
* first firing the {@link net.william278.husksync.event.DataSaveEvent}. This will not update data on Redis.
|
|
|
|
|
*
|
|
|
|
|
* @param user the user to save the data for
|
|
|
|
|
* @param data the data to save
|
|
|
|
|
* @param after a consumer to run after data has been saved. Will be run async (off the main thread).
|
|
|
|
|
* @apiNote Data will not be saved if the {@link net.william278.husksync.event.DataSaveEvent} is cancelled.
|
|
|
|
|
* Note that this method can also edit the data before saving it.
|
|
|
|
|
* @implNote Note that the {@link net.william278.husksync.event.DataSaveEvent} will <b>not</b> be fired if the
|
|
|
|
|
* save cause is {@link DataSnapshot.SaveCause#SERVER_SHUTDOWN}.
|
|
|
|
|
* @since 3.3.2
|
|
|
|
|
*/
|
|
|
|
|
@Blocking
|
|
|
|
|
public void saveData(@NotNull User user, @NotNull DataSnapshot.Packed data,
|
|
|
|
|
@Nullable BiConsumer<User, DataSnapshot.Packed> after) {
|
|
|
|
|
if (data.getSaveCause() == DataSnapshot.SaveCause.SERVER_SHUTDOWN) {
|
|
|
|
|
addSnapshotToDatabase(user, data, after);
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
plugin.fireEvent(
|
|
|
|
|
plugin.getDataSaveEvent(user, data),
|
|
|
|
|
(event) -> addSnapshotToDatabase(user, data, after)
|
|
|
|
|
);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Adds a snapshot to the database and runs the after consumer
|
|
|
|
|
@Blocking
|
|
|
|
|
private void addSnapshotToDatabase(@NotNull User user, @NotNull DataSnapshot.Packed data,
|
|
|
|
|
@Nullable BiConsumer<User, DataSnapshot.Packed> after) {
|
|
|
|
|
getDatabase().addSnapshot(user, data);
|
|
|
|
|
if (after != null) {
|
|
|
|
|
after.accept(user, data);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Calculates the max attempts the system should listen for user data for based on the latency value
|
|
|
|
|
private long getMaxListenAttempts() {
|
|
|
|
|
return BASE_LISTEN_ATTEMPTS + (
|
|
|
|
@ -98,7 +140,7 @@ public abstract class DataSyncer {
|
|
|
|
|
// Set a user's data from the database, or set them as a new user
|
|
|
|
|
@ApiStatus.Internal
|
|
|
|
|
protected void setUserFromDatabase(@NotNull OnlineUser user) {
|
|
|
|
|
plugin.getDatabase().getLatestSnapshot(user).ifPresentOrElse(
|
|
|
|
|
getDatabase().getLatestSnapshot(user).ifPresentOrElse(
|
|
|
|
|
snapshot -> user.applySnapshot(snapshot, DataSnapshot.UpdateCause.SYNCHRONIZED),
|
|
|
|
|
() -> user.completeSync(true, DataSnapshot.UpdateCause.NEW_USER, plugin)
|
|
|
|
|
);
|
|
|
|
@ -139,6 +181,16 @@ public abstract class DataSyncer {
|
|
|
|
|
task.get().run();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@NotNull
|
|
|
|
|
protected RedisManager getRedis() {
|
|
|
|
|
return plugin.getRedisManager();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@NotNull
|
|
|
|
|
protected Database getDatabase() {
|
|
|
|
|
return plugin.getDatabase();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Represents the different available default modes of {@link DataSyncer}
|
|
|
|
|
*
|
|
|
|
|