dubbo.apache.org/dubbo-go/v3@v3.1.1/registry/polaris/core.go (about)

     1  /*
     2   * Licensed to the Apache Software Foundation (ASF) under one or more
     3   * contributor license agreements.  See the NOTICE file distributed with
     4   * this work for additional information regarding copyright ownership.
     5   * The ASF licenses this file to You under the Apache License, Version 2.0
     6   * (the "License"); you may not use this file except in compliance with
     7   * the License.  You may obtain a copy of the License at
     8   *
     9   *     http://www.apache.org/licenses/LICENSE-2.0
    10   *
    11   * Unless required by applicable law or agreed to in writing, software
    12   * distributed under the License is distributed on an "AS IS" BASIS,
    13   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    14   * See the License for the specific language governing permissions and
    15   * limitations under the License.
    16   */
    17  
    18  package polaris
    19  
    20  import (
    21  	"sync"
    22  	"time"
    23  )
    24  
    25  import (
    26  	api "github.com/polarismesh/polaris-go"
    27  	internalapi "github.com/polarismesh/polaris-go/api"
    28  	"github.com/polarismesh/polaris-go/pkg/model"
    29  )
    30  
    31  import (
    32  	"dubbo.apache.org/dubbo-go/v3/config_center"
    33  	"dubbo.apache.org/dubbo-go/v3/remoting"
    34  )
    35  
    36  type item func(remoting.EventType, []model.Instance)
    37  
    38  type PolarisServiceWatcher struct {
    39  	consumer       api.ConsumerAPI
    40  	subscribeParam *api.WatchServiceRequest
    41  	lock           *sync.RWMutex
    42  	subscribers    []item
    43  	execOnce       *sync.Once
    44  }
    45  
    46  // newPolarisWatcher create PolarisServiceWatcher to do watch service action
    47  func newPolarisWatcher(param *api.WatchServiceRequest, consumer api.ConsumerAPI) (*PolarisServiceWatcher, error) {
    48  	watcher := &PolarisServiceWatcher{
    49  		subscribeParam: param,
    50  		consumer:       consumer,
    51  		lock:           &sync.RWMutex{},
    52  		subscribers:    make([]item, 0),
    53  		execOnce:       &sync.Once{},
    54  	}
    55  	return watcher, nil
    56  }
    57  
    58  // AddSubscriber add subscriber into watcher's subscribers
    59  func (watcher *PolarisServiceWatcher) AddSubscriber(subscriber func(remoting.EventType, []model.Instance)) {
    60  
    61  	watcher.lock.Lock()
    62  	watcher.lazyRun()
    63  	defer watcher.lock.Unlock()
    64  
    65  	watcher.subscribers = append(watcher.subscribers, subscriber)
    66  }
    67  
    68  // lazyRun Delayed execution, only triggered when AddSubscriber is called, and will only be executed once
    69  func (watcher *PolarisServiceWatcher) lazyRun() {
    70  	watcher.execOnce.Do(func() {
    71  		go watcher.startWatch()
    72  	})
    73  }
    74  
    75  // startWatch start run work to watch target service by polaris
    76  func (watcher *PolarisServiceWatcher) startWatch() {
    77  	for {
    78  		resp, err := watcher.consumer.WatchService(watcher.subscribeParam)
    79  		if err != nil {
    80  			time.Sleep(time.Duration(500 * time.Millisecond))
    81  			continue
    82  		}
    83  		watcher.notifyAllSubscriber(&config_center.ConfigChangeEvent{
    84  			Value:      resp.GetAllInstancesResp.Instances,
    85  			ConfigType: remoting.EventTypeAdd,
    86  		})
    87  
    88  		for {
    89  			select {
    90  			case event := <-resp.EventChannel:
    91  				eType := event.GetSubScribeEventType()
    92  				if eType == internalapi.EventInstance {
    93  					insEvent := event.(*model.InstanceEvent)
    94  
    95  					if insEvent.AddEvent != nil {
    96  						watcher.notifyAllSubscriber(&config_center.ConfigChangeEvent{
    97  							Value:      insEvent.AddEvent.Instances,
    98  							ConfigType: remoting.EventTypeAdd,
    99  						})
   100  					}
   101  					if insEvent.UpdateEvent != nil {
   102  						instances := make([]model.Instance, len(insEvent.UpdateEvent.UpdateList))
   103  						for i := range insEvent.UpdateEvent.UpdateList {
   104  							instances[i] = insEvent.UpdateEvent.UpdateList[i].After
   105  						}
   106  						watcher.notifyAllSubscriber(&config_center.ConfigChangeEvent{
   107  							Value:      instances,
   108  							ConfigType: remoting.EventTypeUpdate,
   109  						})
   110  					}
   111  					if insEvent.DeleteEvent != nil {
   112  						watcher.notifyAllSubscriber(&config_center.ConfigChangeEvent{
   113  							Value:      insEvent.DeleteEvent.Instances,
   114  							ConfigType: remoting.EventTypeDel,
   115  						})
   116  					}
   117  				}
   118  			}
   119  		}
   120  
   121  	}
   122  }
   123  
   124  // notifyAllSubscriber notify config_center.ConfigChangeEvent to all subscriber
   125  func (watcher *PolarisServiceWatcher) notifyAllSubscriber(event *config_center.ConfigChangeEvent) {
   126  	watcher.lock.RLock()
   127  	defer watcher.lock.RUnlock()
   128  
   129  	for i := 0; i < len(watcher.subscribers); i++ {
   130  		subscriber := watcher.subscribers[i]
   131  		subscriber(event.ConfigType, event.Value.([]model.Instance))
   132  	}
   133  
   134  }