Skip to content

✨ Priorityqueue: Optionally return items within a priority fairly #3261

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 1 commit into
base: main
Choose a base branch
from

Conversation

alvaroaleman
Copy link
Member

This change makes it possible for the priorityqueue to return items fairly across one or more fairness dimensions. These fairness dimensions are extracted from items using a configurable extractor func. Fairness is only ensured within a given priority, as the purpose of priorities is to return higher-priority items before lower-priority items.

An example use-case is to use the namespace as fairness dimension, which then ensures that one very busy namespace can not starve off other namespaces.

An example use-case for more than one dimension are multi-cluster controllers, where fairness should first be achieved across clusters and then across namespaces within each cluster.

By default, no extractor func is configured so this doesn't change any behavior. We can revisit this in the future.

Naively, the whole problem looks like it could be solved by sorting the items in the queue appropriately, but that doesn't really work because:

  • Most (all?) sorting algorithm assume that the order of two elements can be determined just by looking at those two elements, but for fairness we have to consider the items in front of the current elements as well as the items that we already handed out
  • We can not hand out locked items and have to ignore them for the purpose of fairness. This in turn means that whenever an item gets unlocked, we'd have to redo our sorting

This change solves the problem by introducing a fairQueue structure which holds all items that are ready to be handed out and in the highest priority bracket that has ready items. The priorityqueue then hands out items from its internal fairQueue and manages its content.

The fairQueue works by using a slice of all the fairness dinensions it has ever observed and a map of fairness dimension to item slice. Whenever it hands out an item, it iterates over this slice and checks the corresponding map for items until it found an item to hand out.

@k8s-ci-robot k8s-ci-robot added the cncf-cla: yes Indicates the PR's author has signed the CNCF CLA. label Jul 19, 2025
@k8s-ci-robot k8s-ci-robot requested a review from inteon July 19, 2025 19:19
@k8s-ci-robot
Copy link
Contributor

[APPROVALNOTIFIER] This PR is APPROVED

This pull-request has been approved by: alvaroaleman

The full list of commands accepted by this bot can be found here.

The pull request process is described here

Needs approval from an approver in each of these files:

Approvers can indicate their approval by writing /approve in a comment
Approvers can cancel approval by writing /approve cancel in a comment

@k8s-ci-robot k8s-ci-robot requested a review from troy0820 July 19, 2025 19:19
@k8s-ci-robot k8s-ci-robot added approved Indicates a PR has been approved by an approver from all required OWNERS files. size/XL Denotes a PR that changes 500-999 lines, ignoring generated files. labels Jul 19, 2025
@alvaroaleman
Copy link
Member Author

/hold

@k8s-ci-robot k8s-ci-robot added the do-not-merge/hold Indicates that a PR should not merge because someone has issued a /hold command. label Jul 19, 2025
@alvaroaleman alvaroaleman changed the title ✨ Priorityqueue: Optionally return items fairly ✨ Priorityqueue: Optionally return items within a priority fairly Jul 19, 2025
This change makes it possible for the priorityqueue to return items
fairly across one or more fairness dimensions. These fairness dimensions
are extracted from items using a configurable extractor func. Fairness
is only ensured within a given priority, as the purpose of priorities is
to return higher-priority items before lower-priority items.

An example use-case is to use the namespace as fairness dimension, which
then ensures that one very busy namespace can not starve off other
namespaces.

An example use-case for more than one dimension are multi-cluster
controllers, where fairness should first be achieved across clusters and
then across namespaces within each cluster.

By default, no extractor func is configured so this doesn't change any
behavior. We can revisit this in the future.

Naively, the whole problem looks like it could be solved by sorting the
items in the queue appropriately, but that doesn't really work because:

* Most (all?) sorting algorithm assume that the order of two elements
  can be determined just by looking at those two elements, but for
  fairness we have to consider the items in front of the current
  elements as well as the items that we already handed out
* We can not hand out locked items and have to ignore them for the
  purpose of fairness. This in turn means that whenever an item gets
  unlocked, we'd have to redo our sorting

This change solves the problem by introducing a `fairQueue` structure
which holds all items that are ready to be handed out and in the
highest priority bracket that has ready items. The priorityqueue then
hands out items from its internal `fairQueue` and manages its content.

The `fairQueue` works by using a slice of all the fairness dinensions
it has ever observed and a map of fairness dimension to item slice.
Whenever it hands out an item, it iterates over this slice and checks
the corresponding map for items until it found an item to hand out.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
approved Indicates a PR has been approved by an approver from all required OWNERS files. cncf-cla: yes Indicates the PR's author has signed the CNCF CLA. do-not-merge/hold Indicates that a PR should not merge because someone has issued a /hold command. size/XL Denotes a PR that changes 500-999 lines, ignoring generated files.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants