Improve error handling on data sync

feat/data-edit-commands 3.0.1
William 1 year ago
parent b63e1bd283
commit 55e443cd49
No known key found for this signature in database

@ -53,14 +53,8 @@ import java.util.stream.Collectors;
public abstract class BukkitData implements Data { public abstract class BukkitData implements Data {
@Override @Override
public final void apply(@NotNull UserDataHolder dataHolder, @NotNull HuskSync plugin) { public final void apply(@NotNull UserDataHolder dataHolder, @NotNull HuskSync plugin) throws IllegalStateException {
final BukkitUser user = (BukkitUser) dataHolder; this.apply((BukkitUser) dataHolder, (BukkitHuskSync) plugin);
try {
this.apply(user, (BukkitHuskSync) plugin);
} catch (Throwable e) {
plugin.log(Level.WARNING, String.format("[%s] Failed to apply %s data object; skipping",
user.getUsername(), this.getClass().getSimpleName()), e);
}
} }
public abstract void apply(@NotNull BukkitUser user, @NotNull BukkitHuskSync plugin) throws IllegalStateException; public abstract void apply(@NotNull BukkitUser user, @NotNull BukkitHuskSync plugin) throws IllegalStateException;

@ -26,6 +26,7 @@ import org.jetbrains.annotations.NotNull;
import java.util.HashMap; import java.util.HashMap;
import java.util.Map; import java.util.Map;
import java.util.logging.Level;
/** /**
* A holder of data in the form of {@link Data}s, which can be synced * A holder of data in the form of {@link Data}s, which can be synced
@ -83,22 +84,40 @@ public interface UserDataHolder extends DataHolder {
* The {@code runAfter} callback function will be run after the snapshot has been applied. * The {@code runAfter} callback function will be run after the snapshot has been applied.
* *
* @param snapshot the snapshot to apply * @param snapshot the snapshot to apply
* @param runAfter the function to run asynchronously after the snapshot has been applied * @param runAfter a consumer accepting a boolean value, indicating if the data was successfully applied,
* which will be run after the snapshot has been applied
* @since 3.0 * @since 3.0
*/ */
default void applySnapshot(@NotNull DataSnapshot.Packed snapshot, @NotNull ThrowingConsumer<UserDataHolder> runAfter) { default void applySnapshot(@NotNull DataSnapshot.Packed snapshot, @NotNull ThrowingConsumer<Boolean> runAfter) {
final HuskSync plugin = getPlugin(); final HuskSync plugin = getPlugin();
final DataSnapshot.Unpacked unpacked = snapshot.unpack(plugin);
// Unpack the snapshot
final DataSnapshot.Unpacked unpacked;
try {
unpacked = snapshot.unpack(plugin);
} catch (Throwable e) {
plugin.log(Level.SEVERE, String.format("Failed to unpack data snapshot for %s", getUsername()), e);
return;
}
// Synchronously attempt to apply the snapshot
plugin.runSync(() -> { plugin.runSync(() -> {
unpacked.getData().forEach((type, data) -> { try {
if (plugin.getSettings().isSyncFeatureEnabled(type)) { for (Map.Entry<Identifier, Data> entry : unpacked.getData().entrySet()) {
if (type.isCustom()) { final Identifier identifier = entry.getKey();
getCustomDataStore().put(type, data); if (plugin.getSettings().isSyncFeatureEnabled(identifier)) {
if (identifier.isCustom()) {
getCustomDataStore().put(identifier, entry.getValue());
} }
data.apply(this, plugin); entry.getValue().apply(this, plugin);
} }
}); }
plugin.runAsync(() -> runAfter.accept(this)); } catch (Throwable e) {
plugin.log(Level.SEVERE, String.format("Failed to apply data snapshot to %s", getUsername()), e);
plugin.runAsync(() -> runAfter.accept(false));
return;
}
plugin.runAsync(() -> runAfter.accept(true));
}); });
} }
@ -157,6 +176,9 @@ public interface UserDataHolder extends DataHolder {
this.setData(Identifier.PERSISTENT_DATA, persistentData); this.setData(Identifier.PERSISTENT_DATA, persistentData);
} }
@NotNull
String getUsername();
@NotNull @NotNull
Map<Identifier, Data> getCustomDataStore(); Map<Identifier, Data> getCustomDataStore();

@ -125,12 +125,14 @@ public abstract class OnlineUser extends User implements CommandUser, UserDataHo
* Set a player's status from a {@link DataSnapshot} * Set a player's status from a {@link DataSnapshot}
* *
* @param snapshot The {@link DataSnapshot} to set the player's status from * @param snapshot The {@link DataSnapshot} to set the player's status from
* @param cause The {@link DataSnapshot.UpdateCause} of the snapshot
* @since 3.0
*/ */
public void applySnapshot(@NotNull DataSnapshot.Packed snapshot, @NotNull DataSnapshot.UpdateCause cause) { public void applySnapshot(@NotNull DataSnapshot.Packed snapshot, @NotNull DataSnapshot.UpdateCause cause) {
getPlugin().fireEvent(getPlugin().getPreSyncEvent(this, snapshot), (event) -> { getPlugin().fireEvent(getPlugin().getPreSyncEvent(this, snapshot), (event) -> {
if (!isOffline()) { if (!isOffline()) {
UserDataHolder.super.applySnapshot( UserDataHolder.super.applySnapshot(
event.getData(), (owner) -> completeSync(true, cause, getPlugin()) event.getData(), (succeeded) -> completeSync(succeeded, cause, getPlugin())
); );
} }
}); });

Loading…
Cancel
Save