From cb3c05429e3f5dc3c0c82901ecd2b7c97c94f72e Mon Sep 17 00:00:00 2001 From: Noah Kantrowitz Date: Sun, 21 Feb 2021 15:22:42 -0800 Subject: [PATCH 1/4] =?UTF-8?q?=E2=9C=A8=20Deduplicate=20events=20before?= =?UTF-8?q?=20sending=20them=20into=20the=20workqueue.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This avoids race conditions where extra reconciles can happen rarely. --- pkg/handler/enqueue.go | 16 ++-- pkg/handler/enqueue_mapped.go | 4 + pkg/handler/enqueue_owner.go | 32 ++++--- pkg/handler/eventhandler_test.go | 151 +++++++++++++++++++------------ 4 files changed, 120 insertions(+), 83 deletions(-) diff --git a/pkg/handler/enqueue.go b/pkg/handler/enqueue.go index 9f72302d1c..50b7d2478c 100644 --- a/pkg/handler/enqueue.go +++ b/pkg/handler/enqueue.go @@ -47,22 +47,18 @@ func (e *EnqueueRequestForObject) Create(evt event.CreateEvent, q workqueue.Rate // Update implements EventHandler func (e *EnqueueRequestForObject) Update(evt event.UpdateEvent, q workqueue.RateLimitingInterface) { - if evt.ObjectOld != nil { - q.Add(reconcile.Request{NamespacedName: types.NamespacedName{ - Name: evt.ObjectOld.GetName(), - Namespace: evt.ObjectOld.GetNamespace(), - }}) - } else { - enqueueLog.Error(nil, "UpdateEvent received with no old metadata", "event", evt) - } - if evt.ObjectNew != nil { q.Add(reconcile.Request{NamespacedName: types.NamespacedName{ Name: evt.ObjectNew.GetName(), Namespace: evt.ObjectNew.GetNamespace(), }}) + } else if evt.ObjectOld != nil { + q.Add(reconcile.Request{NamespacedName: types.NamespacedName{ + Name: evt.ObjectOld.GetName(), + Namespace: evt.ObjectOld.GetNamespace(), + }}) } else { - enqueueLog.Error(nil, "UpdateEvent received with no new metadata", "event", evt) + enqueueLog.Error(nil, "UpdateEvent received with no metadata", "event", evt) } } diff --git a/pkg/handler/enqueue_mapped.go b/pkg/handler/enqueue_mapped.go index f98ec25638..d5ec46e883 100644 --- a/pkg/handler/enqueue_mapped.go +++ b/pkg/handler/enqueue_mapped.go @@ -73,7 +73,11 @@ func (e *enqueueRequestsFromMapFunc) Generic(evt event.GenericEvent, q workqueue } func (e *enqueueRequestsFromMapFunc) mapAndEnqueue(q workqueue.RateLimitingInterface, object client.Object) { + reqs := map[reconcile.Request]bool{} for _, req := range e.toRequests(object) { + reqs[req] = true + } + for req := range reqs { q.Add(req) } } diff --git a/pkg/handler/enqueue_owner.go b/pkg/handler/enqueue_owner.go index 925b9e3c2d..629ce1d323 100644 --- a/pkg/handler/enqueue_owner.go +++ b/pkg/handler/enqueue_owner.go @@ -59,31 +59,37 @@ type EnqueueRequestForOwner struct { // Create implements EventHandler func (e *EnqueueRequestForOwner) Create(evt event.CreateEvent, q workqueue.RateLimitingInterface) { - for _, req := range e.getOwnerReconcileRequest(evt.Object) { + reqs := map[reconcile.Request]bool{} + e.getOwnerReconcileRequest(evt.Object, reqs) + for req := range reqs { q.Add(req) } } // Update implements EventHandler func (e *EnqueueRequestForOwner) Update(evt event.UpdateEvent, q workqueue.RateLimitingInterface) { - for _, req := range e.getOwnerReconcileRequest(evt.ObjectOld) { - q.Add(req) - } - for _, req := range e.getOwnerReconcileRequest(evt.ObjectNew) { + reqs := map[reconcile.Request]bool{} + e.getOwnerReconcileRequest(evt.ObjectOld, reqs) + e.getOwnerReconcileRequest(evt.ObjectNew, reqs) + for req := range reqs { q.Add(req) } } // Delete implements EventHandler func (e *EnqueueRequestForOwner) Delete(evt event.DeleteEvent, q workqueue.RateLimitingInterface) { - for _, req := range e.getOwnerReconcileRequest(evt.Object) { + reqs := map[reconcile.Request]bool{} + e.getOwnerReconcileRequest(evt.Object, reqs) + for req := range reqs { q.Add(req) } } // Generic implements EventHandler func (e *EnqueueRequestForOwner) Generic(evt event.GenericEvent, q workqueue.RateLimitingInterface) { - for _, req := range e.getOwnerReconcileRequest(evt.Object) { + reqs := map[reconcile.Request]bool{} + e.getOwnerReconcileRequest(evt.Object, reqs) + for req := range reqs { q.Add(req) } } @@ -111,17 +117,16 @@ func (e *EnqueueRequestForOwner) parseOwnerTypeGroupKind(scheme *runtime.Scheme) // getOwnerReconcileRequest looks at object and returns a slice of reconcile.Request to reconcile // owners of object that match e.OwnerType. -func (e *EnqueueRequestForOwner) getOwnerReconcileRequest(object metav1.Object) []reconcile.Request { +func (e *EnqueueRequestForOwner) getOwnerReconcileRequest(object metav1.Object, result map[reconcile.Request]bool) { // Iterate through the OwnerReferences looking for a match on Group and Kind against what was requested // by the user - var result []reconcile.Request for _, ref := range e.getOwnersReferences(object) { // Parse the Group out of the OwnerReference to compare it to what was parsed out of the requested OwnerType refGV, err := schema.ParseGroupVersion(ref.APIVersion) if err != nil { log.Error(err, "Could not parse OwnerReference APIVersion", "api version", ref.APIVersion) - return nil + return } // Compare the OwnerReference Group and Kind against the OwnerType Group and Kind specified by the user. @@ -138,18 +143,15 @@ func (e *EnqueueRequestForOwner) getOwnerReconcileRequest(object metav1.Object) mapping, err := e.mapper.RESTMapping(e.groupKind, refGV.Version) if err != nil { log.Error(err, "Could not retrieve rest mapping", "kind", e.groupKind) - return nil + return } if mapping.Scope.Name() != meta.RESTScopeNameRoot { request.Namespace = object.GetNamespace() } - result = append(result, request) + result[request] = true } } - - // Return the matches - return result } // getOwnersReferences returns the OwnerReferences for an object as specified by the EnqueueRequestForOwner diff --git a/pkg/handler/eventhandler_test.go b/pkg/handler/eventhandler_test.go index e42d86d63d..6886e6257a 100644 --- a/pkg/handler/eventhandler_test.go +++ b/pkg/handler/eventhandler_test.go @@ -86,7 +86,7 @@ var _ = Describe("Eventhandler", func() { close(done) }) - It("should enqueue a Request with the Name / Namespace of both objects in the UpdateEvent.", + It("should enqueue a Request with the Name / Namespace of one object in the UpdateEvent.", func(done Done) { newPod := pod.DeepCopy() newPod.Name = "baz2" @@ -97,18 +97,12 @@ var _ = Describe("Eventhandler", func() { ObjectNew: newPod, } instance.Update(evt, q) - Expect(q.Len()).To(Equal(2)) + Expect(q.Len()).To(Equal(1)) i, _ := q.Get() Expect(i).NotTo(BeNil()) req, ok := i.(reconcile.Request) Expect(ok).To(BeTrue()) - Expect(req.NamespacedName).To(Equal(types.NamespacedName{Namespace: "biz", Name: "baz"})) - - i, _ = q.Get() - Expect(i).NotTo(BeNil()) - req, ok = i.(reconcile.Request) - Expect(ok).To(BeTrue()) Expect(req.NamespacedName).To(Equal(types.NamespacedName{Namespace: "biz2", Name: "baz2"})) close(done) @@ -212,13 +206,14 @@ var _ = Describe("Eventhandler", func() { instance.Create(evt, q) Expect(q.Len()).To(Equal(2)) - i, _ := q.Get() - Expect(i).To(Equal(reconcile.Request{ - NamespacedName: types.NamespacedName{Namespace: "foo", Name: "bar"}})) - - i, _ = q.Get() - Expect(i).To(Equal(reconcile.Request{ - NamespacedName: types.NamespacedName{Namespace: "biz", Name: "baz"}})) + i1, _ := q.Get() + i2, _ := q.Get() + Expect([]interface{}{i1, i2}).To(ConsistOf( + reconcile.Request{ + NamespacedName: types.NamespacedName{Namespace: "foo", Name: "bar"}}, + reconcile.Request{ + NamespacedName: types.NamespacedName{Namespace: "biz", Name: "baz"}}, + )) }) It("should enqueue a Request with the function applied to the DeleteEvent.", func() { @@ -243,13 +238,14 @@ var _ = Describe("Eventhandler", func() { instance.Delete(evt, q) Expect(q.Len()).To(Equal(2)) - i, _ := q.Get() - Expect(i).To(Equal(reconcile.Request{ - NamespacedName: types.NamespacedName{Namespace: "foo", Name: "bar"}})) - - i, _ = q.Get() - Expect(i).To(Equal(reconcile.Request{ - NamespacedName: types.NamespacedName{Namespace: "biz", Name: "baz"}})) + i1, _ := q.Get() + i2, _ := q.Get() + Expect([]interface{}{i1, i2}).To(ConsistOf( + reconcile.Request{ + NamespacedName: types.NamespacedName{Namespace: "foo", Name: "bar"}}, + reconcile.Request{ + NamespacedName: types.NamespacedName{Namespace: "biz", Name: "baz"}}, + )) }) It("should enqueue a Request with the function applied to both objects in the UpdateEvent.", @@ -280,21 +276,20 @@ var _ = Describe("Eventhandler", func() { instance.Update(evt, q) Expect(q.Len()).To(Equal(4)) - i, _ := q.Get() - Expect(i).To(Equal(reconcile.Request{ - NamespacedName: types.NamespacedName{Namespace: "foo", Name: "baz-bar"}})) - - i, _ = q.Get() - Expect(i).To(Equal(reconcile.Request{ - NamespacedName: types.NamespacedName{Namespace: "biz", Name: "baz-baz"}})) - - i, _ = q.Get() - Expect(i).To(Equal(reconcile.Request{ - NamespacedName: types.NamespacedName{Namespace: "foo", Name: "baz2-bar"}})) - - i, _ = q.Get() - Expect(i).To(Equal(reconcile.Request{ - NamespacedName: types.NamespacedName{Namespace: "biz", Name: "baz2-baz"}})) + i1, _ := q.Get() + i2, _ := q.Get() + i3, _ := q.Get() + i4, _ := q.Get() + Expect([]interface{}{i1, i2, i3, i4}).To(ConsistOf( + reconcile.Request{ + NamespacedName: types.NamespacedName{Namespace: "foo", Name: "baz-bar"}}, + reconcile.Request{ + NamespacedName: types.NamespacedName{Namespace: "biz", Name: "baz-baz"}}, + reconcile.Request{ + NamespacedName: types.NamespacedName{Namespace: "foo", Name: "baz2-bar"}}, + reconcile.Request{ + NamespacedName: types.NamespacedName{Namespace: "biz", Name: "baz2-baz"}}, + )) }) It("should enqueue a Request with the function applied to the GenericEvent.", func() { @@ -319,13 +314,14 @@ var _ = Describe("Eventhandler", func() { instance.Generic(evt, q) Expect(q.Len()).To(Equal(2)) - i, _ := q.Get() - Expect(i).To(Equal(reconcile.Request{ - NamespacedName: types.NamespacedName{Namespace: "foo", Name: "bar"}})) - - i, _ = q.Get() - Expect(i).To(Equal(reconcile.Request{ - NamespacedName: types.NamespacedName{Namespace: "biz", Name: "baz"}})) + i1, _ := q.Get() + i2, _ := q.Get() + Expect([]interface{}{i1, i2}).To(ConsistOf( + reconcile.Request{ + NamespacedName: types.NamespacedName{Namespace: "foo", Name: "bar"}}, + reconcile.Request{ + NamespacedName: types.NamespacedName{Namespace: "biz", Name: "baz"}}, + )) }) }) @@ -412,13 +408,50 @@ var _ = Describe("Eventhandler", func() { instance.Update(evt, q) Expect(q.Len()).To(Equal(2)) - i, _ := q.Get() - Expect(i).To(Equal(reconcile.Request{ - NamespacedName: types.NamespacedName{Namespace: pod.GetNamespace(), Name: "foo1-parent"}})) + i1, _ := q.Get() + i2, _ := q.Get() + Expect([]interface{}{i1, i2}).To(ConsistOf( + reconcile.Request{ + NamespacedName: types.NamespacedName{Namespace: pod.GetNamespace(), Name: "foo1-parent"}}, + reconcile.Request{ + NamespacedName: types.NamespacedName{Namespace: newPod.GetNamespace(), Name: "foo2-parent"}}, + )) + }) + + It("should enqueue a Request with the one duplicate Owner of both objects in the UpdateEvent.", func() { + newPod := pod.DeepCopy() + newPod.Name = pod.Name + "2" - i, _ = q.Get() + instance := handler.EnqueueRequestForOwner{ + OwnerType: &appsv1.ReplicaSet{}, + } + Expect(instance.InjectScheme(scheme.Scheme)).To(Succeed()) + Expect(instance.InjectMapper(mapper)).To(Succeed()) + + pod.OwnerReferences = []metav1.OwnerReference{ + { + Name: "foo-parent", + Kind: "ReplicaSet", + APIVersion: "apps/v1", + }, + } + newPod.OwnerReferences = []metav1.OwnerReference{ + { + Name: "foo-parent", + Kind: "ReplicaSet", + APIVersion: "apps/v1", + }, + } + evt := event.UpdateEvent{ + ObjectOld: pod, + ObjectNew: newPod, + } + instance.Update(evt, q) + Expect(q.Len()).To(Equal(1)) + + i, _ := q.Get() Expect(i).To(Equal(reconcile.Request{ - NamespacedName: types.NamespacedName{Namespace: newPod.GetNamespace(), Name: "foo2-parent"}})) + NamespacedName: types.NamespacedName{Namespace: pod.GetNamespace(), Name: "foo-parent"}})) }) It("should enqueue a Request with the Owner of the object in the GenericEvent.", func() { @@ -659,15 +692,17 @@ var _ = Describe("Eventhandler", func() { instance.Create(evt, q) Expect(q.Len()).To(Equal(3)) - i, _ := q.Get() - Expect(i).To(Equal(reconcile.Request{ - NamespacedName: types.NamespacedName{Namespace: pod.GetNamespace(), Name: "foo1-parent"}})) - i, _ = q.Get() - Expect(i).To(Equal(reconcile.Request{ - NamespacedName: types.NamespacedName{Namespace: pod.GetNamespace(), Name: "foo2-parent"}})) - i, _ = q.Get() - Expect(i).To(Equal(reconcile.Request{ - NamespacedName: types.NamespacedName{Namespace: pod.GetNamespace(), Name: "foo3-parent"}})) + i1, _ := q.Get() + i2, _ := q.Get() + i3, _ := q.Get() + Expect([]interface{}{i1, i2, i3}).To(ConsistOf( + reconcile.Request{ + NamespacedName: types.NamespacedName{Namespace: pod.GetNamespace(), Name: "foo1-parent"}}, + reconcile.Request{ + NamespacedName: types.NamespacedName{Namespace: pod.GetNamespace(), Name: "foo2-parent"}}, + reconcile.Request{ + NamespacedName: types.NamespacedName{Namespace: pod.GetNamespace(), Name: "foo3-parent"}}, + )) }) }) From 341be592b1be319ff082043b0f2b60411784512d Mon Sep 17 00:00:00 2001 From: Noah Kantrowitz Date: Sat, 27 Feb 2021 15:29:55 -0800 Subject: [PATCH 2/4] =?UTF-8?q?=E2=9C=A8=20Switch=20to=20map[string]struct?= =?UTF-8?q?{}=20to=20reduce=20memory=20usage=20slightly.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Also make sure that enqueue_mapped preserves order. --- pkg/handler/enqueue.go | 2 ++ pkg/handler/enqueue_mapped.go | 11 ++++++----- pkg/handler/enqueue_owner.go | 12 ++++++------ pkg/handler/eventhandler_test.go | 25 +++++++++++-------------- 4 files changed, 25 insertions(+), 25 deletions(-) diff --git a/pkg/handler/enqueue.go b/pkg/handler/enqueue.go index 50b7d2478c..fb8987cfe9 100644 --- a/pkg/handler/enqueue.go +++ b/pkg/handler/enqueue.go @@ -26,6 +26,8 @@ import ( var enqueueLog = logf.RuntimeLog.WithName("eventhandler").WithName("EnqueueRequestForObject") +type empty struct{} + var _ EventHandler = &EnqueueRequestForObject{} // EnqueueRequestForObject enqueues a Request containing the Name and Namespace of the object that is the source of the Event. diff --git a/pkg/handler/enqueue_mapped.go b/pkg/handler/enqueue_mapped.go index d5ec46e883..1a8229e4e8 100644 --- a/pkg/handler/enqueue_mapped.go +++ b/pkg/handler/enqueue_mapped.go @@ -73,12 +73,13 @@ func (e *enqueueRequestsFromMapFunc) Generic(evt event.GenericEvent, q workqueue } func (e *enqueueRequestsFromMapFunc) mapAndEnqueue(q workqueue.RateLimitingInterface, object client.Object) { - reqs := map[reconcile.Request]bool{} + reqs := map[reconcile.Request]empty{} for _, req := range e.toRequests(object) { - reqs[req] = true - } - for req := range reqs { - q.Add(req) + _, ok := reqs[req] + if !ok { + q.Add(req) + reqs[req] = empty{} + } } } diff --git a/pkg/handler/enqueue_owner.go b/pkg/handler/enqueue_owner.go index 629ce1d323..830a10ba4b 100644 --- a/pkg/handler/enqueue_owner.go +++ b/pkg/handler/enqueue_owner.go @@ -59,7 +59,7 @@ type EnqueueRequestForOwner struct { // Create implements EventHandler func (e *EnqueueRequestForOwner) Create(evt event.CreateEvent, q workqueue.RateLimitingInterface) { - reqs := map[reconcile.Request]bool{} + reqs := map[reconcile.Request]empty{} e.getOwnerReconcileRequest(evt.Object, reqs) for req := range reqs { q.Add(req) @@ -68,7 +68,7 @@ func (e *EnqueueRequestForOwner) Create(evt event.CreateEvent, q workqueue.RateL // Update implements EventHandler func (e *EnqueueRequestForOwner) Update(evt event.UpdateEvent, q workqueue.RateLimitingInterface) { - reqs := map[reconcile.Request]bool{} + reqs := map[reconcile.Request]empty{} e.getOwnerReconcileRequest(evt.ObjectOld, reqs) e.getOwnerReconcileRequest(evt.ObjectNew, reqs) for req := range reqs { @@ -78,7 +78,7 @@ func (e *EnqueueRequestForOwner) Update(evt event.UpdateEvent, q workqueue.RateL // Delete implements EventHandler func (e *EnqueueRequestForOwner) Delete(evt event.DeleteEvent, q workqueue.RateLimitingInterface) { - reqs := map[reconcile.Request]bool{} + reqs := map[reconcile.Request]empty{} e.getOwnerReconcileRequest(evt.Object, reqs) for req := range reqs { q.Add(req) @@ -87,7 +87,7 @@ func (e *EnqueueRequestForOwner) Delete(evt event.DeleteEvent, q workqueue.RateL // Generic implements EventHandler func (e *EnqueueRequestForOwner) Generic(evt event.GenericEvent, q workqueue.RateLimitingInterface) { - reqs := map[reconcile.Request]bool{} + reqs := map[reconcile.Request]empty{} e.getOwnerReconcileRequest(evt.Object, reqs) for req := range reqs { q.Add(req) @@ -117,7 +117,7 @@ func (e *EnqueueRequestForOwner) parseOwnerTypeGroupKind(scheme *runtime.Scheme) // getOwnerReconcileRequest looks at object and returns a slice of reconcile.Request to reconcile // owners of object that match e.OwnerType. -func (e *EnqueueRequestForOwner) getOwnerReconcileRequest(object metav1.Object, result map[reconcile.Request]bool) { +func (e *EnqueueRequestForOwner) getOwnerReconcileRequest(object metav1.Object, result map[reconcile.Request]empty) { // Iterate through the OwnerReferences looking for a match on Group and Kind against what was requested // by the user for _, ref := range e.getOwnersReferences(object) { @@ -149,7 +149,7 @@ func (e *EnqueueRequestForOwner) getOwnerReconcileRequest(object metav1.Object, request.Namespace = object.GetNamespace() } - result[request] = true + result[request] = empty{} } } } diff --git a/pkg/handler/eventhandler_test.go b/pkg/handler/eventhandler_test.go index 6886e6257a..55ca7954e9 100644 --- a/pkg/handler/eventhandler_test.go +++ b/pkg/handler/eventhandler_test.go @@ -276,20 +276,17 @@ var _ = Describe("Eventhandler", func() { instance.Update(evt, q) Expect(q.Len()).To(Equal(4)) - i1, _ := q.Get() - i2, _ := q.Get() - i3, _ := q.Get() - i4, _ := q.Get() - Expect([]interface{}{i1, i2, i3, i4}).To(ConsistOf( - reconcile.Request{ - NamespacedName: types.NamespacedName{Namespace: "foo", Name: "baz-bar"}}, - reconcile.Request{ - NamespacedName: types.NamespacedName{Namespace: "biz", Name: "baz-baz"}}, - reconcile.Request{ - NamespacedName: types.NamespacedName{Namespace: "foo", Name: "baz2-bar"}}, - reconcile.Request{ - NamespacedName: types.NamespacedName{Namespace: "biz", Name: "baz2-baz"}}, - )) + i, _ := q.Get() + Expect(i).To(Equal(reconcile.Request{NamespacedName: types.NamespacedName{Namespace: "foo", Name: "baz-bar"}})) + + i, _ = q.Get() + Expect(i).To(Equal(reconcile.Request{NamespacedName: types.NamespacedName{Namespace: "biz", Name: "baz-baz"}})) + + i, _ = q.Get() + Expect(i).To(Equal(reconcile.Request{NamespacedName: types.NamespacedName{Namespace: "foo", Name: "baz2-bar"}})) + + i, _ = q.Get() + Expect(i).To(Equal(reconcile.Request{NamespacedName: types.NamespacedName{Namespace: "biz", Name: "baz2-baz"}})) }) It("should enqueue a Request with the function applied to the GenericEvent.", func() { From 337285adad6dffefdab4cb7b40631011da9d4224 Mon Sep 17 00:00:00 2001 From: Noah Kantrowitz Date: Sun, 7 Mar 2021 15:55:15 -0800 Subject: [PATCH 3/4] =?UTF-8?q?=F0=9F=93=9D=20Update=20function=20doc=20fo?= =?UTF-8?q?r=20getOwnerReconcileRequest.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- pkg/handler/enqueue_owner.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pkg/handler/enqueue_owner.go b/pkg/handler/enqueue_owner.go index 830a10ba4b..8aa4ec52b2 100644 --- a/pkg/handler/enqueue_owner.go +++ b/pkg/handler/enqueue_owner.go @@ -115,7 +115,7 @@ func (e *EnqueueRequestForOwner) parseOwnerTypeGroupKind(scheme *runtime.Scheme) return nil } -// getOwnerReconcileRequest looks at object and returns a slice of reconcile.Request to reconcile +// getOwnerReconcileRequest looks at object and builds a map of reconcile.Request to reconcile // owners of object that match e.OwnerType. func (e *EnqueueRequestForOwner) getOwnerReconcileRequest(object metav1.Object, result map[reconcile.Request]empty) { // Iterate through the OwnerReferences looking for a match on Group and Kind against what was requested From 28f3a5d714fd887109355a464023fa2eb8dd0959 Mon Sep 17 00:00:00 2001 From: Noah Kantrowitz Date: Sun, 7 Mar 2021 15:57:18 -0800 Subject: [PATCH 4/4] =?UTF-8?q?=F0=9F=8E=A8=20Fix=20up=20duplication=20tes?= =?UTF-8?q?ts=20and=20ensure=20Update=20for=20=5Fmapped=20dedups=20between?= =?UTF-8?q?=20both=20objects.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- pkg/handler/enqueue_mapped.go | 17 ++++++++++------- pkg/handler/eventhandler_test.go | 10 +--------- 2 files changed, 11 insertions(+), 16 deletions(-) diff --git a/pkg/handler/enqueue_mapped.go b/pkg/handler/enqueue_mapped.go index 1a8229e4e8..585c21e718 100644 --- a/pkg/handler/enqueue_mapped.go +++ b/pkg/handler/enqueue_mapped.go @@ -53,27 +53,30 @@ type enqueueRequestsFromMapFunc struct { // Create implements EventHandler func (e *enqueueRequestsFromMapFunc) Create(evt event.CreateEvent, q workqueue.RateLimitingInterface) { - e.mapAndEnqueue(q, evt.Object) + reqs := map[reconcile.Request]empty{} + e.mapAndEnqueue(q, evt.Object, reqs) } // Update implements EventHandler func (e *enqueueRequestsFromMapFunc) Update(evt event.UpdateEvent, q workqueue.RateLimitingInterface) { - e.mapAndEnqueue(q, evt.ObjectOld) - e.mapAndEnqueue(q, evt.ObjectNew) + reqs := map[reconcile.Request]empty{} + e.mapAndEnqueue(q, evt.ObjectOld, reqs) + e.mapAndEnqueue(q, evt.ObjectNew, reqs) } // Delete implements EventHandler func (e *enqueueRequestsFromMapFunc) Delete(evt event.DeleteEvent, q workqueue.RateLimitingInterface) { - e.mapAndEnqueue(q, evt.Object) + reqs := map[reconcile.Request]empty{} + e.mapAndEnqueue(q, evt.Object, reqs) } // Generic implements EventHandler func (e *enqueueRequestsFromMapFunc) Generic(evt event.GenericEvent, q workqueue.RateLimitingInterface) { - e.mapAndEnqueue(q, evt.Object) + reqs := map[reconcile.Request]empty{} + e.mapAndEnqueue(q, evt.Object, reqs) } -func (e *enqueueRequestsFromMapFunc) mapAndEnqueue(q workqueue.RateLimitingInterface, object client.Object) { - reqs := map[reconcile.Request]empty{} +func (e *enqueueRequestsFromMapFunc) mapAndEnqueue(q workqueue.RateLimitingInterface, object client.Object, reqs map[reconcile.Request]empty) { for _, req := range e.toRequests(object) { _, ok := reqs[req] if !ok { diff --git a/pkg/handler/eventhandler_test.go b/pkg/handler/eventhandler_test.go index 55ca7954e9..7ba3b8aa84 100644 --- a/pkg/handler/eventhandler_test.go +++ b/pkg/handler/eventhandler_test.go @@ -251,8 +251,6 @@ var _ = Describe("Eventhandler", func() { It("should enqueue a Request with the function applied to both objects in the UpdateEvent.", func() { newPod := pod.DeepCopy() - newPod.Name = pod.Name + "2" - newPod.Namespace = pod.Namespace + "2" req := []reconcile.Request{} @@ -274,19 +272,13 @@ var _ = Describe("Eventhandler", func() { ObjectNew: newPod, } instance.Update(evt, q) - Expect(q.Len()).To(Equal(4)) + Expect(q.Len()).To(Equal(2)) i, _ := q.Get() Expect(i).To(Equal(reconcile.Request{NamespacedName: types.NamespacedName{Namespace: "foo", Name: "baz-bar"}})) i, _ = q.Get() Expect(i).To(Equal(reconcile.Request{NamespacedName: types.NamespacedName{Namespace: "biz", Name: "baz-baz"}})) - - i, _ = q.Get() - Expect(i).To(Equal(reconcile.Request{NamespacedName: types.NamespacedName{Namespace: "foo", Name: "baz2-bar"}})) - - i, _ = q.Get() - Expect(i).To(Equal(reconcile.Request{NamespacedName: types.NamespacedName{Namespace: "biz", Name: "baz2-baz"}})) }) It("should enqueue a Request with the function applied to the GenericEvent.", func() {