Rename LeafQueue to TreeQueue (#8856)

**What this PR does / why we need it**:

`TreeQueue` is the semantically more correct term for this type of queue.

Signed-off-by: Christian Haudum <christian.haudum@gmail.com>
pull/8886/head
Christian Haudum 2 years ago committed by GitHub
parent 4721d7efd3
commit 9844fad8b4
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
  1. 7
      pkg/scheduler/queue/mapping.go
  2. 10
      pkg/scheduler/queue/mapping_test.go
  3. 11
      pkg/scheduler/queue/tenant_queues.go
  4. 36
      pkg/scheduler/queue/treequeue.go
  5. 10
      pkg/scheduler/queue/treequeue_test.go

@ -4,13 +4,6 @@ import (
"github.com/pkg/errors"
)
type Mapable interface {
*tenantQueue | *LeafQueue
// https://github.com/golang/go/issues/48522#issuecomment-924348755
Pos() QueueIndex
SetPos(index QueueIndex)
}
var ErrOutOfBounds = errors.New("queue index out of bounds")
var empty = string([]byte{byte(0)})

@ -10,20 +10,20 @@ func TestQueueMapping(t *testing.T) {
// Individual sub-tests in this test case are reflecting a scenario and need
// to be executed in sequential order.
m := &Mapping[*LeafQueue]{}
m := &Mapping[*TreeQueue]{}
m.Init(16)
require.Equal(t, m.Len(), 0)
t.Run("put item to mapping", func(t *testing.T) {
q1 := newLeafQueue(10, "queue-1")
q1 := newTreeQueue(10, "queue-1")
m.Put(q1.Name(), q1)
require.Equal(t, 1, m.Len())
require.Equal(t, []string{"queue-1"}, m.Keys())
})
t.Run("insert order is preserved if there is no empty slot", func(t *testing.T) {
q2 := newLeafQueue(10, "queue-2")
q2 := newTreeQueue(10, "queue-2")
m.Put(q2.Name(), q2)
require.Equal(t, 2, m.Len())
require.Equal(t, []string{"queue-1", "queue-2"}, m.Keys())
@ -33,14 +33,14 @@ func TestQueueMapping(t *testing.T) {
ok := m.Remove("queue-1")
require.True(t, ok)
require.Equal(t, 1, m.Len())
q3 := newLeafQueue(10, "queue-3")
q3 := newTreeQueue(10, "queue-3")
m.Put(q3.Name(), q3)
require.Equal(t, 2, m.Len())
require.Equal(t, []string{"queue-3", "queue-2"}, m.Keys())
})
t.Run("insert order is preserved across keys and values", func(t *testing.T) {
q4 := newLeafQueue(10, "queue-4")
q4 := newTreeQueue(10, "queue-4")
m.Put(q4.Name(), q4)
require.Equal(t, 3, m.Len())
for idx, v := range m.Values() {

@ -50,8 +50,15 @@ type Queue interface {
Len() int
}
type Mapable interface {
*tenantQueue | *TreeQueue
// https://github.com/golang/go/issues/48522#issuecomment-924348755
Pos() QueueIndex
SetPos(index QueueIndex)
}
type tenantQueue struct {
*LeafQueue
*TreeQueue
// 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.
@ -102,7 +109,7 @@ func (q *tenantQueues) getOrAddQueue(tenant string, path []string, maxQueriers i
uq = &tenantQueue{
seed: util.ShuffleShardSeed(tenant, ""),
}
uq.LeafQueue = newLeafQueue(q.maxUserQueueSize, tenant)
uq.TreeQueue = newTreeQueue(q.maxUserQueueSize, tenant)
q.mapping.Put(tenant, uq)
}

@ -7,10 +7,10 @@ import (
type QueuePath []string //nolint:revive
// LeafQueue is an hierarchical queue implementation where each sub-queue
// TreeQueue is an hierarchical queue implementation where each sub-queue
// has the same guarantees to be chosen from.
// Each queue has also a local queue, which gets chosen with equal preference as the sub-queues.
type LeafQueue struct {
type TreeQueue struct {
// local queue
ch RequestChannel
// index of where this item is located in the mapping
@ -18,18 +18,18 @@ type LeafQueue struct {
// index of the sub-queues
current QueueIndex
// mapping for sub-queues
mapping *Mapping[*LeafQueue]
mapping *Mapping[*TreeQueue]
// name of the queue
name string
// maximum queue size of the local queue
size int
}
// newLeafQueue creates a new LeafQueue instance
func newLeafQueue(size int, name string) *LeafQueue {
m := &Mapping[*LeafQueue]{}
// newTreeQueue creates a new TreeQueue instance
func newTreeQueue(size int, name string) *TreeQueue {
m := &Mapping[*TreeQueue]{}
m.Init(64) // TODO(chaudum): What is a good initial value?
return &LeafQueue{
return &TreeQueue{
ch: make(RequestChannel, size),
pos: StartIndexWithLocalQueue,
current: StartIndexWithLocalQueue,
@ -40,7 +40,7 @@ func newLeafQueue(size int, name string) *LeafQueue {
}
// add recursively adds queues based on given path
func (q *LeafQueue) add(path QueuePath) *LeafQueue {
func (q *TreeQueue) add(path QueuePath) *TreeQueue {
if len(path) == 0 {
return q
}
@ -52,22 +52,22 @@ func (q *LeafQueue) add(path QueuePath) *LeafQueue {
return queue.add(remaining)
}
func (q *LeafQueue) getOrCreate(name string) (subq *LeafQueue, created bool) {
func (q *TreeQueue) getOrCreate(name string) (subq *TreeQueue, created bool) {
subq = q.mapping.GetByKey(name)
if subq == nil {
subq = newLeafQueue(q.size, name)
subq = newTreeQueue(q.size, name)
created = true
}
return subq, created
}
// Chan implements Queue
func (q *LeafQueue) Chan() RequestChannel {
func (q *TreeQueue) Chan() RequestChannel {
return q.ch
}
// Dequeue implements Queue
func (q *LeafQueue) Dequeue() Request {
func (q *TreeQueue) Dequeue() Request {
var item Request
// shortcut of there are not sub-queues
@ -111,14 +111,14 @@ func (q *LeafQueue) Dequeue() Request {
}
// Name implements Queue
func (q *LeafQueue) Name() string {
func (q *TreeQueue) Name() string {
return q.name
}
// Len implements Queue
// It returns the length of the local queue and all sub-queues.
// This may be expensive depending on the size of the queue tree.
func (q *LeafQueue) Len() int {
func (q *TreeQueue) Len() int {
count := len(q.ch)
for _, subq := range q.mapping.Values() {
count += subq.Len()
@ -127,20 +127,20 @@ func (q *LeafQueue) Len() int {
}
// Index implements Mapable
func (q *LeafQueue) Pos() QueueIndex {
func (q *TreeQueue) Pos() QueueIndex {
return q.pos
}
// Index implements Mapable
func (q *LeafQueue) SetPos(index QueueIndex) {
func (q *TreeQueue) SetPos(index QueueIndex) {
q.pos = index
}
// String makes the queue printable
func (q *LeafQueue) String() string {
func (q *TreeQueue) String() string {
sb := &strings.Builder{}
sb.WriteString("{")
fmt.Fprintf(sb, "name=%s, len=%d/%d, leafs=[", q.Name(), q.Len(), cap(q.ch))
fmt.Fprintf(sb, "name=%s, len=%d/%d, children=[", q.Name(), q.Len(), cap(q.ch))
subqs := q.mapping.Values()
for i, m := range subqs {
sb.WriteString(m.String())

@ -14,13 +14,13 @@ func r(id int) *dummyRequest {
return &dummyRequest{id}
}
func TestLeafQueue(t *testing.T) {
func TestTreeQueue(t *testing.T) {
t.Run("add sub queues recursively", func(t *testing.T) {
pathA := QueuePath([]string{"l0", "l1", "l3"})
pathB := QueuePath([]string{"l0", "l2", "l3"})
q := newLeafQueue(1, "root")
q := newTreeQueue(1, "root")
require.NotNil(t, q)
require.Equal(t, "root", q.Name())
require.Equal(t, 0, q.Len())
@ -58,7 +58,7 @@ func TestLeafQueue(t *testing.T) {
QueuePath([]string{"c", "c1", "c11"}),
}
q := newLeafQueue(10, "root")
q := newTreeQueue(10, "root")
require.NotNil(t, q)
for _, p := range paths {
q.add(p)
@ -116,7 +116,7 @@ func TestLeafQueue(t *testing.T) {
QueuePath([]string{"c"}),
}
q := newLeafQueue(10, "root")
q := newTreeQueue(10, "root")
require.NotNil(t, q)
for _, p := range paths {
q.add(p)
@ -150,7 +150,7 @@ func TestLeafQueue(t *testing.T) {
})
t.Run("empty sub-queues are removed", func(t *testing.T) {
q := newLeafQueue(10, "root")
q := newTreeQueue(10, "root")
q.add(QueuePath{"a"})
q.add(QueuePath{"b"})
Loading…
Cancel
Save