diff --git a/api/http/handler/edgestacks/edgestack_status_update.go b/api/http/handler/edgestacks/edgestack_status_update.go index 08bd8bdf1..c38300a49 100644 --- a/api/http/handler/edgestacks/edgestack_status_update.go +++ b/api/http/handler/edgestacks/edgestack_status_update.go @@ -4,6 +4,7 @@ import ( "errors" "fmt" "net/http" + "strconv" "time" portainer "github.com/portainer/portainer/api" @@ -20,6 +21,7 @@ type updateStatusPayload struct { Status *portainer.EdgeStackStatusType EndpointID portainer.EndpointID Time int64 + Version int } func (payload *updateStatusPayload) Validate(r *http.Request) error { @@ -69,6 +71,10 @@ func (handler *Handler) edgeStackStatusUpdate(w http.ResponseWriter, r *http.Req var stack *portainer.EdgeStack if err := handler.DataStore.UpdateTx(func(tx dataservices.DataStoreTx) error { + if r.Context().Err() != nil { + return err + } + stack, err = handler.updateEdgeStackStatus(tx, r, portainer.EdgeStackID(stackID), payload) return err }); err != nil { @@ -80,6 +86,10 @@ func (handler *Handler) edgeStackStatusUpdate(w http.ResponseWriter, r *http.Req return httperror.InternalServerError("Unexpected error", err) } + if ok, _ := strconv.ParseBool(r.Header.Get("X-Portainer-No-Body")); ok { + return nil + } + return response.JSON(w, stack) } @@ -87,18 +97,23 @@ func (handler *Handler) updateEdgeStackStatus(tx dataservices.DataStoreTx, r *ht stack, err := tx.EdgeStack().EdgeStack(stackID) if err != nil { if dataservices.IsErrObjectNotFound(err) { - // skip error because agent tries to report on deleted stack + // Skip error because agent tries to report on deleted stack log.Debug(). Err(err). Int("stackID", int(stackID)). Int("status", int(*payload.Status)). Msg("Unable to find a stack inside the database, skipping error") + return nil, nil } return nil, fmt.Errorf("unable to retrieve Edge stack from the database: %w. Environment ID: %d", err, payload.EndpointID) } + if payload.Version > 0 && payload.Version < stack.Version { + return stack, nil + } + endpoint, err := tx.Endpoint().Endpoint(payload.EndpointID) if err != nil { return nil, handler.handlerDBErr(fmt.Errorf("unable to find the environment from the database: %w. Environment ID: %d", err, payload.EndpointID), "unable to find the environment") diff --git a/api/internal/edge/edgestacks/status.go b/api/internal/edge/edgestacks/status.go index da12df394..25629d958 100644 --- a/api/internal/edge/edgestacks/status.go +++ b/api/internal/edge/edgestacks/status.go @@ -9,7 +9,6 @@ func NewStatus(oldStatus map[portainer.EndpointID]portainer.EdgeStackStatus, rel status := map[portainer.EndpointID]portainer.EdgeStackStatus{} for _, environmentID := range relatedEnvironmentIDs { - newEnvStatus := portainer.EdgeStackStatus{ Status: []portainer.EdgeStackDeploymentStatus{}, EndpointID: environmentID, diff --git a/api/portainer.go b/api/portainer.go index b507e6290..2700696e8 100644 --- a/api/portainer.go +++ b/api/portainer.go @@ -370,6 +370,7 @@ type ( Error string // EE only feature RollbackTo *int + Version int `json:"Version,omitempty"` } // EdgeStackStatusType represents an edge stack status type