@@ -2,6 +2,7 @@ package queue
2
2
3
3
import (
4
4
"math/rand"
5
+ "reflect"
5
6
"sort"
6
7
"time"
7
8
@@ -63,8 +64,11 @@ type userQueue struct {
63
64
64
65
// If not nil, only these queriers can handle user requests. If nil, all queriers can.
65
66
// We set this to nil if number of available queriers <= maxQueriers.
66
- queriers map [string ]struct {}
67
- maxQueriers int
67
+ queriers map [string ]struct {}
68
+ reservedQueriers map [string ]int64
69
+ priorityList []int64
70
+ priorityEnabled bool
71
+ maxQueriers int
68
72
69
73
// Seed for shuffle sharding of queriers. This seed is based on userID only and is therefore consistent
70
74
// between different frontends.
@@ -110,7 +114,7 @@ func (q *queues) deleteQueue(userID string) {
110
114
// MaxQueriers is used to compute which queriers should handle requests for this user.
111
115
// If maxQueriers is <= 0, all queriers can handle this user's requests.
112
116
// If maxQueriers has changed since the last call, queriers for this are recomputed.
113
- func (q * queues ) getOrAddQueue (userID string , maxQueriers int ) userRequestQueue {
117
+ func (q * queues ) getOrAddQueue (userID string , maxQueriers int , priorityList [] int64 , priorityEnabled bool ) userRequestQueue {
114
118
// Empty user is not allowed, as that would break our users list ("" is used for free spot).
115
119
if userID == "" {
116
120
return nil
@@ -121,48 +125,12 @@ func (q *queues) getOrAddQueue(userID string, maxQueriers int) userRequestQueue
121
125
}
122
126
123
127
uq := q .userQueues [userID ]
124
- queryPriority := q .limits .QueryPriority (userID )
125
128
126
129
if uq == nil {
127
- queueSize := q .limits .MaxOutstandingPerTenant (userID )
128
- // 0 is the default value of the flag. If the old flag is set
129
- // then we use its value for compatibility reason.
130
- if q .maxUserQueueSize != 0 {
131
- queueSize = q .maxUserQueueSize
132
- }
133
- uq = & userQueue {
134
- seed : util .ShuffleShardSeed (userID , "" ),
135
- index : - 1 ,
136
- }
137
-
138
- if queryPriority .Enabled {
139
- uq .queue = NewPriorityRequestQueue (util .NewPriorityQueue (nil ))
140
- } else {
141
- uq .queue = NewFIFORequestQueue (make (chan Request , queueSize ))
142
- }
143
-
144
- q .userQueues [userID ] = uq
145
-
146
- // Add user to the list of users... find first free spot, and put it there.
147
- for ix , u := range q .users {
148
- if u == "" {
149
- uq .index = ix
150
- q .users [ix ] = userID
151
- break
152
- }
153
- }
154
-
155
- // ... or add to the end.
156
- if uq .index < 0 {
157
- uq .index = len (q .users )
158
- q .users = append (q .users , userID )
159
- }
130
+ uq = q .createUserQueue (userID )
160
131
}
161
132
162
- if uq .maxQueriers != maxQueriers {
163
- uq .maxQueriers = maxQueriers
164
- uq .queriers = shuffleQueriersForUser (uq .seed , maxQueriers , q .sortedQueriers , nil )
165
- }
133
+ q .updateUserQueuesAttributes (uq , userID , maxQueriers , priorityList , priorityEnabled )
166
134
167
135
return uq .queue
168
136
}
@@ -196,21 +164,98 @@ func (q *queues) getNextQueueForQuerier(lastUserIndex int, querierID string) (us
196
164
}
197
165
}
198
166
199
- // TODO: justinjung04, reserved queriers
200
- //if priority, isReserved := uq.reservedQueriers[querierID]; isReserved {
201
- // return uq.queues[priority], u, uid
202
- //}
203
-
204
167
return uq .queue , u , uid
205
168
}
206
169
return nil , "" , uid
207
170
}
208
171
209
- func (q * queues ) getMinPriority (userID string , querierID string ) int64 {
210
- // TODO: justinjung04 reserved querier
211
- // check list of queriers and QueryPriority config
212
- // from QueryPriority config, establish map of
213
- return 0
172
+ func (q * queues ) createUserQueue (userID string ) * userQueue {
173
+ uq := & userQueue {
174
+ seed : util .ShuffleShardSeed (userID , "" ),
175
+ index : - 1 ,
176
+ }
177
+
178
+ uq .queue = q .createUserRequestQueue (userID )
179
+ q .userQueues [userID ] = uq
180
+
181
+ // Add user to the list of users... find first free spot, and put it there.
182
+ for ix , u := range q .users {
183
+ if u == "" {
184
+ uq .index = ix
185
+ q .users [ix ] = userID
186
+ break
187
+ }
188
+ }
189
+
190
+ // ... or add to the end.
191
+ if uq .index < 0 {
192
+ uq .index = len (q .users )
193
+ q .users = append (q .users , userID )
194
+ }
195
+
196
+ return uq
197
+ }
198
+
199
+ func (q * queues ) createUserRequestQueue (userID string ) userRequestQueue {
200
+ if q .limits .QueryPriority (userID ).Enabled {
201
+ return NewPriorityRequestQueue (util .NewPriorityQueue (nil ))
202
+ }
203
+
204
+ return NewFIFORequestQueue (make (chan Request , q .getQueueSize (userID )))
205
+ }
206
+
207
+ func (q * queues ) getQueueSize (userID string ) int {
208
+ queueSize := q .limits .MaxOutstandingPerTenant (userID )
209
+
210
+ // 0 is the default value of the flag. If the old flag is set
211
+ // then we use its value for compatibility reason.
212
+ if q .maxUserQueueSize != 0 {
213
+ queueSize = q .maxUserQueueSize
214
+ }
215
+
216
+ return queueSize
217
+ }
218
+
219
+ func (q * queues ) updateUserQueuesAttributes (uq * userQueue , userID string , maxQueriers int , priorityList []int64 , priorityEnabled bool ) {
220
+ if uq .maxQueriers != maxQueriers {
221
+ uq .maxQueriers = maxQueriers
222
+ uq .queriers = shuffleQueriersForUser (uq .seed , maxQueriers , q .sortedQueriers , nil )
223
+ }
224
+
225
+ // if query priority is newly enabled/disabled, transfer the requests to the new queue
226
+ if uq .priorityEnabled != priorityEnabled {
227
+ tmpQueue := q .createUserRequestQueue (userID )
228
+ uq .queue .closeQueue ()
229
+
230
+ for uq .queue .length () > 0 {
231
+ tmpQueue .enqueueRequest (uq .queue .dequeueRequest (0 , false ))
232
+ }
233
+ uq .queue = tmpQueue
234
+ }
235
+
236
+ if priorityEnabled && ! reflect .DeepEqual (uq .priorityList , priorityList ) {
237
+ reservedQueriers := make (map [string ]int64 )
238
+
239
+ i := 0
240
+ for querierID := range uq .queriers {
241
+ reservedQueriers [querierID ] = priorityList [i ]
242
+ i ++
243
+ if i == len (priorityList ) {
244
+ break
245
+ }
246
+ }
247
+
248
+ uq .reservedQueriers = reservedQueriers
249
+ uq .priorityList = priorityList
250
+ uq .priorityEnabled = priorityEnabled
251
+ }
252
+ }
253
+
254
+ func (q * queues ) getMinPriority (userID string , querierID string ) (int64 , bool ) {
255
+ if priority , ok := q .userQueues [userID ].reservedQueriers [querierID ]; ok {
256
+ return priority , true
257
+ }
258
+ return 0 , false
214
259
}
215
260
216
261
func (q * queues ) addQuerierConnection (querierID string ) {
@@ -349,7 +394,7 @@ type MockLimits struct {
349
394
queryPriority validation.QueryPriority
350
395
}
351
396
352
- func (l MockLimits ) MaxQueriersPerUser (user string ) float64 {
397
+ func (l MockLimits ) MaxQueriersPerUser (_ string ) float64 {
353
398
return l .maxQueriersPerUser
354
399
}
355
400
0 commit comments