From 374493e8b416d56776d5f973e6d0c5d381661ec0 Mon Sep 17 00:00:00 2001 From: Sebastian Stenzel Date: Wed, 30 Jun 2021 14:15:23 +0200 Subject: [PATCH] implemented async sequential fix queue --- .../ui/health/ResultFixApplier.java | 38 ++++++++++++++----- .../ui/health/ResultListCellController.java | 25 +++++++----- 2 files changed, 44 insertions(+), 19 deletions(-) diff --git a/src/main/java/org/cryptomator/ui/health/ResultFixApplier.java b/src/main/java/org/cryptomator/ui/health/ResultFixApplier.java index feea6eae0..841a8f5c4 100644 --- a/src/main/java/org/cryptomator/ui/health/ResultFixApplier.java +++ b/src/main/java/org/cryptomator/ui/health/ResultFixApplier.java @@ -10,20 +10,24 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; import javax.inject.Inject; -import javafx.scene.control.Alert; +import javafx.application.Platform; import java.nio.file.Path; import java.security.SecureRandom; +import java.util.concurrent.CompletableFuture; +import java.util.concurrent.CompletionException; +import java.util.concurrent.CompletionStage; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executors; import java.util.concurrent.atomic.AtomicReference; @HealthCheckScoped class ResultFixApplier { - private static final Logger LOG = LoggerFactory.getLogger(ResultFixApplier.class); - private final Path vaultPath; private final SecureRandom csprng; private final Masterkey masterkey; private final VaultConfig vaultConfig; + private final ExecutorService sequentialExecutor; @Inject public ResultFixApplier(@HealthCheckWindow Vault vault, AtomicReference masterkeyRef, AtomicReference vaultConfigRef, SecureRandom csprng) { @@ -31,18 +35,32 @@ class ResultFixApplier { this.masterkey = masterkeyRef.get(); this.vaultConfig = vaultConfigRef.get(); this.csprng = csprng; + this.sequentialExecutor = Executors.newSingleThreadExecutor(); } - public void fix(DiagnosticResult result) { - Preconditions.checkArgument(result.getSeverity() == DiagnosticResult.Severity.WARN, "Unfixable result"); + public CompletionStage fix(Result result) { + Preconditions.checkArgument(result.getState() == Result.FixState.FIXABLE); + result.setState(Result.FixState.FIXING); + return CompletableFuture.runAsync(() -> fix(result.diagnosis()), sequentialExecutor) + .whenCompleteAsync((unused, throwable) -> { + var fixed = throwable == null ? Result.FixState.FIXED : Result.FixState.FIX_FAILED; + result.setState(fixed); + }, Platform::runLater); + } + + public void fix(DiagnosticResult diagnosis) { + Preconditions.checkArgument(diagnosis.getSeverity() == DiagnosticResult.Severity.WARN, "Unfixable result"); try (var masterkeyClone = masterkey.clone(); // var cryptor = CryptorProvider.forScheme(vaultConfig.getCipherCombo()).provide(masterkeyClone, csprng)) { - result.fix(vaultPath, vaultConfig, masterkeyClone, cryptor); + diagnosis.fix(vaultPath, vaultConfig, masterkeyClone, cryptor); } catch (Exception e) { - LOG.error("Failed to apply fix", e); - Alert alert = new Alert(Alert.AlertType.ERROR, e.getMessage()); - alert.showAndWait(); - //TODO: real error/not supported handling + throw new FixFailedException(e); + } + } + + public static class FixFailedException extends CompletionException { + private FixFailedException(Throwable cause) { + super(cause); } } } diff --git a/src/main/java/org/cryptomator/ui/health/ResultListCellController.java b/src/main/java/org/cryptomator/ui/health/ResultListCellController.java index cf9f03a73..683d0fb93 100644 --- a/src/main/java/org/cryptomator/ui/health/ResultListCellController.java +++ b/src/main/java/org/cryptomator/ui/health/ResultListCellController.java @@ -16,7 +16,6 @@ import javafx.beans.binding.BooleanBinding; import javafx.beans.binding.ObjectBinding; import javafx.beans.property.ObjectProperty; import javafx.beans.property.SimpleObjectProperty; -import javafx.beans.value.ObservableObjectValue; import javafx.fxml.FXML; import javafx.scene.control.Button; @@ -49,14 +48,6 @@ public class ResultListCellController implements FxController { this.fixed = Bindings.createBooleanBinding(this::isFixed, fixState); } - @FXML - public void fix() { - final var realResult = result.get(); - if (realResult != null) { - fixApplier.fix(realResult); - } - } - @FXML public void initialize() { // see getGlyph() for relevant glyphs: @@ -66,6 +57,22 @@ public class ResultListCellController implements FxController { EasyBind.includeWhen(iconView.getStyleClass(), "glyph-icon-red", iconView.glyphProperty().isEqualTo(FontAwesome5Icon.TIMES)); } + @FXML + public void fix() { + Result r = result.get(); + if (r != null) { + fixApplier.fix(r).whenCompleteAsync(this::fixFinished, Platform::runLater); + } + } + + private void fixFinished(Void unused, Throwable exception) { + if (exception != null) { + LOG.error("Failed to apply fix", exception); + // TODO ... + } + } + + /* Getter & Setter */ public Result getResult() {