@@ -6,6 +6,8 @@ package api
66import (
77 "context"
88 "fmt"
9+ "math"
10+ "sync"
911 "time"
1012
1113 "github.com/prometheus/prometheus/model/labels"
@@ -16,10 +18,46 @@ type RemoteQuery interface {
1618 fmt.Stringer
1719}
1820
21+ // Deprecated: RemoteEndpoints will be replaced with
22+ // RemoteEndpointsV2 / RemoteEndpointsV3 in a future breaking change.
1923type RemoteEndpoints interface {
2024 Engines () []RemoteEngine
2125}
2226
27+ // RemoteEndpointsV2 describes endpoints that accept pruning hints when
28+ // selecting remote engines.
29+ //
30+ // For example implementations may use the hints to prune the TSDBInfos, but
31+ // also may safely ignore them and return all available remote engines.
32+ //
33+ // NOTE(Aleksandr Krivoshchekov):
34+ // We add a new interface as a temporary backward compatibility.
35+ // RemoteEndpoints will be replaced with it in a future breaking change.
36+ type RemoteEndpointsV2 interface {
37+ EnginesV2 (mint , maxt int64 ) []RemoteEngine
38+ }
39+
40+ type RemoteEndpointsQuery struct {
41+ MinT int64
42+ MaxT int64
43+ }
44+
45+ // RemoteEndpointsV3 describes endpoints that accept pruning hints when
46+ // selecting remote engines.
47+ //
48+ // For example implementations may use the hints to prune the TSDBInfos, but
49+ // also may safely ignore them and return all available remote engines.
50+ //
51+ // NOTE(Aleksandr Krivoshchekov):
52+ // We add a new interface as a temporary backward compatibility.
53+ // RemoteEndpoints will be replaced with it in a future breaking change.
54+ //
55+ // Unlike RemoteEndpointsV2, this interface can be extended with more hints
56+ // in the future, without making any breaking changes.
57+ type RemoteEndpointsV3 interface {
58+ EnginesV3 (query RemoteEndpointsQuery ) []RemoteEngine
59+ }
60+
2361type RemoteEngine interface {
2462 MaxT () int64
2563 MinT () int64
@@ -44,6 +82,71 @@ func (m staticEndpoints) Engines() []RemoteEngine {
4482 return m .engines
4583}
4684
85+ func (m staticEndpoints ) EnginesV2 (mint , maxt int64 ) []RemoteEngine {
86+ return m .engines
87+ }
88+
89+ func (m staticEndpoints ) EnginesV3 (query RemoteEndpointsQuery ) []RemoteEngine {
90+ return m .engines
91+ }
92+
4793func NewStaticEndpoints (engines []RemoteEngine ) RemoteEndpoints {
4894 return & staticEndpoints {engines : engines }
4995}
96+
97+ type cachedEndpoints struct {
98+ endpoints RemoteEndpoints
99+
100+ enginesOnce sync.Once
101+ engines []RemoteEngine
102+ }
103+
104+ func (l * cachedEndpoints ) Engines () []RemoteEngine {
105+ return l .EnginesV3 (RemoteEndpointsQuery {
106+ MaxT : math .MinInt64 ,
107+ MinT : math .MaxInt64 ,
108+ })
109+ }
110+
111+ func (l * cachedEndpoints ) EnginesV2 (mint , maxt int64 ) []RemoteEngine {
112+ return l .EnginesV3 (RemoteEndpointsQuery {
113+ MaxT : maxt ,
114+ MinT : mint ,
115+ })
116+ }
117+
118+ func (l * cachedEndpoints ) EnginesV3 (query RemoteEndpointsQuery ) []RemoteEngine {
119+ l .enginesOnce .Do (func () {
120+ l .engines = getEngines (l .endpoints , query )
121+ })
122+ return l .engines
123+ }
124+
125+ func getEngines (endpoints RemoteEndpoints , query RemoteEndpointsQuery ) []RemoteEngine {
126+ if v3 , ok := endpoints .(RemoteEndpointsV3 ); ok {
127+ return v3 .EnginesV3 (query )
128+ }
129+
130+ if v2 , ok := endpoints .(RemoteEndpointsV2 ); ok {
131+ return v2 .EnginesV2 (query .MinT , query .MaxT )
132+ }
133+
134+ return endpoints .Engines ()
135+ }
136+
137+ // NewCachedEndpoints returns an endpoints wrapper that
138+ // resolves and caches engines on first access.
139+ //
140+ // All subsequent Engines calls return cached engines, ignoring any query
141+ // parameters.
142+ func NewCachedEndpoints (endpoints RemoteEndpoints ) RemoteEndpoints {
143+ if endpoints == nil {
144+ panic ("api.NewCachedEndpoints: endpoints is nil" )
145+ }
146+
147+ if le , ok := endpoints .(* cachedEndpoints ); ok {
148+ return le
149+ }
150+
151+ return & cachedEndpoints {endpoints : endpoints }
152+ }
0 commit comments