knative.dev/pkg@v0.0.0-20260602142205-ac97e43f6622/reconciler/leader.go (about) 1 /* 2 Copyright 2020 The Knative Authors 3 4 Licensed under the Apache License, Version 2.0 (the "License"); 5 you may not use this file except in compliance with the License. 6 You may obtain a copy of the License at 7 8 http://www.apache.org/licenses/LICENSE-2.0 9 10 Unless required by applicable law or agreed to in writing, software 11 distributed under the License is distributed on an "AS IS" BASIS, 12 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 See the License for the specific language governing permissions and 14 limitations under the License. 15 */ 16 17 package reconciler 18 19 import ( 20 "sync" 21 22 "k8s.io/apimachinery/pkg/types" 23 ) 24 25 // Bucket is an opaque type used to scope leadership. 26 type Bucket interface { 27 // Name returns a string representing this bucket, which uniquely 28 // identifies the bucket and is suitable for use as a resource lock name. 29 Name() string 30 31 // Has determines whether this Bucket contains a particular key. 32 Has(key types.NamespacedName) bool 33 } 34 35 // UniversalBucket returns a Bucket that "Has()" all keys. 36 func UniversalBucket() Bucket { 37 return &bucket{} 38 } 39 40 type bucket struct{} 41 42 var _ Bucket = (*bucket)(nil) 43 44 // Name implements Bucket 45 func (b *bucket) Name() string { 46 return "" 47 } 48 49 // Has implements Bucket 50 func (b *bucket) Has(nn types.NamespacedName) bool { 51 return true 52 } 53 54 // LeaderAware is implemented by Reconcilers that are aware of their leader status. 55 type LeaderAware interface { 56 // Promote is called when we become the leader of a given Bucket. It must be 57 // supplied with an enqueue function through which a Bucket resync may be triggered. 58 Promote(b Bucket, enq func(Bucket, types.NamespacedName)) error 59 60 // Demote is called when we stop being the leader for the specified Bucket. 61 Demote(Bucket) 62 } 63 64 // LeaderAwareFuncs implements LeaderAware using the given functions for handling 65 // promotion and demotion. 66 type LeaderAwareFuncs struct { 67 sync.RWMutex 68 buckets map[string]Bucket 69 70 PromoteFunc func(b Bucket, enq func(Bucket, types.NamespacedName)) error 71 DemoteFunc func(b Bucket) 72 } 73 74 var _ LeaderAware = (*LeaderAwareFuncs)(nil) 75 76 // IsLeaderFor implements LeaderAware 77 func (laf *LeaderAwareFuncs) IsLeaderFor(key types.NamespacedName) bool { 78 laf.RLock() 79 defer laf.RUnlock() 80 81 for _, bkt := range laf.buckets { 82 if bkt.Has(key) { 83 return true 84 } 85 } 86 return false 87 } 88 89 // Promote implements LeaderAware 90 func (laf *LeaderAwareFuncs) Promote(b Bucket, enq func(Bucket, types.NamespacedName)) error { 91 func() { 92 laf.Lock() 93 defer laf.Unlock() 94 if laf.buckets == nil { 95 laf.buckets = make(map[string]Bucket, 1) 96 } 97 laf.buckets[b.Name()] = b 98 }() 99 100 if promote := laf.PromoteFunc; promote != nil && enq != nil { 101 return promote(b, enq) 102 } 103 return nil 104 } 105 106 // Demote implements LeaderAware 107 func (laf *LeaderAwareFuncs) Demote(b Bucket) { 108 func() { 109 laf.Lock() 110 defer laf.Unlock() 111 delete(laf.buckets, b.Name()) 112 }() 113 114 if demote := laf.DemoteFunc; demote != nil { 115 demote(b) 116 } 117 }