@ -25,15 +25,15 @@ type querier struct {
disconnectedAt time . Time
}
// This struct holds user queues for pending requests. It also keeps track of connected queriers,
// and mapping between user s and queriers.
type q ueues struct {
userQ ueues map [ string ] * user Queue
// This struct holds tenant queues for pending requests. It also keeps track of connected queriers,
// and mapping between tenant s and queriers.
type tenantQ ueues struct {
q ueues map [ string ] * tenant Queue
// List of all user s with queues, used for iteration when searching for next queue to handle.
// Users removed from the middle are replaced with "". To avoid skipping user s during iteration, we only shrink
// List of all tenant s with queues, used for iteration when searching for next queue to handle.
// Tenants removed from the middle are replaced with "". To avoid skipping tenant s during iteration, we only shrink
// this list when there are ""'s at the end of it.
user s [ ] string
tenant s [ ] string
maxUserQueueSize int
@ -48,8 +48,8 @@ type queues struct {
sortedQueriers [ ] string
}
type user Queue struct {
ch chan Request
type tenant Queue struct {
ch RequestChannel
// If not nil, only these queriers can handle user requests. If nil, all queriers can.
// We set this to nil if number of available queriers <= maxQueriers.
@ -64,10 +64,10 @@ type userQueue struct {
index int
}
func newUser Queues ( maxUserQueueSize int , forgetDelay time . Duration ) * q ueues {
return & q ueues{
userQueues : map [ string ] * user Queue{ } ,
users : nil ,
func newTenant Queues ( maxUserQueueSize int , forgetDelay time . Duration ) * tenantQ ueues {
return & tenantQ ueues{
queues : map [ string ] * tenant Queue{ } ,
tenants : nil ,
maxUserQueueSize : maxUserQueueSize ,
forgetDelay : forgetDelay ,
queriers : map [ string ] * querier { } ,
@ -75,32 +75,32 @@ func newUserQueues(maxUserQueueSize int, forgetDelay time.Duration) *queues {
}
}
func ( q * q ueues) len ( ) int {
return len ( q . userQ ueues)
func ( q * tenantQ ueues) len ( ) int {
return len ( q . q ueues)
}
func ( q * q ueues) deleteQueue ( userID string ) {
uq := q . userQueues [ userID ]
func ( q * tenantQ ueues) deleteQueue ( tenant string ) {
uq := q . queues [ tenant ]
if uq == nil {
return
}
delete ( q . userQueues , userID )
q . user s[ uq . index ] = ""
delete ( q . queues , tenant )
q . tenant s[ uq . index ] = ""
// Shrink users list size if possible. This is safe, and no users will be skipped during iteration.
for ix := len ( q . user s) - 1 ; ix >= 0 && q . user s[ ix ] == "" ; ix -- {
q . user s = q . user s[ : ix ]
for ix := len ( q . tenant s) - 1 ; ix >= 0 && q . tenant s[ ix ] == "" ; ix -- {
q . tenant s = q . tenant s[ : ix ]
}
}
// Returns existing or new queue for user .
// MaxQueriers is used to compute which queriers should handle requests for this user .
// If maxQueriers is <= 0, all queriers can handle this user 's requests.
// Returns existing or new queue for a tenant .
// MaxQueriers is used to compute which queriers should handle requests for this tenant .
// If maxQueriers is <= 0, all queriers can handle this tenant 's requests.
// If maxQueriers has changed since the last call, queriers for this are recomputed.
func ( q * q ueues) getOrAddQueue ( userID string , maxQueriers int ) chan Request {
// Empty user is not allowed, as that would break our user s list ("" is used for free spot).
if userID == "" {
func ( q * tenantQ ueues) getOrAddQueue ( tenant string , maxQueriers int ) RequestChannel {
// Empty tenant is not allowed, as that would break our tenant s list ("" is used for free spot).
if tenant == "" {
return nil
}
@ -108,35 +108,35 @@ func (q *queues) getOrAddQueue(userID string, maxQueriers int) chan Request {
maxQueriers = 0
}
uq := q . userQueues [ userID ]
uq := q . queues [ tenant ]
if uq == nil {
uq = & user Queue{
ch : make ( chan Request , q . maxUserQueueSize ) ,
seed : util . ShuffleShardSeed ( userID , "" ) ,
uq = & tenant Queue{
ch : make ( RequestChannel , q . maxUserQueueSize ) ,
seed : util . ShuffleShardSeed ( tenant , "" ) ,
index : - 1 ,
}
q . userQueues [ userID ] = uq
q . queues [ tenant ] = uq
// Add user to the list of users... find first free spot, and put it there.
for ix , u := range q . user s {
for ix , u := range q . tenant s {
if u == "" {
uq . index = ix
q . user s[ ix ] = userID
q . tenant s[ ix ] = tenant
break
}
}
// ... or add to the end.
if uq . index < 0 {
uq . index = len ( q . user s)
q . user s = append ( q . users , userID )
uq . index = len ( q . tenant s)
q . tenant s = append ( q . tenants , tenant )
}
}
if uq . maxQueriers != maxQueriers {
uq . maxQueriers = maxQueriers
uq . queriers = shuffleQueriersForUser ( uq . seed , maxQueriers , q . sortedQueriers , nil )
uq . queriers = shuffleQueriersForTenants ( uq . seed , maxQueriers , q . sortedQueriers , nil )
}
return uq . ch
@ -145,7 +145,7 @@ func (q *queues) getOrAddQueue(userID string, maxQueriers int) chan Request {
// Finds next queue for the querier. To support fair scheduling between users, client is expected
// to pass last user index returned by this function as argument. Is there was no previous
// last user index, use -1.
func ( q * q ueues) getNextQueueForQuerier ( lastUserIndex int , querierID string ) ( chan Request , string , int ) {
func ( q * tenantQ ueues) getNextQueueForQuerier ( lastUserIndex QueueIndex , querierID string ) ( RequestChannel , string , QueueIndex ) {
uid := lastUserIndex
// Ensure the querier is not shutting down. If the querier is shutting down, we shouldn't forward
@ -154,21 +154,21 @@ func (q *queues) getNextQueueForQuerier(lastUserIndex int, querierID string) (ch
return nil , "" , uid
}
for iters := 0 ; iters < len ( q . user s) ; iters ++ {
for iters := 0 ; iters < len ( q . tenant s) ; iters ++ {
uid = uid + 1
// Don't use "mod len(q.users)", as that could skip users at the beginning of the list
// for example when q.users has shrunk since last call.
if uid >= len ( q . user s) {
if int ( uid ) >= len ( q . tenant s) {
uid = 0
}
u := q . user s[ uid ]
u := q . tenant s[ uid ]
if u == "" {
continue
}
q := q . userQ ueues[ u ]
q := q . q ueues[ u ]
if q . queriers != nil {
if _ , ok := q . queriers [ querierID ] ; ! ok {
@ -182,7 +182,7 @@ func (q *queues) getNextQueueForQuerier(lastUserIndex int, querierID string) (ch
return nil , "" , uid
}
func ( q * q ueues) addQuerierConnection ( querierID string ) {
func ( q * tenantQ ueues) addQuerierConnection ( querierID string ) {
info := q . queriers [ querierID ]
if info != nil {
info . connections ++
@ -202,7 +202,7 @@ func (q *queues) addQuerierConnection(querierID string) {
q . recomputeUserQueriers ( )
}
func ( q * q ueues) removeQuerierConnection ( querierID string , now time . Time ) {
func ( q * tenantQ ueues) removeQuerierConnection ( querierID string , now time . Time ) {
info := q . queriers [ querierID ]
if info == nil || info . connections <= 0 {
panic ( "unexpected number of connections for querier" )
@ -227,7 +227,7 @@ func (q *queues) removeQuerierConnection(querierID string, now time.Time) {
info . disconnectedAt = now
}
func ( q * q ueues) removeQuerier ( querierID string ) {
func ( q * tenantQ ueues) removeQuerier ( querierID string ) {
delete ( q . queriers , querierID )
ix := sort . SearchStrings ( q . sortedQueriers , querierID )
@ -241,7 +241,7 @@ func (q *queues) removeQuerier(querierID string) {
}
// notifyQuerierShutdown records that a querier has sent notification about a graceful shutdown.
func ( q * q ueues) notifyQuerierShutdown ( querierID string ) {
func ( q * tenantQ ueues) notifyQuerierShutdown ( querierID string ) {
info := q . queriers [ querierID ]
if info == nil {
// The querier may have already been removed, so we just ignore it.
@ -261,7 +261,7 @@ func (q *queues) notifyQuerierShutdown(querierID string) {
// forgetDisconnectedQueriers removes all disconnected queriers that have gone since at least
// the forget delay. Returns the number of forgotten queriers.
func ( q * q ueues) forgetDisconnectedQueriers ( now time . Time ) int {
func ( q * tenantQ ueues) forgetDisconnectedQueriers ( now time . Time ) int {
// Nothing to do if the forget delay is disabled.
if q . forgetDelay == 0 {
return 0
@ -281,18 +281,18 @@ func (q *queues) forgetDisconnectedQueriers(now time.Time) int {
return forgotten
}
func ( q * q ueues) recomputeUserQueriers ( ) {
func ( q * tenantQ ueues) recomputeUserQueriers ( ) {
scratchpad := make ( [ ] string , 0 , len ( q . sortedQueriers ) )
for _ , uq := range q . userQ ueues {
uq . queriers = shuffleQueriersForUser ( uq . seed , uq . maxQueriers , q . sortedQueriers , scratchpad )
for _ , uq := range q . q ueues {
uq . queriers = shuffleQueriersForTenants ( uq . seed , uq . maxQueriers , q . sortedQueriers , scratchpad )
}
}
// shuffleQueriersForUser returns nil if queriersToSelect is 0 or there are not enough queriers to select from.
// shuffleQueriersForTenants returns nil if queriersToSelect is 0 or there are not enough queriers to select from.
// In that case *all* queriers should be used.
// Scratchpad is used for shuffling, to avoid new allocations. If nil, new slice is allocated.
func shuffleQueriersForUser ( userSeed int64 , queriersToSelect int , allSortedQueriers [ ] string , scratchpad [ ] string ) map [ string ] struct { } {
func shuffleQueriersForTenants ( userSeed int64 , queriersToSelect int , allSortedQueriers [ ] string , scratchpad [ ] string ) map [ string ] struct { } {
if queriersToSelect == 0 || len ( allSortedQueriers ) <= queriersToSelect {
return nil
}