mirror of
https://github.com/rcourtman/Pulse.git
synced 2026-05-11 21:28:15 +00:00
- Use background context for update downloads to prevent cancellation - Detect actual binary location and update correct file - Support both 'pulse' and 'pulse-backend' service names - Copy VERSION file to multiple locations for compatibility - Handle flat tarball structure from GitHub releases
99 lines
No EOL
2.6 KiB
Go
99 lines
No EOL
2.6 KiB
Go
package api
|
|
|
|
import (
|
|
"context"
|
|
"encoding/json"
|
|
"net/http"
|
|
|
|
"github.com/rcourtman/pulse-go-rewrite/internal/updates"
|
|
"github.com/rs/zerolog/log"
|
|
)
|
|
|
|
// UpdateHandlers handles update-related API requests
|
|
type UpdateHandlers struct {
|
|
manager *updates.Manager
|
|
}
|
|
|
|
// NewUpdateHandlers creates new update handlers
|
|
func NewUpdateHandlers(manager *updates.Manager) *UpdateHandlers {
|
|
return &UpdateHandlers{
|
|
manager: manager,
|
|
}
|
|
}
|
|
|
|
// HandleCheckUpdates handles update check requests
|
|
func (h *UpdateHandlers) HandleCheckUpdates(w http.ResponseWriter, r *http.Request) {
|
|
if r.Method != http.MethodGet {
|
|
http.Error(w, "Method not allowed", http.StatusMethodNotAllowed)
|
|
return
|
|
}
|
|
|
|
ctx := r.Context()
|
|
|
|
// Get channel from query parameter if provided
|
|
channel := r.URL.Query().Get("channel")
|
|
|
|
info, err := h.manager.CheckForUpdatesWithChannel(ctx, channel)
|
|
if err != nil {
|
|
log.Error().Err(err).Msg("Failed to check for updates")
|
|
http.Error(w, "Failed to check for updates", http.StatusInternalServerError)
|
|
return
|
|
}
|
|
|
|
w.Header().Set("Content-Type", "application/json")
|
|
if err := json.NewEncoder(w).Encode(info); err != nil {
|
|
log.Error().Err(err).Msg("Failed to encode update info")
|
|
}
|
|
}
|
|
|
|
// HandleApplyUpdate handles update application requests
|
|
func (h *UpdateHandlers) HandleApplyUpdate(w http.ResponseWriter, r *http.Request) {
|
|
if r.Method != http.MethodPost {
|
|
http.Error(w, "Method not allowed", http.StatusMethodNotAllowed)
|
|
return
|
|
}
|
|
|
|
var req struct {
|
|
DownloadURL string `json:"downloadUrl"`
|
|
}
|
|
|
|
if err := json.NewDecoder(r.Body).Decode(&req); err != nil {
|
|
http.Error(w, "Invalid request body", http.StatusBadRequest)
|
|
return
|
|
}
|
|
|
|
if req.DownloadURL == "" {
|
|
http.Error(w, "Download URL is required", http.StatusBadRequest)
|
|
return
|
|
}
|
|
|
|
// Start update in background with a new context (not request context which gets cancelled)
|
|
go func() {
|
|
ctx := context.Background()
|
|
if err := h.manager.ApplyUpdate(ctx, req.DownloadURL); err != nil {
|
|
log.Error().Err(err).Msg("Failed to apply update")
|
|
}
|
|
}()
|
|
|
|
// Return success immediately
|
|
w.Header().Set("Content-Type", "application/json")
|
|
json.NewEncoder(w).Encode(map[string]string{
|
|
"status": "started",
|
|
"message": "Update process started",
|
|
})
|
|
}
|
|
|
|
// HandleUpdateStatus handles update status requests
|
|
func (h *UpdateHandlers) HandleUpdateStatus(w http.ResponseWriter, r *http.Request) {
|
|
if r.Method != http.MethodGet {
|
|
http.Error(w, "Method not allowed", http.StatusMethodNotAllowed)
|
|
return
|
|
}
|
|
|
|
status := h.manager.GetStatus()
|
|
|
|
w.Header().Set("Content-Type", "application/json")
|
|
if err := json.NewEncoder(w).Encode(status); err != nil {
|
|
log.Error().Err(err).Msg("Failed to encode update status")
|
|
}
|
|
} |