feat: Настройки › Автообновление - clients compare their version with the server's every N and update themselves; the server looks at GitLab every N and, when a newer release is out, offers it to an administrator at login (after the PIN) with «Обновить» and «Отказаться»; the words of a made picture's result are the model's only
This commit is contained in:
1 parent
916a49958b
commit
3d2f886f04
22 files changed
+1074
-7
No files matched your search
@@ -0,0 +1,95 @@
|
||||
package agent
|
||||
|
||||
import (
|
||||
"context"
|
||||
"log"
|
||||
"net/http"
|
||||
"strconv"
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
"github.com/x-grk/longpolling-remote-access/internal/proto"
|
||||
)
|
||||
|
||||
// Auto-update, the agent's part: the server tells (with every poll, on its
|
||||
// config and on the WebSocket) its own version and how often to compare -
|
||||
// in minutes, 0 for never. When the server's version is newer, the agent
|
||||
// takes the new one from it, as the panel's «Обновить» does.
|
||||
|
||||
// autoUpdate is what the agent was told, and when it last looked.
|
||||
type autoUpdate struct {
|
||||
mu sync.Mutex
|
||||
minutes int
|
||||
serverVer string
|
||||
last time.Time
|
||||
}
|
||||
|
||||
func (a *Agent) applyUpdateInfo(minutes int, serverVersion string) {
|
||||
a.auto.mu.Lock()
|
||||
defer a.auto.mu.Unlock()
|
||||
if minutes < 0 {
|
||||
minutes = 0
|
||||
}
|
||||
a.auto.minutes = minutes
|
||||
if serverVersion != "" {
|
||||
a.auto.serverVer = serverVersion
|
||||
}
|
||||
}
|
||||
|
||||
// applyUpdateHeaders takes the settings from the headers of an answer; an
|
||||
// answer without them (an older server) changes nothing.
|
||||
func (a *Agent) applyUpdateHeaders(h http.Header) {
|
||||
v := h.Get(proto.AutoUpdateHeader)
|
||||
if v == "" {
|
||||
return
|
||||
}
|
||||
m, err := strconv.Atoi(v)
|
||||
if err != nil {
|
||||
m = 0
|
||||
}
|
||||
a.applyUpdateInfo(m, h.Get(proto.ServerVersionHeader))
|
||||
}
|
||||
|
||||
func (a *Agent) updateInfo() (int, string) {
|
||||
a.auto.mu.Lock()
|
||||
defer a.auto.mu.Unlock()
|
||||
return a.auto.minutes, a.auto.serverVer
|
||||
}
|
||||
|
||||
func (a *Agent) autoUpdateOn() bool { m, _ := a.updateInfo(); return m > 0 }
|
||||
|
||||
// autoUpdateTick: one look at the clock. Out of the interval since the last
|
||||
// look, it looks; the server's version newer than its own, it updates.
|
||||
// Reports whether it did.
|
||||
func (a *Agent) autoUpdateTick(now time.Time, update func() proto.TaskResult) bool {
|
||||
a.auto.mu.Lock()
|
||||
if a.auto.minutes <= 0 || (!a.auto.last.IsZero() && now.Sub(a.auto.last) < time.Duration(a.auto.minutes)*time.Minute) {
|
||||
a.auto.mu.Unlock()
|
||||
return false
|
||||
}
|
||||
a.auto.last = now
|
||||
server := a.auto.serverVer
|
||||
a.auto.mu.Unlock()
|
||||
if !proto.VersionNewer(server, Version) {
|
||||
return false
|
||||
}
|
||||
log.Printf("auto-update: server has %s, this is %s - updating", server, Version)
|
||||
if res := update(); !res.OK {
|
||||
log.Printf("auto-update: %s", res.Error)
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
// autoUpdateLoop watches the clock until ctx ends.
|
||||
func (a *Agent) autoUpdateLoop(ctx context.Context) {
|
||||
t := time.NewTicker(30 * time.Second)
|
||||
defer t.Stop()
|
||||
for {
|
||||
select {
|
||||
case <-ctx.Done():
|
||||
return
|
||||
case now := <-t.C:
|
||||
a.autoUpdateTick(now, a.doUpdate)
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in new issue
Block a user