Skip to content

Commit 96a70f2

Browse files
committed
refactor some more
1 parent 9585b0f commit 96a70f2

File tree

5 files changed

+69
-5
lines changed

5 files changed

+69
-5
lines changed

backend/datasource/manage.go

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ import (
66
"os"
77

88
"github.com/grafana/grafana-plugin-sdk-go/backend"
9+
"github.com/grafana/grafana-plugin-sdk-go/backend/instancemgmt"
910
"github.com/grafana/grafana-plugin-sdk-go/backend/tracing"
1011
"github.com/grafana/grafana-plugin-sdk-go/internal/automanagement"
1112
"github.com/grafana/grafana-plugin-sdk-go/internal/buildinfo"
@@ -27,6 +28,11 @@ type ManageOpts struct {
2728

2829
// Stateless query conversion handler
2930
QueryConversionHandler backend.QueryConversionHandler
31+
32+
// UseTTLInstanceManager controls whether to use the TTL-based instance manager.
33+
// When true, instances will be automatically evicted from the cache after a configurable TTL.
34+
// Default is false, which uses the standard instance manager.
35+
UseTTLInstanceManager bool
3036
}
3137

3238
// Manage starts serving the data source over gPRC with automatic instance management.
@@ -46,7 +52,17 @@ func Manage(pluginID string, instanceFactory InstanceFactoryFunc, opts ManageOpt
4652
if err := backend.SetupTracer(pluginID, opts.TracingOpts); err != nil {
4753
return fmt.Errorf("setup tracer: %w", err)
4854
}
49-
handler := automanagement.NewManager(NewInstanceManager(instanceFactory))
55+
56+
ip := NewInstanceProvider(instanceFactory)
57+
58+
var im instancemgmt.InstanceManager
59+
if opts.UseTTLInstanceManager {
60+
im = instancemgmt.NewTTLInstanceManager(ip)
61+
} else {
62+
im = instancemgmt.New(ip)
63+
}
64+
65+
handler := automanagement.NewManager(im)
5066
return backend.Manage(pluginID, backend.ServeOpts{
5167
CheckHealthHandler: handler,
5268
CallResourceHandler: handler,

backend/instancemgmt/instance_manager.go

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,9 @@ var (
1818
Name: "active_instances",
1919
Help: "The number of active plugin instances",
2020
})
21+
)
22+
23+
const (
2124
disposeTTL = 5 * time.Second
2225
)
2326

backend/instancemgmt/instance_manager_test.go

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -7,8 +7,9 @@ import (
77
"testing"
88
"time"
99

10-
"github.com/grafana/grafana-plugin-sdk-go/backend"
1110
"github.com/stretchr/testify/require"
11+
12+
"github.com/grafana/grafana-plugin-sdk-go/backend"
1213
)
1314

1415
func TestInstanceManager(t *testing.T) {
@@ -21,7 +22,7 @@ func TestInstanceManager(t *testing.T) {
2122
}
2223

2324
tip := &testInstanceProvider{}
24-
im := NewWithOptions(tip, defaultInstanceTTL, defaultInstanceCleanup, time.Millisecond)
25+
im := New(tip)
2526

2627
t.Run("When getting instance should create a new instance", func(t *testing.T) {
2728
instance, err := im.Get(ctx, pCtx)
@@ -75,7 +76,7 @@ func TestInstanceManagerExpiration(t *testing.T) {
7576
}
7677

7778
tip := &testInstanceProvider{}
78-
im := NewWithOptions(tip, time.Millisecond, 2*time.Millisecond, 10*time.Millisecond)
79+
im := newTTLInstanceManager(tip, time.Millisecond, 2*time.Millisecond)
7980

8081
instance, err := im.Get(ctx, pCtx)
8182
require.NoError(t, err)
@@ -151,7 +152,7 @@ func TestInstanceManagerConcurrency(t *testing.T) {
151152
},
152153
}
153154
tip := &testInstanceProvider{}
154-
im := NewWithOptions(tip, defaultInstanceTTL, defaultInstanceCleanup, time.Millisecond)
155+
im := newTTLInstanceManager(tip, defaultInstanceTTL, defaultInstanceCleanupInterval)
155156
// Creating initial instance with old contexts
156157
instanceToDispose, _ := im.Get(ctx, initialPCtx)
157158

backend/instancemgmt/intance_manager_ttl.go

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,12 +3,52 @@ package instancemgmt
33
import (
44
"context"
55
"fmt"
6+
"time"
67

78
gocache "github.com/patrickmn/go-cache"
89

910
"github.com/grafana/grafana-plugin-sdk-go/backend"
1011
)
1112

13+
const (
14+
defaultInstanceTTL = 24 * time.Hour
15+
defaultInstanceCleanupInterval = 48 * time.Hour
16+
)
17+
18+
// NewTTLInstanceManager creates a new instance manager with TTL-based caching.
19+
// Instances will be automatically evicted from the cache after the specified TTL.
20+
func NewTTLInstanceManager(provider InstanceProvider) InstanceManager {
21+
return newTTLInstanceManager(provider, defaultInstanceTTL, defaultInstanceCleanupInterval)
22+
}
23+
24+
func newTTLInstanceManager(provider InstanceProvider, instanceTTL, instanceCleanupInterval time.Duration) InstanceManager {
25+
if provider == nil {
26+
panic("provider cannot be nil")
27+
}
28+
29+
// Use go-cache for TTL-based caching
30+
cache := gocache.New(instanceTTL, instanceCleanupInterval)
31+
32+
// Set up the OnEvicted callback to dispose instances
33+
cache.OnEvicted(func(_ string, value interface{}) {
34+
ci := value.(CachedInstance)
35+
if disposer, valid := ci.instance.(InstanceDisposer); valid {
36+
time.AfterFunc(disposeTTL, func() {
37+
disposer.Dispose()
38+
activeInstances.Dec()
39+
})
40+
} else {
41+
activeInstances.Dec()
42+
}
43+
})
44+
45+
return &instanceManagerWithTTL{
46+
provider: provider,
47+
cache: cache,
48+
locker: newLocker(),
49+
}
50+
}
51+
1252
type instanceManagerWithTTL struct {
1353
locker *locker
1454
provider InstanceProvider

experimental/featuretoggles/featuretoggles.go

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,10 @@ import (
77

88
const (
99
EnabledFeatures = "GF_INSTANCE_FEATURE_TOGGLES_ENABLE"
10+
11+
// TTLInstanceManager is a feature toggle for enabling the TTL-based instance manager.
12+
// When enabled, instances will be automatically evicted from the cache after a configurable TTL.
13+
TTLInstanceManager = "ttlInstanceManager"
1014
)
1115

1216
// FeatureToggles can check if feature toggles are enabled on the Grafana instance.

0 commit comments

Comments
 (0)