github.com/lingyao2333/mo-zero@v1.4.1/zrpc/resolver/internal/kube/eventhandler.go (about)

     1  package kube
     2  
     3  import (
     4  	"sync"
     5  
     6  	"github.com/lingyao2333/mo-zero/core/lang"
     7  	"github.com/lingyao2333/mo-zero/core/logx"
     8  	v1 "k8s.io/api/core/v1"
     9  )
    10  
    11  // EventHandler is ResourceEventHandler implementation.
    12  type EventHandler struct {
    13  	update    func([]string)
    14  	endpoints map[string]lang.PlaceholderType
    15  	lock      sync.Mutex
    16  }
    17  
    18  // NewEventHandler returns an EventHandler.
    19  func NewEventHandler(update func([]string)) *EventHandler {
    20  	return &EventHandler{
    21  		update:    update,
    22  		endpoints: make(map[string]lang.PlaceholderType),
    23  	}
    24  }
    25  
    26  // OnAdd handles the endpoints add events.
    27  func (h *EventHandler) OnAdd(obj interface{}) {
    28  	endpoints, ok := obj.(*v1.Endpoints)
    29  	if !ok {
    30  		logx.Errorf("%v is not an object with type *v1.Endpoints", obj)
    31  		return
    32  	}
    33  
    34  	h.lock.Lock()
    35  	defer h.lock.Unlock()
    36  
    37  	var changed bool
    38  	for _, sub := range endpoints.Subsets {
    39  		for _, point := range sub.Addresses {
    40  			if _, ok := h.endpoints[point.IP]; !ok {
    41  				h.endpoints[point.IP] = lang.Placeholder
    42  				changed = true
    43  			}
    44  		}
    45  	}
    46  
    47  	if changed {
    48  		h.notify()
    49  	}
    50  }
    51  
    52  // OnDelete handles the endpoints delete events.
    53  func (h *EventHandler) OnDelete(obj interface{}) {
    54  	endpoints, ok := obj.(*v1.Endpoints)
    55  	if !ok {
    56  		logx.Errorf("%v is not an object with type *v1.Endpoints", obj)
    57  		return
    58  	}
    59  
    60  	h.lock.Lock()
    61  	defer h.lock.Unlock()
    62  
    63  	var changed bool
    64  	for _, sub := range endpoints.Subsets {
    65  		for _, point := range sub.Addresses {
    66  			if _, ok := h.endpoints[point.IP]; ok {
    67  				delete(h.endpoints, point.IP)
    68  				changed = true
    69  			}
    70  		}
    71  	}
    72  
    73  	if changed {
    74  		h.notify()
    75  	}
    76  }
    77  
    78  // OnUpdate handles the endpoints update events.
    79  func (h *EventHandler) OnUpdate(oldObj, newObj interface{}) {
    80  	oldEndpoints, ok := oldObj.(*v1.Endpoints)
    81  	if !ok {
    82  		logx.Errorf("%v is not an object with type *v1.Endpoints", oldObj)
    83  		return
    84  	}
    85  
    86  	newEndpoints, ok := newObj.(*v1.Endpoints)
    87  	if !ok {
    88  		logx.Errorf("%v is not an object with type *v1.Endpoints", newObj)
    89  		return
    90  	}
    91  
    92  	if oldEndpoints.ResourceVersion == newEndpoints.ResourceVersion {
    93  		return
    94  	}
    95  
    96  	h.Update(newEndpoints)
    97  }
    98  
    99  // Update updates the endpoints.
   100  func (h *EventHandler) Update(endpoints *v1.Endpoints) {
   101  	h.lock.Lock()
   102  	defer h.lock.Unlock()
   103  
   104  	old := h.endpoints
   105  	h.endpoints = make(map[string]lang.PlaceholderType)
   106  	for _, sub := range endpoints.Subsets {
   107  		for _, point := range sub.Addresses {
   108  			h.endpoints[point.IP] = lang.Placeholder
   109  		}
   110  	}
   111  
   112  	if diff(old, h.endpoints) {
   113  		h.notify()
   114  	}
   115  }
   116  
   117  func (h *EventHandler) notify() {
   118  	targets := make([]string, 0, len(h.endpoints))
   119  
   120  	for k := range h.endpoints {
   121  		targets = append(targets, k)
   122  	}
   123  
   124  	h.update(targets)
   125  }
   126  
   127  func diff(o, n map[string]lang.PlaceholderType) bool {
   128  	if len(o) != len(n) {
   129  		return true
   130  	}
   131  
   132  	for k := range o {
   133  		if _, ok := n[k]; !ok {
   134  			return true
   135  		}
   136  	}
   137  
   138  	return false
   139  }