Skip to content

Commit 9470fb8

Browse files
authored
Filter subscriber reconciler events (#18660)
* Filter subscriber reconciler events * Notify changes in the port visibility * Switch to reflect.DeepEquals * Address feedback
1 parent 6408031 commit 9470fb8

File tree

2 files changed

+44
-1
lines changed

2 files changed

+44
-1
lines changed

components/ws-manager-api/go/crd/v1/workspace_types.go

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -150,6 +150,22 @@ type PortSpec struct {
150150
Protocol PortProtocol `json:"protocol"`
151151
}
152152

153+
func (ps PortSpec) Equal(other PortSpec) bool {
154+
if ps.Port != other.Port {
155+
return false
156+
}
157+
158+
if ps.Visibility != other.Visibility {
159+
return false
160+
}
161+
162+
if ps.Protocol != other.Protocol {
163+
return false
164+
}
165+
166+
return true
167+
}
168+
153169
// WorkspaceStatus defines the observed state of Workspace
154170
type WorkspaceStatus struct {
155171
PodStarts int `json:"podStarts"`

components/ws-manager-mk2/controllers/subscriber_controller.go

Lines changed: 28 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,18 +7,22 @@ package controllers
77
import (
88
"context"
99
"os"
10+
"reflect"
1011

1112
"k8s.io/apimachinery/pkg/api/errors"
1213
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
1314
ctrl "sigs.k8s.io/controller-runtime"
1415
"sigs.k8s.io/controller-runtime/pkg/client"
1516
"sigs.k8s.io/controller-runtime/pkg/controller"
17+
"sigs.k8s.io/controller-runtime/pkg/event"
1618
"sigs.k8s.io/controller-runtime/pkg/handler"
1719
"sigs.k8s.io/controller-runtime/pkg/log"
20+
"sigs.k8s.io/controller-runtime/pkg/predicate"
1821
"sigs.k8s.io/controller-runtime/pkg/source"
1922

2023
config "github.com/gitpod-io/gitpod/ws-manager/api/config"
2124
workspacev1 "github.com/gitpod-io/gitpod/ws-manager/api/crd/v1"
25+
"github.com/google/go-cmp/cmp"
2226
)
2327

2428
func NewSubscriberReconciler(c client.Client, cfg *config.Configuration) (*SubscriberReconciler, error) {
@@ -76,5 +80,28 @@ func (r *SubscriberReconciler) SetupWithManager(ctx context.Context, mgr ctrl.Ma
7680
}
7781
}()
7882

79-
return c.Watch(source.Kind(mgr.GetCache(), &workspacev1.Workspace{}), &handler.EnqueueRequestForObject{})
83+
// we need several reconciliation loops during a workspace creation until it reaches a stable state.
84+
// this introduces the side effect of multiple notifications to the subscribers with partial information.
85+
// the filterByUpdate predicate acts as a filter to avoid this
86+
filterByUpdate := predicate.Funcs{
87+
CreateFunc: func(ce event.CreateEvent) bool {
88+
return true
89+
},
90+
UpdateFunc: func(e event.UpdateEvent) bool {
91+
old := e.ObjectOld.(*workspacev1.Workspace)
92+
new := e.ObjectNew.(*workspacev1.Workspace)
93+
94+
if !cmp.Equal(old.Spec.Ports, new.Spec.Ports) {
95+
return true
96+
}
97+
98+
// do not notify LastActivity changes
99+
old.Status.LastActivity = nil
100+
new.Status.LastActivity = nil
101+
102+
return !reflect.DeepEqual(old.Status, new.Status)
103+
},
104+
}
105+
106+
return c.Watch(source.Kind(mgr.GetCache(), &workspacev1.Workspace{}), &handler.EnqueueRequestForObject{}, filterByUpdate)
80107
}

0 commit comments

Comments
 (0)