diff --git a/internal/pkg/service/appsproxy/dataapps/api/config.go b/internal/pkg/service/appsproxy/dataapps/api/config.go index 5a8733b640..72136f8854 100644 --- a/internal/pkg/service/appsproxy/dataapps/api/config.go +++ b/internal/pkg/service/appsproxy/dataapps/api/config.go @@ -17,11 +17,12 @@ import ( const ( // maxCacheExpiration is the maximum duration for which an old AppConfig of a data app is cached. - maxCacheExpiration = time.Hour - attrProjectID = "proxy.app.projectId" - attrAppID = "proxy.app.id" - attrAppName = "proxy.app.name" - attrAppUpstream = "proxy.app.upstream" + maxCacheExpiration = time.Hour + attrSandboxesServiceStatusCode = "proxy.sandboxesService.statusCode" + attrProjectID = "proxy.app.projectId" + attrAppID = "proxy.app.id" + attrAppName = "proxy.app.name" + attrAppUpstream = "proxy.app.upstream" ) type AppID string diff --git a/internal/pkg/service/appsproxy/dataapps/api/wakeup.go b/internal/pkg/service/appsproxy/dataapps/api/wakeup.go index 4c0b1098ab..b735f86b35 100644 --- a/internal/pkg/service/appsproxy/dataapps/api/wakeup.go +++ b/internal/pkg/service/appsproxy/dataapps/api/wakeup.go @@ -1,6 +1,12 @@ package api -import "github.com/keboola/go-client/pkg/request" +import ( + "context" + + "github.com/keboola/go-client/pkg/request" + "go.opentelemetry.io/otel/attribute" + "go.opentelemetry.io/otel/trace" +) type wakeupBody struct { DesiredState string `json:"desiredState"` @@ -9,6 +15,14 @@ type wakeupBody struct { func (a *API) WakeupApp(appID AppID) request.APIRequest[request.NoResult] { return request.NewAPIRequest(request.NoResult{}, a.newRequest(). WithError(&Error{}). + WithOnError(func(ctx context.Context, response request.HTTPResponse, err error) error { + span := trace.SpanFromContext(ctx) + attrs := []attribute.KeyValue{ + attribute.Int(attrSandboxesServiceStatusCode, response.StatusCode()), + } + span.SetAttributes(attrs...) + return nil + }). WithPatch("apps/{appId}"). AndPathParam("appId", appID.String()). WithJSONBody(wakeupBody{ diff --git a/internal/pkg/service/appsproxy/dataapps/wakeup/wakeup.go b/internal/pkg/service/appsproxy/dataapps/wakeup/wakeup.go index 18453ba895..a7a057d6d4 100644 --- a/internal/pkg/service/appsproxy/dataapps/wakeup/wakeup.go +++ b/internal/pkg/service/appsproxy/dataapps/wakeup/wakeup.go @@ -16,7 +16,10 @@ import ( // Interval sets how often the proxy sends wakeup request to sandboxes service. // If the last notification for the app was less than this Interval ago then the notification is skipped. -const Interval = time.Second +const ( + Interval = time.Second + wakeupErrorToBeSkipped = `can't have desired state "running". Currently is in state: "stopping", desired state: "stopped"` +) type Manager struct { clock clock.Clock @@ -68,7 +71,11 @@ func (l *Manager) Wakeup(ctx context.Context, appID api.AppID) error { item.nextRequestAfter = now.Add(Interval) // Send the notification - if _, err := l.api.WakeupApp(appID).Send(ctx); err != nil { + _, err := l.api.WakeupApp(appID).Send(ctx) + // If it does not succeed but app is currently stopping do not log it as error, log only other errors + // Instead of implementing state machine as in sandboxes service, we want to skip valid state that the + // pod is dealocating and we want to wait till pod is `stopped` and we can `start` the pod again. + if err != nil && err.Error() != wakeupErrorToBeSkipped { l.logger.Errorf(ctx, `failed sending wakeup request to Sandboxes Service about for app "%s": %s`, appID, err.Error()) return err } diff --git a/internal/pkg/service/appsproxy/proxy/apphandler/upstream/upstream.go b/internal/pkg/service/appsproxy/proxy/apphandler/upstream/upstream.go index 0f2e036435..78222aa10b 100644 --- a/internal/pkg/service/appsproxy/proxy/apphandler/upstream/upstream.go +++ b/internal/pkg/service/appsproxy/proxy/apphandler/upstream/upstream.go @@ -30,7 +30,7 @@ import ( const ( notifyRequestTimeout = 5 * time.Second - wakeupRequestTimeout = 15 * time.Second + wakeupRequestTimeout = 60 * time.Second attrWakeupReason = "proxy.wakeup.reason" attrWebsocket = "proxy.websocket" )