vitess.io/vitess@v0.16.2/go/vt/srvtopo/watch_srvkeyspace.go (about) 1 /* 2 Copyright 2021 The Vitess 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 srvtopo 18 19 import ( 20 "context" 21 "time" 22 23 "vitess.io/vitess/go/stats" 24 "vitess.io/vitess/go/vt/proto/topodata" 25 "vitess.io/vitess/go/vt/topo" 26 ) 27 28 type SrvKeyspaceWatcher struct { 29 rw *resilientWatcher 30 } 31 32 type srvKeyspaceKey struct { 33 cell, keyspace string 34 } 35 36 func (k *srvKeyspaceKey) String() string { 37 return k.cell + "." + k.keyspace 38 } 39 40 func NewSrvKeyspaceWatcher(topoServer *topo.Server, counts *stats.CountersWithSingleLabel, cacheRefresh, cacheTTL time.Duration) *SrvKeyspaceWatcher { 41 watch := func(entry *watchEntry) { 42 key := entry.key.(*srvKeyspaceKey) 43 ctx, cancel := context.WithCancel(context.Background()) 44 defer cancel() 45 46 current, changes, err := topoServer.WatchSrvKeyspace(ctx, key.cell, key.keyspace) 47 if err != nil { 48 entry.update(nil, err, true) 49 return 50 } 51 52 entry.update(current.Value, current.Err, true) 53 if current.Err != nil { 54 return 55 } 56 57 for c := range changes { 58 entry.update(c.Value, c.Err, false) 59 if c.Err != nil { 60 return 61 } 62 } 63 } 64 65 rw := &resilientWatcher{ 66 watcher: watch, 67 counts: counts, 68 cacheRefreshInterval: cacheRefresh, 69 cacheTTL: cacheTTL, 70 entries: make(map[string]*watchEntry), 71 } 72 73 return &SrvKeyspaceWatcher{rw} 74 } 75 76 func (w *SrvKeyspaceWatcher) GetSrvKeyspace(ctx context.Context, cell, keyspace string) (*topodata.SrvKeyspace, error) { 77 key := &srvKeyspaceKey{cell, keyspace} 78 v, err := w.rw.getValue(ctx, key) 79 ks, _ := v.(*topodata.SrvKeyspace) 80 return ks, err 81 } 82 83 func (w *SrvKeyspaceWatcher) WatchSrvKeyspace(ctx context.Context, cell, keyspace string, callback func(*topodata.SrvKeyspace, error) bool) { 84 entry := w.rw.getEntry(&srvKeyspaceKey{cell, keyspace}) 85 entry.addListener(ctx, func(v any, err error) bool { 86 srvkeyspace, _ := v.(*topodata.SrvKeyspace) 87 return callback(srvkeyspace, err) 88 }) 89 } 90 91 func (w *SrvKeyspaceWatcher) srvKeyspaceCacheStatus() (result []*SrvKeyspaceCacheStatus) { 92 w.rw.mutex.Lock() 93 defer w.rw.mutex.Unlock() 94 95 for _, entry := range w.rw.entries { 96 entry.mutex.Lock() 97 expirationTime := time.Now().Add(w.rw.cacheTTL) 98 if entry.watchState != watchStateRunning { 99 expirationTime = entry.lastValueTime.Add(w.rw.cacheTTL) 100 } 101 102 key := entry.key.(*srvKeyspaceKey) 103 value, _ := entry.value.(*topodata.SrvKeyspace) 104 105 result = append(result, &SrvKeyspaceCacheStatus{ 106 Cell: key.cell, 107 Keyspace: key.keyspace, 108 Value: value, 109 ExpirationTime: expirationTime, 110 LastErrorTime: entry.lastErrorTime, 111 LastError: entry.lastError, 112 }) 113 entry.mutex.Unlock() 114 } 115 return 116 }