dubbo.apache.org/dubbo-go/v3@v3.1.1/registry/polaris/listener.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 "fmt" 22 "net/url" 23 "strconv" 24 ) 25 26 import ( 27 gxchan "github.com/dubbogo/gost/container/chan" 28 "github.com/dubbogo/gost/log/logger" 29 30 perrors "github.com/pkg/errors" 31 32 "github.com/polarismesh/polaris-go/pkg/model" 33 ) 34 35 import ( 36 "dubbo.apache.org/dubbo-go/v3/common" 37 "dubbo.apache.org/dubbo-go/v3/common/constant" 38 "dubbo.apache.org/dubbo-go/v3/config_center" 39 "dubbo.apache.org/dubbo-go/v3/registry" 40 "dubbo.apache.org/dubbo-go/v3/remoting" 41 ) 42 43 type polarisListener struct { 44 watcher *PolarisServiceWatcher 45 events *gxchan.UnboundedChan 46 closeCh chan struct{} 47 } 48 49 // NewPolarisListener new polaris listener 50 func NewPolarisListener(watcher *PolarisServiceWatcher) (*polarisListener, error) { 51 listener := &polarisListener{ 52 watcher: watcher, 53 events: gxchan.NewUnboundedChan(32), 54 closeCh: make(chan struct{}), 55 } 56 listener.startListen() 57 return listener, nil 58 } 59 func (pl *polarisListener) startListen() { 60 pl.watcher.AddSubscriber(func(et remoting.EventType, ins []model.Instance) { 61 for i := range ins { 62 pl.events.In() <- &config_center.ConfigChangeEvent{Value: ins[i], ConfigType: et} 63 } 64 }) 65 } 66 67 // Next returns next service event once received 68 func (pl *polarisListener) Next() (*registry.ServiceEvent, error) { 69 for { 70 select { 71 case <-pl.closeCh: 72 logger.Warnf("polaris listener is close") 73 return nil, perrors.New("listener stopped") 74 case val := <-pl.events.Out(): 75 e, _ := val.(*config_center.ConfigChangeEvent) 76 logger.Debugf("got polaris event %s", e) 77 instance := e.Value.(model.Instance) 78 return ®istry.ServiceEvent{Action: e.ConfigType, Service: generateUrl(instance)}, nil 79 } 80 } 81 } 82 83 // Close closes this listener 84 func (pl *polarisListener) Close() { 85 // TODO need to add UnWatch in polaris 86 close(pl.closeCh) 87 } 88 89 func generateUrl(instance model.Instance) *common.URL { 90 if instance.GetMetadata() == nil { 91 logger.Errorf("polaris instance metadata is empty,instance:%+v", instance) 92 return nil 93 } 94 path := instance.GetMetadata()["path"] 95 myInterface := instance.GetMetadata()["interface"] 96 if len(path) == 0 && len(myInterface) == 0 { 97 logger.Errorf("polaris instance metadata does not have both path key and interface key,instance:%+v", instance) 98 return nil 99 } 100 if len(path) == 0 && len(myInterface) != 0 { 101 path = "/" + myInterface 102 } 103 protocol := instance.GetProtocol() 104 if len(protocol) == 0 { 105 logger.Errorf("polaris instance metadata does not have protocol key,instance:%+v", instance) 106 return nil 107 } 108 urlMap := url.Values{} 109 for k, v := range instance.GetMetadata() { 110 urlMap.Set(k, v) 111 } 112 urlMap.Set(constant.PolarisInstanceID, instance.GetId()) 113 urlMap.Set(constant.PolarisInstanceHealthStatus, fmt.Sprintf("%+v", instance.IsHealthy())) 114 urlMap.Set(constant.PolarisInstanceIsolatedStatus, fmt.Sprintf("%+v", instance.IsIsolated())) 115 instance.GetCircuitBreakerStatus() 116 return common.NewURLWithOptions( 117 common.WithIp(instance.GetHost()), 118 common.WithPort(strconv.Itoa(int(instance.GetPort()))), 119 common.WithProtocol(protocol), 120 common.WithParams(urlMap), 121 common.WithPath(path), 122 ) 123 }