Skip to content

Commit 9585b0f

Browse files
committed
refactor
1 parent 521ca10 commit 9585b0f

File tree

2 files changed

+94
-29
lines changed

2 files changed

+94
-29
lines changed

backend/instancemgmt/instance_manager.go

Lines changed: 19 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -2,15 +2,14 @@ package instancemgmt
22

33
import (
44
"context"
5-
"fmt"
65
"reflect"
6+
"sync"
77
"time"
88

99
"github.com/prometheus/client_golang/prometheus"
1010
"github.com/prometheus/client_golang/prometheus/promauto"
1111

1212
"github.com/grafana/grafana-plugin-sdk-go/backend"
13-
gocache "github.com/patrickmn/go-cache"
1413
)
1514

1615
var (
@@ -19,10 +18,7 @@ var (
1918
Name: "active_instances",
2019
Help: "The number of active plugin instances",
2120
})
22-
defaultDisposeTTL = 5 * time.Second
23-
24-
defaultInstanceTTL = 24 * time.Hour
25-
defaultInstanceCleanup = 48 * time.Hour
21+
disposeTTL = 5 * time.Second
2622
)
2723

2824
// Instance is a marker interface for an instance.
@@ -77,35 +73,21 @@ type InstanceProvider interface {
7773

7874
// New create a new instance manager.
7975
func New(provider InstanceProvider) InstanceManager {
80-
return NewWithOptions(provider, defaultInstanceTTL, defaultInstanceCleanup, defaultDisposeTTL)
81-
}
82-
83-
func NewWithOptions(provider InstanceProvider, instanceTTL, instanceCleanup, disposeTTL time.Duration) InstanceManager {
8476
if provider == nil {
8577
panic("provider cannot be nil")
8678
}
87-
cache := gocache.New(instanceTTL, instanceCleanup)
88-
cache.OnEvicted(func(_ string, i interface{}) {
89-
ci := i.(CachedInstance)
90-
if disposer, valid := ci.instance.(InstanceDisposer); valid {
91-
time.AfterFunc(disposeTTL, func() {
92-
disposer.Dispose()
93-
})
94-
}
95-
activeInstances.Dec()
96-
})
9779

9880
return &instanceManager{
9981
provider: provider,
100-
cache: cache,
82+
cache: sync.Map{},
10183
locker: newLocker(),
10284
}
10385
}
10486

10587
type instanceManager struct {
10688
locker *locker
10789
provider InstanceProvider
108-
cache *gocache.Cache
90+
cache sync.Map
10991
}
11092

11193
func (im *instanceManager) Get(ctx context.Context, pluginContext backend.PluginContext) (Instance, error) {
@@ -114,8 +96,9 @@ func (im *instanceManager) Get(ctx context.Context, pluginContext backend.Plugin
11496
return nil, err
11597
}
11698
// Double-checked locking for update/create criteria
117-
strKey := fmt.Sprintf("%v", cacheKey)
118-
item, ok := im.cache.Get(strKey)
99+
im.locker.RLock(cacheKey)
100+
item, ok := im.cache.Load(cacheKey)
101+
im.locker.RUnlock(cacheKey)
119102

120103
if ok {
121104
ci := item.(CachedInstance)
@@ -126,25 +109,32 @@ func (im *instanceManager) Get(ctx context.Context, pluginContext backend.Plugin
126109
}
127110
}
128111

129-
im.locker.Lock(strKey)
130-
defer im.locker.Unlock(strKey)
112+
im.locker.Lock(cacheKey)
113+
defer im.locker.Unlock(cacheKey)
131114

132-
if item, ok := im.cache.Get(strKey); ok {
115+
if item, ok := im.cache.Load(cacheKey); ok {
133116
ci := item.(CachedInstance)
134117
needsUpdate := im.provider.NeedsUpdate(ctx, pluginContext, ci)
135118

136119
if !needsUpdate {
137120
return ci.instance, nil
138121
}
139122

140-
im.cache.Delete(strKey)
123+
if disposer, valid := ci.instance.(InstanceDisposer); valid {
124+
time.AfterFunc(disposeTTL, func() {
125+
disposer.Dispose()
126+
activeInstances.Dec()
127+
})
128+
} else {
129+
activeInstances.Dec()
130+
}
141131
}
142132

143133
instance, err := im.provider.NewInstance(ctx, pluginContext)
144134
if err != nil {
145135
return nil, err
146136
}
147-
im.cache.SetDefault(strKey, CachedInstance{
137+
im.cache.Store(cacheKey, CachedInstance{
148138
PluginContext: pluginContext,
149139
instance: instance,
150140
})
Lines changed: 75 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,75 @@
1+
package instancemgmt
2+
3+
import (
4+
"context"
5+
"fmt"
6+
7+
gocache "github.com/patrickmn/go-cache"
8+
9+
"github.com/grafana/grafana-plugin-sdk-go/backend"
10+
)
11+
12+
type instanceManagerWithTTL struct {
13+
locker *locker
14+
provider InstanceProvider
15+
cache *gocache.Cache
16+
}
17+
18+
func (im *instanceManagerWithTTL) Get(ctx context.Context, pluginContext backend.PluginContext) (Instance, error) {
19+
providerKey, err := im.provider.GetKey(ctx, pluginContext)
20+
if err != nil {
21+
return nil, err
22+
}
23+
// Double-checked locking for update/create criteria
24+
cacheKey := fmt.Sprintf("%v", providerKey)
25+
item, ok := im.cache.Get(cacheKey)
26+
27+
if ok {
28+
ci := item.(CachedInstance)
29+
needsUpdate := im.provider.NeedsUpdate(ctx, pluginContext, ci)
30+
31+
if !needsUpdate {
32+
return ci.instance, nil
33+
}
34+
}
35+
36+
im.locker.Lock(cacheKey)
37+
defer im.locker.Unlock(cacheKey)
38+
39+
if item, ok := im.cache.Get(cacheKey); ok {
40+
ci := item.(CachedInstance)
41+
needsUpdate := im.provider.NeedsUpdate(ctx, pluginContext, ci)
42+
43+
if !needsUpdate {
44+
return ci.instance, nil
45+
}
46+
47+
im.cache.Delete(cacheKey)
48+
}
49+
50+
instance, err := im.provider.NewInstance(ctx, pluginContext)
51+
if err != nil {
52+
return nil, err
53+
}
54+
im.cache.SetDefault(cacheKey, CachedInstance{
55+
PluginContext: pluginContext,
56+
instance: instance,
57+
})
58+
activeInstances.Inc()
59+
60+
return instance, nil
61+
}
62+
63+
func (im *instanceManagerWithTTL) Do(ctx context.Context, pluginContext backend.PluginContext, fn InstanceCallbackFunc) error {
64+
if fn == nil {
65+
panic("fn cannot be nil")
66+
}
67+
68+
instance, err := im.Get(ctx, pluginContext)
69+
if err != nil {
70+
return err
71+
}
72+
73+
callInstanceHandlerFunc(fn, instance)
74+
return nil
75+
}

0 commit comments

Comments
 (0)