33import org .cryptomator .cryptofs .VaultConfig ;
44import org .cryptomator .cryptolib .api .Cryptor ;
55import org .cryptomator .cryptolib .api .Masterkey ;
6+ import org .slf4j .LoggerFactory ;
67
78import java .nio .file .Path ;
89import java .util .Collection ;
910import java .util .ServiceLoader ;
1011import java .util .concurrent .ExecutorService ;
11- import java .util .concurrent .Executors ;
12- import java .util .concurrent .ForkJoinPool ;
12+ import java .util .function .Consumer ;
1313import java .util .stream .Stream ;
14+ import java .util .stream .StreamSupport ;
1415
1516public interface HealthCheck {
1617
18+ /**
19+ * @return All known health checks
20+ */
21+ static Collection <HealthCheck > allChecks () {
22+ return ServiceLoader .load (HealthCheck .class ).stream ().map (ServiceLoader .Provider ::get ).toList ();
23+ }
24+
1725 /**
1826 * @return A unique name for this check (that might be used as a translation key)
1927 */
@@ -24,24 +32,42 @@ default String identifier() {
2432 /**
2533 * Checks the vault at the given path.
2634 *
27- * @param pathToVault Path to the vault's root directory
28- * @param config The parsed and verified vault config
29- * @param masterkey The masterkey
30- * @param cryptor A cryptor initialized for this vault
31- * @param executor An executor service to run the health check
32- * @return Diagnostic results
35+ * @param pathToVault Path to the vault's root directory
36+ * @param config The parsed and verified vault config
37+ * @param masterkey The masterkey
38+ * @param cryptor A cryptor initialized for this vault
39+ * @param resultCollector Callback called for each result.
3340 */
34- Stream < DiagnosticResult > check (Path pathToVault , VaultConfig config , Masterkey masterkey , Cryptor cryptor , ExecutorService executor );
41+ void check (Path pathToVault , VaultConfig config , Masterkey masterkey , Cryptor cryptor , Consumer < DiagnosticResult > resultCollector );
3542
3643 /**
37- * Attempts to cancel this health check (if it is running).
44+ * Invokes the health check on a background thread scheduled using the given executor service. The results will be
45+ * streamed. If the stream gets {@link Stream#close() closed} before it terminates, an attempt is made to cancel
46+ * the health check.
47+ * <p>
48+ * The check blocks if the stream is not consumed
3849 *
39- * Calling this method does not guarantee that no further results are produced due to async behaviour.
50+ * @param pathToVault Path to the vault's root directory
51+ * @param config The parsed and verified vault config
52+ * @param masterkey The masterkey
53+ * @param cryptor A cryptor initialized for this vault
54+ * @param executor An executor service to run the health check
55+ * @return A lazily filled stream of diagnostic results.
4056 */
41- void cancel ();
57+ default Stream <DiagnosticResult > check (Path pathToVault , VaultConfig config , Masterkey masterkey , Cryptor cryptor , ExecutorService executor ) {
58+ var resultSpliterator = new TransferSpliterator <DiagnosticResult >(new PoisonResult ());
4259
43- static Collection <HealthCheck > allChecks () {
44- return ServiceLoader .load (HealthCheck .class ).stream ().map (ServiceLoader .Provider ::get ).toList ();
60+ var task = executor .submit (() -> {
61+ try {
62+ check (pathToVault , config , masterkey , cryptor , resultSpliterator );
63+ } catch (TransferSpliterator .TransferClosedException e ) {
64+ LoggerFactory .getLogger (HealthCheck .class ).debug ("{} cancelled." , identifier ());
65+ } finally {
66+ resultSpliterator .close ();
67+ }
68+ });
69+
70+ return StreamSupport .stream (resultSpliterator , false ).onClose (() -> task .cancel (true ));
4571 }
4672
47- }
73+ }
0 commit comments