...
1 package reaper
2
3 import (
4 "context"
5 "fmt"
6 "sync"
7 "time"
8
9 "github.com/cybertec-postgresql/pgwatch/v3/internal/metrics"
10 "github.com/cybertec-postgresql/pgwatch/v3/internal/sources"
11 )
12
13 var monitoredDbCache map[string]*sources.SourceConn
14 var monitoredDbCacheLock sync.RWMutex
15
16 var lastSQLFetchError sync.Map
17
18 func UpdateMonitoredDBCache(data sources.SourceConns) {
19 monitoredDbCacheNew := make(map[string]*sources.SourceConn)
20 for _, row := range data {
21 monitoredDbCacheNew[row.Name] = row
22 }
23 monitoredDbCacheLock.Lock()
24 monitoredDbCache = monitoredDbCacheNew
25 monitoredDbCacheLock.Unlock()
26 }
27
28 func GetMonitoredDatabaseByUniqueName(ctx context.Context, name string) (*sources.SourceConn, error) {
29 if ctx.Err() != nil {
30 return nil, ctx.Err()
31 }
32 monitoredDbCacheLock.RLock()
33 defer monitoredDbCacheLock.RUnlock()
34 md, exists := monitoredDbCache[name]
35 if !exists || md == nil {
36 return nil, fmt.Errorf("database %s not found in cache", name)
37 }
38 return md, nil
39 }
40
41 type InstanceMetricCache struct {
42 cache map[string](metrics.Measurements)
43 sync.RWMutex
44 }
45
46 func NewInstanceMetricCache() *InstanceMetricCache {
47 return &InstanceMetricCache{
48 cache: make(map[string](metrics.Measurements)),
49 }
50 }
51
52 func (imc *InstanceMetricCache) Get(key string, age time.Duration) metrics.Measurements {
53 if key == "" {
54 return nil
55 }
56 imc.RLock()
57 defer imc.RUnlock()
58 instanceMetricEpochNs := (imc.cache[key]).GetEpoch()
59
60 if time.Now().UnixNano()-instanceMetricEpochNs > age.Nanoseconds() {
61 return nil
62 }
63 instanceMetricData, ok := imc.cache[key]
64 if !ok {
65 return nil
66 }
67 return instanceMetricData.DeepCopy()
68 }
69
70 func (imc *InstanceMetricCache) Put(key string, data metrics.Measurements) {
71 if len(data) == 0 || key == "" {
72 return
73 }
74 imc.Lock()
75 defer imc.Unlock()
76 m := data.DeepCopy()
77 if !m.IsEpochSet() {
78 m.Touch()
79 }
80 imc.cache[key] = m
81 }
82