fix behaviour when switching between enabled and disabled

This commit is contained in:
Eva Ho 2025-12-17 16:57:43 -05:00
parent cf7e5e88bc
commit 5a5d3260f4
2 changed files with 62 additions and 13 deletions

View File

@ -119,6 +119,7 @@ type UpdaterInterface interface {
CheckForUpdate(ctx context.Context) (bool, string, error)
DownloadUpdate(ctx context.Context, updateVersion string) error
InstallAndRestart() error
CancelOngoingDownload()
}
func (s *Server) log() *slog.Logger {
@ -1466,15 +1467,41 @@ func (s *Server) settings(w http.ResponseWriter, r *http.Request) error {
// Update tray notification based on auto-update toggle
if old.AutoUpdateEnabled && !settings.AutoUpdateEnabled {
// Auto-update disabled: clear tray notification
// Auto-update disabled: cancel any ongoing download and clear tray notification
if s.Updater != nil {
s.Updater.CancelOngoingDownload()
}
if s.ClearUpdateAvailableFunc != nil {
s.ClearUpdateAvailableFunc()
}
} else if !old.AutoUpdateEnabled && settings.AutoUpdateEnabled {
// Auto-update enabled: show tray notification if update is pending
if (updater.IsUpdatePending() || updater.UpdateDownloaded) && s.UpdateAvailableFunc != nil {
s.UpdateAvailableFunc()
}
// Auto-update enabled: check for updates and download if available
go func() {
// First, show notification if update is already pending
if (updater.IsUpdatePending() || updater.UpdateDownloaded) && s.UpdateAvailableFunc != nil {
s.UpdateAvailableFunc()
} else if s.Updater != nil {
// Otherwise, immediately check for and download new updates
slog.Info("auto-update re-enabled, checking for updates")
available, updateVersion, err := s.Updater.CheckForUpdate(r.Context())
if err != nil {
slog.Error("failed to check for update after re-enabling auto-update", "error", err)
return
}
if available {
slog.Info("update available, starting download", "version", updateVersion)
err := s.Updater.DownloadUpdate(r.Context(), updateVersion)
if err != nil {
slog.Error("failed to download update", "error", err)
return
}
// Show tray notification after successful download
if s.UpdateAvailableFunc != nil {
s.UpdateAvailableFunc()
}
}
}
}()
}
if old.ContextLength != settings.ContextLength ||
@ -1631,10 +1658,6 @@ func (s *Server) installUpdate(w http.ResponseWriter, r *http.Request) error {
return fmt.Errorf("no update downloaded")
}
// Check if we can actually upgrade (not in dev mode)
if updater.BundlePath == "" {
return fmt.Errorf("cannot install updates in development mode")
}
// Send response before restarting
response := map[string]any{

View File

@ -19,6 +19,7 @@ import (
"runtime"
"strconv"
"strings"
"sync"
"time"
"github.com/ollama/ollama/app/store"
@ -134,15 +135,27 @@ func (u *Updater) checkForUpdate(ctx context.Context) (bool, UpdateResponse) {
}
func (u *Updater) DownloadNewRelease(ctx context.Context, updateResp UpdateResponse) error {
// Create a cancellable context for this download
downloadCtx, cancel := context.WithCancel(ctx)
u.cancelDownloadLock.Lock()
u.cancelDownload = cancel
u.cancelDownloadLock.Unlock()
defer func() {
u.cancelDownloadLock.Lock()
u.cancelDownload = nil
u.cancelDownloadLock.Unlock()
cancel()
}()
// Do a head first to check etag info
req, err := http.NewRequestWithContext(ctx, http.MethodHead, updateResp.UpdateURL, nil)
req, err := http.NewRequestWithContext(downloadCtx, http.MethodHead, updateResp.UpdateURL, nil)
if err != nil {
return err
}
// In case of slow downloads, continue the update check in the background
bgctx, cancel := context.WithCancel(ctx)
defer cancel()
bgctx, bgcancel := context.WithCancel(downloadCtx)
defer bgcancel()
go func() {
for {
select {
@ -248,7 +261,20 @@ func cleanupOldDownloads(stageDir string) {
}
type Updater struct {
Store *store.Store
Store *store.Store
cancelDownload context.CancelFunc
cancelDownloadLock sync.Mutex
}
// CancelOngoingDownload cancels any currently running download
func (u *Updater) CancelOngoingDownload() {
u.cancelDownloadLock.Lock()
defer u.cancelDownloadLock.Unlock()
if u.cancelDownload != nil {
slog.Info("cancelling ongoing update download")
u.cancelDownload()
u.cancelDownload = nil
}
}
func (u *Updater) StartBackgroundUpdaterChecker(ctx context.Context, cb func(string) error) {