Skip to content

Commit 9ac2a4d

Browse files
authored
feat(flowcontrol): refine types and docs (#1191)
This commit improves the foundational `types` package by consolidating documentation and adding a safer default enum value in preparation for the new `FlowController` implementation. It also removes concepts related to displacement, which are out of scope for the initial release. Key changes: - The package-level `README.md` has been removed. Its content is now in a comprehensive GoDoc package comment in `doc.go`. This addresses reviewer feedback to co-locate documentation with the code it describes, reducing maintenance burden and preventing doc drift. - The package documentation has been rewritten to tell a clearer architectural narrative, explaining the request lifecycle through the lens of the `EnqueueAndWait` model. - The `ErrDisplaced` error and `QueueOutcomeEvictedDisplaced` outcome have been removed to align the types with the GA feature set. - A new `QueueOutcomeNotYetFinalized` enum value has been added. This serves as a safer, explicit zero-value for the `QueueOutcome` type, which is used by the new `ShardProcessor` to represent the initial state of a request before its lifecycle is complete.
1 parent 6cf8f31 commit 9ac2a4d

File tree

7 files changed

+103
-97
lines changed

7 files changed

+103
-97
lines changed

pkg/epp/flowcontrol/types/README.md

Lines changed: 0 additions & 33 deletions
This file was deleted.

pkg/epp/flowcontrol/types/doc.go

Lines changed: 33 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -14,9 +14,38 @@ See the License for the specific language governing permissions and
1414
limitations under the License.
1515
*/
1616

17-
// Package types defines the core data structures and service contracts for the Flow Control system.
17+
// Package types defines the fundamental data structures, interfaces, and errors that form the vocabulary of the Flow
18+
// Control system. It establishes the core data contracts for the request lifecycle, from initial submission to final,
19+
// reportable outcome.
1820
//
19-
// It establishes the "vocabulary" of the system, defining the objects that are passed between the main controller,
20-
// policies, and queue plugins. The central data model revolves around the lifecycle of a request, which is
21-
// progressively wrapped in interfaces that provide an enriched, read-only view of its state.
21+
// # The Request Lifecycle
22+
//
23+
// The primary entry point to the `controller.FlowController` is the synchronous `EnqueueAndWait` method. The types in
24+
// this package are designed to model a request's journey through this blocking call.
25+
//
26+
// 1. A client first constructs an object that implements the `FlowControlRequest` interface. This is the "raw" input,
27+
// containing the essential data for the request, such as its `FlowID` and `ByteSize`. This object is passed to
28+
// `EnqueueAndWait`.
29+
//
30+
// 2. Internally, the `controller.FlowController` wraps the `FlowControlRequest` in an object that implements the
31+
// `QueueItemAccessor` interface. This is an enriched, read-only view used by policies and queues. It adds internal
32+
// metadata like `EnqueueTime` and `EffectiveTTL`.
33+
//
34+
// 3. If the request is accepted and added to a `framework.SafeQueue`, the queue creates a `QueueItemHandle`. This is
35+
// an opaque, queue-specific handle that the controller uses to perform targeted operations (like removal) without
36+
// needing to know the queue's internal implementation details.
37+
//
38+
// 4. The `EnqueueAndWait` method blocks until the request reaches a terminal state. This final state is reported using
39+
// a `QueueOutcome` enum and a corresponding `error`.
40+
//
41+
// # Final State Reporting: Outcomes and Errors
42+
//
43+
// This combination of a concise enum and a detailed error provides a clear, machine-inspectable result.
44+
//
45+
// - `QueueOutcome`: A low-cardinality enum summarizing the final result (e.g., `QueueOutcomeDispatched`,
46+
// `QueueOutcomeRejectedCapacity`). This is ideal for metrics.
47+
//
48+
// - `error`: For any non-dispatch outcome, a specific sentinel error is returned. These are nested to provide rich
49+
// context. Callers can use `errors.Is()` to check for the general class of failure (`ErrRejected` or `ErrEvicted`),
50+
// and then unwrap the error to find the specific cause (e.g., `ErrQueueAtCapacity` or `ErrTTLExpired`).
2251
package types

pkg/epp/flowcontrol/types/errors.go

Lines changed: 22 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -20,39 +20,44 @@ import (
2020
"errors"
2121
)
2222

23-
// --- High Level Queue Outcome Errors ---
23+
// --- High-Level Outcome Errors ---
24+
2425
var (
25-
// ErrRejected is a sentinel error indicating a request was rejected by the Flow Controller *before* being formally
26-
// enqueued. Errors returned by `FlowController.EnqueueAndWait()` that signify pre-queue rejection will wrap this
27-
// error.
26+
// ErrRejected is a sentinel error indicating a request was rejected by the `controller.FlowController` *before* being
27+
// formally enqueued. Errors returned by `FlowController.EnqueueAndWait()` that signify pre-queue rejection will wrap
28+
// this error.
29+
//
2830
// Callers should use `errors.Is(err, ErrRejected)` to check for this general class of failure.
2931
ErrRejected = errors.New("request rejected pre-queue")
3032

3133
// ErrEvicted is a sentinel error indicating a request was removed from a queue *after* being successfully enqueued,
32-
// but for reasons other than successful dispatch (e.g., TTL expiry, displacement).
33-
// Errors returned by `FlowController.EnqueueAndWait()` that signify post-queue eviction will wrap this error.
34+
// but for reasons other than successful dispatch (e.g., TTL expiry, displacement). Errors returned by
35+
// `FlowController.EnqueueAndWait()` that signify post-queue eviction will wrap this error.
36+
//
3437
// Callers should use `errors.Is(err, ErrEvicted)` to check for this general class of failure.
3538
ErrEvicted = errors.New("request evicted from queue")
3639
)
3740

3841
// --- Pre-Enqueue Rejection Errors ---
39-
// Errors that can occur before a request is formally added to a `framework.SafeQueue`.
40-
// When returned by `FlowController.EnqueueAndWait()`, these specific errors will typically be wrapped by `ErrRejected`.
42+
43+
// The following errors can occur before a request is formally added to a `framework.SafeQueue`. When returned by
44+
// `FlowController.EnqueueAndWait()`, these specific errors will typically be wrapped by `ErrRejected`.
4145
var (
4246
// ErrNilRequest indicates that a nil `types.FlowControlRequest` was provided.
4347
ErrNilRequest = errors.New("FlowControlRequest cannot be nil")
4448

4549
// ErrFlowIDEmpty indicates that a flow ID was empty when one was required.
4650
ErrFlowIDEmpty = errors.New("flow ID cannot be empty")
4751

48-
// ErrQueueAtCapacity indicates that a request could not be enqueued because queue capacity limits were met and
49-
// displacement (if applicable) failed to make space.
52+
// ErrQueueAtCapacity indicates that a request could not be enqueued because queue capacity limits were met.
5053
ErrQueueAtCapacity = errors.New("queue at capacity and displacement failed to make space")
5154
)
5255

5356
// --- Post-Enqueue Eviction Errors ---
54-
// Errors that occur when a request, already in a `framework.SafeQueue`, is removed for reasons other than dispatch.
55-
// When returned by `FlowController.EnqueueAndWait()`, these specific errors will typically be wrapped by `ErrEvicted`.
57+
58+
// The following errors occur when a request, already in a `framework.SafeQueue`, is removed for reasons other than
59+
// dispatch. When returned by `FlowController.EnqueueAndWait()`, these specific errors will typically be wrapped by
60+
// `ErrEvicted`.
5661
var (
5762
// ErrTTLExpired indicates a request was evicted from a queue because its effective Time-To-Live expired.
5863
ErrTTLExpired = errors.New("request TTL expired")
@@ -61,17 +66,14 @@ var (
6166
// `FlowControlRequest.Context()`) was cancelled. This error typically wraps the underlying `context.Canceled` or
6267
// `context.DeadlineExceeded` error.
6368
ErrContextCancelled = errors.New("request context cancelled")
64-
65-
// ErrDisplaced indicates a request was evicted from a queue because it was chosen as a victim by a displacement
66-
// policy to make space for another request.
67-
ErrDisplaced = errors.New("request displaced")
6869
)
6970

70-
// --- General FlowController Errors ---
71-
// General runtime errors for the Flow Controller.
71+
// --- General `controller.FlowController` Errors ---
72+
7273
var (
73-
// ErrFlowControllerShutdown indicates that an operation could not complete or an item was evicted because the Flow
74-
// Controller is shutting down or has stopped.
74+
// ErrFlowControllerShutdown indicates that an operation could not complete or an item was evicted because the
75+
// `controller.FlowController` is shutting down or has stopped.
76+
//
7577
// When returned by `FlowController.EnqueueAndWait()`, this will be wrapped by `ErrRejected` (if rejection happens
7678
// before internal queuing) or `ErrEvicted` (if eviction happens after internal queuing).
7779
ErrFlowControllerShutdown = errors.New("FlowController is shutting down")

pkg/epp/flowcontrol/types/flow.go

Lines changed: 5 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -16,17 +16,13 @@ limitations under the License.
1616

1717
package types
1818

19-
// FlowSpecification defines the configuration of a logical flow, encapsulating its identity and registered priority.
20-
//
21-
// It acts as the registration key for a flow within the `contracts.FlowRegistry`.
19+
// FlowSpecification defines the complete configuration for a single logical flow.
20+
// It is the data contract used by the `contracts.FlowRegistry` to create and manage the lifecycle of queues and
21+
// policies.
2222
type FlowSpecification struct {
23-
// ID returns the unique name or identifier for this logical flow, corresponding to the value from
24-
// `FlowControlRequest.FlowID()`.
23+
// ID is the unique identifier for this flow (e.g., model name, tenant ID).
2524
ID string
2625

27-
// Priority returns the numerical priority level currently associated with this flow within the
28-
// `contracts.FlowRegistry`.
29-
//
30-
// Convention: Lower numerical values indicate higher priority.
26+
// Priority is the numerical priority level for this flow. Lower values indicate higher priority.
3127
Priority uint
3228
}

pkg/epp/flowcontrol/types/mocks/mocks.go

Lines changed: 19 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,19 @@ type MockFlowControlRequest struct {
3434
IDV string
3535
}
3636

37+
// NewMockFlowControlRequest creates a new `MockFlowControlRequest` instance.
38+
func NewMockFlowControlRequest(byteSize uint64, id, flowID string, ctx context.Context) *MockFlowControlRequest {
39+
if ctx == nil {
40+
ctx = context.Background()
41+
}
42+
return &MockFlowControlRequest{
43+
ByteSizeV: byteSize,
44+
IDV: id,
45+
FlowIDV: flowID,
46+
Ctx: ctx,
47+
}
48+
}
49+
3750
func (m *MockFlowControlRequest) Context() context.Context { return m.Ctx }
3851
func (m *MockFlowControlRequest) FlowID() string { return m.FlowIDV }
3952
func (m *MockFlowControlRequest) ByteSize() uint64 { return m.ByteSizeV }
@@ -82,12 +95,12 @@ var _ types.QueueItemAccessor = &MockQueueItemAccessor{}
8295
func NewMockQueueItemAccessor(byteSize uint64, reqID, flowID string) *MockQueueItemAccessor {
8396
return &MockQueueItemAccessor{
8497
EnqueueTimeV: time.Now(),
85-
OriginalRequestV: &MockFlowControlRequest{
86-
IDV: reqID,
87-
FlowIDV: flowID,
88-
ByteSizeV: byteSize,
89-
Ctx: context.Background(),
90-
},
98+
OriginalRequestV: NewMockFlowControlRequest(
99+
byteSize,
100+
reqID,
101+
flowID,
102+
context.Background(),
103+
),
91104
HandleV: &MockQueueItemHandle{},
92105
}
93106
}

pkg/epp/flowcontrol/types/outcomes.go

Lines changed: 14 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -18,30 +18,33 @@ package types
1818

1919
import "strconv"
2020

21-
// QueueOutcome represents the high-level final state of a request's lifecycle within the Flow Controller.
21+
// QueueOutcome represents the high-level final state of a request's lifecycle within the `controller.FlowController`.
2222
//
2323
// It is returned by `FlowController.EnqueueAndWait()` along with a corresponding error. This enum is designed to be a
2424
// low-cardinality label ideal for metrics, while the error provides fine-grained details for non-dispatched outcomes.
2525
type QueueOutcome int
2626

2727
const (
28-
// QueueOutcomeDispatched indicates the request was successfully processed by the Flow Controller and unblocked for
29-
// the caller to proceed.
28+
// QueueOutcomeNotYetFinalized indicates the request has not yet been finalized by the `controller.FlowController`.
29+
// This is an internal default value and should never be returned by `FlowController.EnqueueAndWait()`.
30+
QueueOutcomeNotYetFinalized QueueOutcome = iota
31+
32+
// QueueOutcomeDispatched indicates the request was successfully processed by the `controller.FlowController` and
33+
// unblocked for the caller to proceed.
3034
// The associated error from `FlowController.EnqueueAndWait()` will be nil.
31-
QueueOutcomeDispatched QueueOutcome = iota
35+
QueueOutcomeDispatched
3236

3337
// --- Pre-Enqueue Rejection Outcomes (request never entered a `framework.SafeQueue`) ---
3438
// For these outcomes, the error from `FlowController.EnqueueAndWait()` will wrap `ErrRejected`.
3539

36-
// QueueOutcomeRejectedCapacity indicates rejection because queue capacity limits were met and displacement (if
37-
// applicable) failed to make space.
40+
// QueueOutcomeRejectedCapacity indicates rejection because queue capacity limits were met.
3841
// The associated error will wrap `ErrQueueAtCapacity` (and `ErrRejected`).
3942
QueueOutcomeRejectedCapacity
4043

4144
// QueueOutcomeRejectedOther indicates rejection for reasons other than capacity before the request was formally
4245
// enqueued.
4346
// The specific underlying cause can be determined from the associated error (e.g., a nil request, an unregistered
44-
// flow ID, or a controller shutdown), which will be wrapped by `ErrRejected`.
47+
// flow ID, or controller shutdown), which will be wrapped by `ErrRejected`.
4548
QueueOutcomeRejectedOther
4649

4750
// --- Post-Enqueue Eviction Outcomes (request was in a `framework.SafeQueue` but not dispatched) ---
@@ -57,21 +60,18 @@ const (
5760
// `context.DeadlineExceeded` error) (and `ErrEvicted`).
5861
QueueOutcomeEvictedContextCancelled
5962

60-
// QueueOutcomeEvictedDisplaced indicates eviction from a queue to make space for another request due to a
61-
// displacement policy.
62-
// The associated error will wrap `ErrDisplaced` (and `ErrEvicted`).
63-
QueueOutcomeEvictedDisplaced
64-
6563
// QueueOutcomeEvictedOther indicates eviction from a queue for reasons not covered by more specific eviction
6664
// outcomes.
67-
// The specific underlying cause can be determined from the associated error (e.g., a controller shutdown while the
68-
// item was queued), which will be wrapped by `ErrEvicted`.
65+
// The specific underlying cause can be determined from the associated error (e.g., controller shutdown while the item
66+
// was queued), which will be wrapped by `ErrEvicted`.
6967
QueueOutcomeEvictedOther
7068
)
7169

7270
// String returns a human-readable string representation of the QueueOutcome.
7371
func (o QueueOutcome) String() string {
7472
switch o {
73+
case QueueOutcomeNotYetFinalized:
74+
return "NotYetFinalized"
7575
case QueueOutcomeDispatched:
7676
return "Dispatched"
7777
case QueueOutcomeRejectedCapacity:
@@ -82,8 +82,6 @@ func (o QueueOutcome) String() string {
8282
return "EvictedTTL"
8383
case QueueOutcomeEvictedContextCancelled:
8484
return "EvictedContextCancelled"
85-
case QueueOutcomeEvictedDisplaced:
86-
return "EvictedDisplaced"
8785
case QueueOutcomeEvictedOther:
8886
return "EvictedOther"
8987
default:

pkg/epp/flowcontrol/types/request.go

Lines changed: 10 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -21,8 +21,8 @@ import (
2121
"time"
2222
)
2323

24-
// FlowControlRequest is the contract for an incoming request submitted to the Flow Controller. It represents the "raw"
25-
// user-provided data and context for a single unit of work.
24+
// FlowControlRequest is the contract for an incoming request submitted to the `controller.FlowController`. It
25+
// represents the "raw" user-provided data and context for a single unit of work.
2626
//
2727
// An object implementing this interface is the primary input to `FlowController.EnqueueAndWait()`. The controller then
2828
// wraps this object with its own internal structures (which implement `QueueItemAccessor`) to manage the request's
@@ -34,12 +34,12 @@ type FlowControlRequest interface {
3434
Context() context.Context
3535

3636
// FlowID returns the unique identifier for the flow this request belongs to (e.g., model name, tenant ID). The
37-
// `controller.FlowController` uses this ID, in conjunction with the flow's registered priority, to look up the
38-
// active `contracts.ManagedQueue` from the `contracts.FlowRegistry`'s `contracts.RegistryShard`.
37+
// `controller.FlowController` uses this ID to look up the active `contracts.ManagedQueue` and configured
38+
// `framework.IntraFlowDispatchPolicy` from a `contracts.RegistryShard`.
3939
FlowID() string
4040

4141
// ByteSize returns the request's size in bytes (e.g., prompt size). This is used by the `controller.FlowController`
42-
// and for managing byte-based capacity limits and for `contracts.FlowRegistry` statistics.
42+
// for managing byte-based capacity limits and for `contracts.FlowRegistry` statistics.
4343
ByteSize() uint64
4444

4545
// InitialEffectiveTTL returns the suggested Time-To-Live for this request.
@@ -78,11 +78,12 @@ type QueueItemHandle interface {
7878
IsInvalidated() bool
7979
}
8080

81-
// QueueItemAccessor provides the internal, enriched, read-only view of a request being managed within the Flow
82-
// Controller's queues. It is the primary interface through which `framework.SafeQueue` implementations and policy
83-
// plugins interact with request data and its associated flow control metadata.
81+
// QueueItemAccessor provides the internal, enriched, read-only view of a request being managed within the
82+
// controller.FlowController`'s queues. It is the primary interface through which `framework.SafeQueue` implementations
83+
// and policy plugins interact with request data and its associated flow control metadata.
8484
//
85-
// The Flow Controller creates an object that implements this interface by wrapping an incoming `FlowControlRequest`.
85+
// The `controller.FlowController` creates an object that implements this interface by wrapping an incoming
86+
// `FlowControlRequest`.
8687
type QueueItemAccessor interface {
8788
// OriginalRequest returns the underlying `FlowControlRequest` that this accessor provides a view of.
8889
// This method serves as an escape hatch, allowing policies or components that are aware of specific

0 commit comments

Comments
 (0)