Преглед изворни кода

fix(gui): show restarting modal during upgrade restart (fixes #1248) (#10566)

Signed-off-by: steadytao <[email protected]>
Signed-off-by: Jakob Borg <[email protected]>
Co-authored-by: Jakob Borg <[email protected]>
Tao пре 3 дана
родитељ
комит
f86c1d83db

+ 6 - 1
cmd/syncthing/main.go

@@ -748,8 +748,13 @@ func autoUpgrade(cfg config.Wrapper, app *syncthing.App, evLogger events.Logger)
 			continue
 		}
 		sub.Unsubscribe()
+		restartDelay := time.Minute
+		evLogger.Log(events.UpgradeRestartScheduled, map[string]any{
+			"delayS":     int(restartDelay / time.Second),
+			"newVersion": rel.Tag,
+		})
 		slog.Error("Automatically upgraded, restarting in 1 minute", slog.String("newVersion", rel.Tag))
-		time.Sleep(time.Minute)
+		time.Sleep(restartDelay)
 		app.Stop(svcutil.ExitUpgrade)
 		return
 	}

+ 1 - 0
gui/default/syncthing/core/eventService.js

@@ -73,6 +73,7 @@ angular.module('syncthing.core')
             CLUSTER_CONFIG_RECEIVED: 'ClusterConfigReceived',   // Emitted when receiving a remote device's cluster config
             DOWNLOAD_PROGRESS: 'DownloadProgress',   // Emitted during file downloads for each folder for each file
             FAILURE: 'Failure',   // Specific errors sent to the usage reporting server for diagnosis
+            UPGRADE_RESTART_SCHEDULED: 'UpgradeRestartScheduled',   // Auto-upgrade completed, restart scheduled
             FOLDER_COMPLETION: 'FolderCompletion',   //Emitted when the local or remote contents for a folder changes
             FOLDER_REJECTED: 'FolderRejected',   // DEPRECATED: Emitted when a device sends index information for a folder we do not have, or have but do not share with the device in question
             PENDING_FOLDERS_CHANGED: 'PendingFoldersChanged',   // Emitted when pending folders were added / updated (offered by some device, but not shared to them) or removed (folder ignored or added or no longer offered from the remote device)

+ 48 - 1
gui/default/syncthing/core/syncthingController.js

@@ -11,6 +11,8 @@ angular.module('syncthing.core')
         var navigatingAway = false;
         var online = false;
         var restarting = false;
+        var restartExpectedFrom = 0;
+        var restartExpectedUntil = 0;
 
         function initController() {
             LocaleService.autoConfigLocale();
@@ -33,6 +35,34 @@ angular.module('syncthing.core')
             Events.start();
         }
 
+        function clearRestartExpectation() {
+            restartExpectedFrom = 0;
+            restartExpectedUntil = 0;
+        }
+
+        function setRestartExpectation(delayS) {
+            var delay = delayS > 0 ? delayS : 60;
+            var delayMs = delay * 1000;
+            var earlyMs = 5 * 1000;
+            var graceMs = 60 * 1000;
+            var now = Date.now();
+
+            restartExpectedFrom = now + Math.max(0, delayMs - earlyMs);
+            restartExpectedUntil = now + delayMs + graceMs;
+        }
+
+        function restartExpectedNow() {
+            if (!restartExpectedUntil) {
+                return false;
+            }
+            var now = Date.now();
+            if (now > restartExpectedUntil) {
+                clearRestartExpectation();
+                return false;
+            }
+            return now >= restartExpectedFrom;
+        }
+
         // public/scope definitions
 
         // window.metadata is set in /meta.js which requires authentication
@@ -204,6 +234,7 @@ angular.module('syncthing.core')
 
                 online = true;
                 restarting = false;
+                clearRestartExpectation();
                 hideModal('#networkError');
                 hideModal('#restarting');
                 hideModal('#shutdown');
@@ -218,8 +249,24 @@ angular.module('syncthing.core')
             console.log('UIOffline');
             online = false;
             if (!restarting) {
-                showModal('#networkError');
+                if (restartExpectedNow()) {
+                    restarting = true;
+                    showModal('#restarting');
+                } else {
+                    showModal('#networkError');
+                }
+            }
+        });
+
+        $scope.$on(Events.UPGRADE_RESTART_SCHEDULED, function (_event, arg) {
+            var delayS = 0;
+            if (arg && arg.data && arg.data.delayS !== undefined) {
+                delayS = parseInt(arg.data.delayS, 10);
+                if (isNaN(delayS) || delayS < 0) {
+                    delayS = 0;
+                }
             }
+            setRestartExpectation(delayS);
         });
 
         $scope.$on('HTTPError', function (event, arg) {

+ 5 - 0
lib/events/events.go

@@ -57,6 +57,7 @@ const (
 	ListenAddressesChanged
 	LoginAttempt
 	Failure
+	UpgradeRestartScheduled
 
 	AllEvents = (1 << iota) - 1
 )
@@ -134,6 +135,8 @@ func (t EventType) String() string {
 		return "FolderWatchStateChanged"
 	case Failure:
 		return "Failure"
+	case UpgradeRestartScheduled:
+		return "UpgradeRestartScheduled"
 	default:
 		return "Unknown"
 	}
@@ -221,6 +224,8 @@ func UnmarshalEventType(s string) EventType {
 		return FolderWatchStateChanged
 	case "Failure":
 		return Failure
+	case "UpgradeRestartScheduled":
+		return UpgradeRestartScheduled
 	default:
 		return 0
 	}