forked from llm-d/llm-d-router
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathlistqueue.go
More file actions
215 lines (178 loc) · 6.71 KB
/
Copy pathlistqueue.go
File metadata and controls
215 lines (178 loc) · 6.71 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
/*
Copyright 2025 The Kubernetes Authors.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
// Package listqueue provides a high-performance, concurrent-safe FIFO (First-In, First-Out) implementation of the
// SafeQueue based on the standard library's `container/list`.
package queue
import (
"container/list"
"sync"
"sync/atomic"
"github.com/llm-d/llm-d-router/pkg/epp/flowcontrol/contracts"
"github.com/llm-d/llm-d-router/pkg/epp/framework/interface/flowcontrol"
)
// ListQueueName is the name of the list-based queue implementation.
//
// This queue provides a high-performance, low-overhead implementation based on a standard `container/list`.
// It advertises the `CapabilityFIFO`.
//
// # Behavioral Guarantees
//
// The core guarantee of this queue is strict physical First-In, First-Out (FIFO) ordering. It processes items in the
// exact order they are added to the queue on a specific shard.
//
// # Performance and Trade-offs
//
// Because the physical insertion order may not match a request's logical arrival time (due to the
// `controller.FlowController`'s internal "bounce-and-retry" mechanic), this queue provides an*approximate FCFS behavior
// from a system-wide perspective.
//
// Given that true end-to-end ordering is non-deterministic in a distributed system, this high-performance queue is the
// recommended default for most FCFS-like policies. It prioritizes throughput and efficiency, which aligns with the
// primary goal of the Flow Control system.
//
// For workloads that require the strictest possible logical-time ordering this layer can provide, explicitly using a
// queue that supports `CapabilityPriorityConfigurable` is the appropriate choice.
const ListQueueName = "ListQueue"
func init() {
MustRegisterQueue(RegisteredQueueName(ListQueueName),
func(_ flowcontrol.OrderingPolicy) (contracts.SafeQueue, error) {
// The list queue is a simple FIFO queue and does not use an ordering policy.
return newListQueue(), nil
})
}
// listQueue is the internal implementation of the ListQueue.
// See the documentation for the exported `ListQueueName` constant for detailed user-facing information.
type listQueue struct {
requests *list.List
byteSize atomic.Uint64
mu sync.RWMutex
}
// listItemHandle is the concrete type for `flowcontrol.QueueItemHandle` used by `listQueue`.
// It wraps the `list.Element` and includes a pointer to the owning `listQueue` for validation.
type listItemHandle struct {
element *list.Element
owner *listQueue
isInvalidated bool
}
// Handle returns the underlying queue-specific raw handle.
func (lh *listItemHandle) Handle() any {
return lh.element
}
// Invalidate marks this handle instance as no longer valid for future operations.
func (lh *listItemHandle) Invalidate() {
lh.isInvalidated = true
}
// IsInvalidated returns true if this handle instance has been marked as invalid.
func (lh *listItemHandle) IsInvalidated() bool {
return lh.isInvalidated
}
var _ flowcontrol.QueueItemHandle = &listItemHandle{}
// newListQueue creates a new `listQueue` instance.
func newListQueue() *listQueue {
return &listQueue{
requests: list.New(),
}
}
// --- SafeQueue Interface Implementation ---
// Add enqueues an item to the back of the list.
func (lq *listQueue) Add(item flowcontrol.QueueItemAccessor) {
lq.mu.Lock()
defer lq.mu.Unlock()
element := lq.requests.PushBack(item)
lq.byteSize.Add(item.OriginalRequest().ByteSize())
item.SetHandle(&listItemHandle{element: element, owner: lq})
}
// Remove removes an item identified by the given handle from the queue.
func (lq *listQueue) Remove(handle flowcontrol.QueueItemHandle) (flowcontrol.QueueItemAccessor, error) {
lq.mu.Lock()
defer lq.mu.Unlock()
if handle == nil || handle.IsInvalidated() {
return nil, contracts.ErrInvalidQueueItemHandle
}
lh, ok := handle.(*listItemHandle)
if !ok {
return nil, contracts.ErrInvalidQueueItemHandle
}
if lh.owner != lq {
return nil, contracts.ErrQueueItemNotFound
}
item := lh.element.Value.(flowcontrol.QueueItemAccessor)
lq.requests.Remove(lh.element)
lq.byteSize.Add(^item.OriginalRequest().ByteSize() + 1) // Atomic subtraction
handle.Invalidate()
return item, nil
}
// Cleanup removes items from the queue that satisfy the predicate.
func (lq *listQueue) Cleanup(predicate contracts.PredicateFunc) (cleanedItems []flowcontrol.QueueItemAccessor) {
lq.mu.Lock()
defer lq.mu.Unlock()
var removedItems []flowcontrol.QueueItemAccessor
var next *list.Element
for e := lq.requests.Front(); e != nil; e = next {
next = e.Next() // Get next before potentially removing e
item := e.Value.(flowcontrol.QueueItemAccessor)
if predicate(item) {
lq.requests.Remove(e)
lq.byteSize.Add(^item.OriginalRequest().ByteSize() + 1) // Atomic subtraction
if itemHandle := item.Handle(); itemHandle != nil {
itemHandle.Invalidate()
}
removedItems = append(removedItems, item)
}
}
return removedItems
}
// Drain removes all items from the queue and returns them.
func (lq *listQueue) Drain() (removedItems []flowcontrol.QueueItemAccessor) {
lq.mu.Lock()
defer lq.mu.Unlock()
removedItems = make([]flowcontrol.QueueItemAccessor, 0, lq.requests.Len())
for e := lq.requests.Front(); e != nil; e = e.Next() {
item := e.Value.(flowcontrol.QueueItemAccessor)
removedItems = append(removedItems, item)
if handle := item.Handle(); handle != nil {
handle.Invalidate()
}
}
lq.requests.Init()
lq.byteSize.Store(0)
return removedItems
}
// Name returns the name of the queue.
func (lq *listQueue) Name() string {
return ListQueueName
}
// Capabilities returns the capabilities of the queue.
func (lq *listQueue) Capabilities() []flowcontrol.QueueCapability {
return []flowcontrol.QueueCapability{flowcontrol.CapabilityFIFO}
}
// Len returns the number of items in the queue.
func (lq *listQueue) Len() int {
lq.mu.RLock()
defer lq.mu.RUnlock()
return lq.requests.Len()
}
// ByteSize returns the total byte size of all items in the queue.
func (lq *listQueue) ByteSize() uint64 {
return lq.byteSize.Load()
}
// Peek returns the item at the front of the queue without removing it.
func (lq *listQueue) Peek() flowcontrol.QueueItemAccessor {
lq.mu.RLock()
defer lq.mu.RUnlock()
if lq.requests.Len() == 0 {
return nil
}
element := lq.requests.Front()
return element.Value.(flowcontrol.QueueItemAccessor)
}