Skip to content

Commit 1107384

Browse files
authored
fix: last request idleness check (#993)
1 parent 8eaf38f commit 1107384

File tree

1 file changed

+44
-24
lines changed

1 file changed

+44
-24
lines changed

internal/controller/status.go

Lines changed: 44 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -16,8 +16,12 @@ import (
1616
"sigs.k8s.io/controller-runtime/pkg/log"
1717
)
1818

19+
// If the cpu usage of the session is less than this then the session is considered idle
1920
var cpuUsageIdlenessThreshold resource.Quantity = *resource.NewMilliQuantity(300, resource.DecimalSI)
2021

22+
// If the last request performed in the user session is older than this the session is considered idle
23+
const lastRequestAgeThreshold time.Duration = time.Minute * 30
24+
2125
// countainerCounts provides from the total and completed/fully running containers in a pod.
2226
// The output is a tuple with the init container counts followed by the regular container counts.
2327
func containerCounts(pod *v1.Pod) (amaltheadevv1alpha1.ContainerCounts, amaltheadevv1alpha1.ContainerCounts) {
@@ -82,7 +86,7 @@ func metrics(ctx context.Context, clnt metricsv1beta1.PodMetricsesGetter, cr *am
8286
return nil, fmt.Errorf("could not find the metrics for the session container %s", amaltheadevv1alpha1.SessionContainerName)
8387
}
8488

85-
func lastRequestTime(cr *amaltheadevv1alpha1.AmaltheaSession) (time.Time, error) {
89+
func getLastRequestTime(cr *amaltheadevv1alpha1.AmaltheaSession) (time.Time, error) {
8690
url := fmt.Sprintf("http://%s:%d/request_stats", cr.Service().Name, amaltheadevv1alpha1.AuthProxyMetaPort)
8791

8892
resp, err := http.Get(url)
@@ -107,6 +111,14 @@ func lastRequestTime(cr *amaltheadevv1alpha1.AmaltheaSession) (time.Time, error)
107111
return req_stats.LastRequestTime, nil
108112
}
109113

114+
type IdleDecision int
115+
116+
// The values are setup in a way so that max(x, y, z) where x, y, z are
117+
// one of the values below will give the final decision.
118+
const Unknown IdleDecision = 0
119+
const Idle IdleDecision = 1
120+
const NotIdle IdleDecision = 2
121+
110122
func getIdleState(
111123
ctx context.Context,
112124
r *AmaltheaSessionReconciler,
@@ -117,41 +129,49 @@ func getIdleState(
117129
return metav1.Time{}, false
118130
}
119131
idleSince := cr.Status.IdleSince
120-
idle := false
121132

133+
cpuIdle := Unknown
134+
var cpuUsage *resource.Quantity
122135
metrics, err := metrics(ctx, r.MetricsClient, cr)
123136
if err != nil {
124-
log.Info("Metrics returned error", "error", err)
125-
return metav1.Time{}, false
137+
log.Info("Metrics returned error when checking idleness", "error", err)
138+
} else {
139+
cpuUsage = metrics.Cpu()
126140
}
127-
128-
cpuUsage := metrics.Cpu()
129-
if cpuUsage != nil && cpuUsage.Cmp(cpuUsageIdlenessThreshold) == -1 {
130-
if cr.Status.IdleSince.IsZero() {
131-
log.Info(
132-
"the session was found to be idle",
133-
"cpu usage milicores",
134-
cpuUsage.MilliValue(),
135-
"idle threshold milicores",
136-
cpuUsageIdlenessThreshold.MilliValue(),
137-
)
141+
if cpuUsage != nil {
142+
if cpuUsage.Cmp(cpuUsageIdlenessThreshold) == -1 {
143+
cpuIdle = Idle
144+
} else {
145+
cpuIdle = NotIdle
138146
}
139-
idle = true
140-
// check last request time before setting session to idle
141-
rt, err := lastRequestTime(cr)
142-
if err == nil && (idleSince.IsZero() || idleSince.Time.Before(rt)) {
143-
log.Info("the last request to the session happened after the session became idle, skipping marking as idle")
144-
idleSince = metav1.NewTime(rt)
145-
} else if err != nil {
146-
// note, if there was an error getting the time, we continue as normal
147-
log.Info("Couldn't get last request time from proxy", "err", err)
147+
}
148+
149+
requestIdle := Unknown
150+
lastRequesTime, err := getLastRequestTime(cr)
151+
if err != nil {
152+
log.Info("Request time check returned an error when checking idleness", "error", err)
153+
} else {
154+
if time.Since(lastRequesTime) >= lastRequestAgeThreshold {
155+
requestIdle = Idle
156+
} else {
157+
requestIdle = NotIdle
148158
}
149159
}
150160

161+
idle := false
162+
// If the decision is Unknown or there is at least 1 NotIdle then we keep the final status not idle.
163+
// If there is 2 Idle or an Unknown and an Idle then the status is Idle.
164+
decision := max(cpuIdle, requestIdle)
165+
if decision == Idle {
166+
idle = true
167+
}
151168
if idle && idleSince.IsZero() {
152169
idleSince = metav1.NewTime(time.Now())
153170
} else if !idle && !idleSince.IsZero() {
154171
idleSince = metav1.Time{}
155172
}
173+
174+
log.Info("session idle check", "idle", idle, "session", cr.Name, "cpuUsage", cpuUsage, "cpuUsageThreshold", cpuUsageIdlenessThreshold, "lastRequestTime", lastRequesTime, "lastRequestAgeThreshold", lastRequestAgeThreshold)
175+
156176
return idleSince, idle
157177
}

0 commit comments

Comments
 (0)