Commit d9b8fe78 authored by Sean McGivern's avatar Sean McGivern

Add tags to queue selector attributes

Tags are sets of transient annotations for workers. We will change them
more frequently than other worker attributes, and will remove them
completely at times.

For instance, we want to tag workers that require disk I/O. Once no
workers require disk I/O, workers will no longer have the tag indicating
this, but we'll still support the general tags concept.
parent 14822a68
This diff is collapsed.
...@@ -111,6 +111,14 @@ module WorkerAttributes ...@@ -111,6 +111,14 @@ module WorkerAttributes
1 1
end end
def tags(*values)
worker_attributes[:tags] = values
end
def get_tags
Array(worker_attributes[:tags])
end
protected protected
# Returns a worker attribute declared on this class or its parent class. # Returns a worker attribute declared on this class or its parent class.
......
---
title: Add tags to experimental queue selector attributes
merge_request: 32651
author:
type: added
...@@ -126,6 +126,8 @@ in a more general way using the following components: ...@@ -126,6 +126,8 @@ in a more general way using the following components:
### Available attributes ### Available attributes
- [Introduced](https://gitlab.com/gitlab-com/gl-infra/scalability/-/issues/261) in GitLab 13.1, `tags`.
From the [list of all available From the [list of all available
attributes](https://gitlab.com/gitlab-org/gitlab/-/blob/master/app/workers/all_queues.yml), attributes](https://gitlab.com/gitlab-org/gitlab/-/blob/master/app/workers/all_queues.yml),
`experimental_queue_selector` allows selecting of queues by the `experimental_queue_selector` allows selecting of queues by the
...@@ -147,11 +149,18 @@ following attributes: ...@@ -147,11 +149,18 @@ following attributes:
- `resource_boundary` - if the worker is bound by `cpu`, `memory`, or - `resource_boundary` - if the worker is bound by `cpu`, `memory`, or
`unknown`. For example, the `project_export` queue is memory bound as it has `unknown`. For example, the `project_export` queue is memory bound as it has
to load data in memory before saving it for export. to load data in memory before saving it for export.
- `tags` - short-lived annotations for workers. These are expected to frequently
change from release to release, and may be removed entirely.
`has_external_dependencies` is a boolean attribute: only the exact `has_external_dependencies` is a boolean attribute: only the exact
string `true` is considered true, and everything else is considered string `true` is considered true, and everything else is considered
false. false.
`tags` is a set, which means that `=` checks for intersecting sets, and
`!=` checks for disjoint sets. For example, `tags=a,b` selects queues
that have tags `a`, `b`, or both. `tags!=a,b` selects queues that have
neither of those tags.
### Available operators ### Available operators
`experimental_queue_selector` supports the following operators, listed `experimental_queue_selector` supports the following operators, listed
......
This diff is collapsed.
...@@ -14,8 +14,8 @@ module Gitlab ...@@ -14,8 +14,8 @@ module Gitlab
].compact.freeze ].compact.freeze
DEFAULT_WORKERS = [ DEFAULT_WORKERS = [
DummyWorker.new('default', weight: 1), DummyWorker.new('default', weight: 1, tags: []),
DummyWorker.new('mailers', weight: 2) DummyWorker.new('mailers', weight: 2, tags: [])
].map { |worker| Gitlab::SidekiqConfig::Worker.new(worker, ee: false) }.freeze ].map { |worker| Gitlab::SidekiqConfig::Worker.new(worker, ee: false) }.freeze
class << self class << self
......
...@@ -28,6 +28,7 @@ module Gitlab ...@@ -28,6 +28,7 @@ module Gitlab
has_external_dependencies: lambda { |value| value == 'true' }, has_external_dependencies: lambda { |value| value == 'true' },
name: :to_s, name: :to_s,
resource_boundary: :to_sym, resource_boundary: :to_sym,
tags: :to_sym,
urgency: :to_sym urgency: :to_sym
}.freeze }.freeze
...@@ -117,7 +118,11 @@ module Gitlab ...@@ -117,7 +118,11 @@ module Gitlab
raise UnknownPredicate.new("Unknown predicate: #{lhs}") unless values_block raise UnknownPredicate.new("Unknown predicate: #{lhs}") unless values_block
lambda { |queue| values.map(&values_block).include?(queue[lhs.to_sym]) } lambda do |queue|
comparator = Array(queue[lhs.to_sym]).to_set
values.map(&values_block).to_set.intersect?(comparator)
end
end end
end end
end end
......
...@@ -12,7 +12,8 @@ module Gitlab ...@@ -12,7 +12,8 @@ module Gitlab
urgency: :get_urgency, urgency: :get_urgency,
resource_boundary: :get_worker_resource_boundary, resource_boundary: :get_worker_resource_boundary,
idempotent: :idempotent?, idempotent: :idempotent?,
weight: :get_weight weight: :get_weight,
tags: :get_tags
}.freeze }.freeze
def initialize(queue, attributes = {}) def initialize(queue, attributes = {})
......
...@@ -6,7 +6,7 @@ module Gitlab ...@@ -6,7 +6,7 @@ module Gitlab
include Comparable include Comparable
attr_reader :klass attr_reader :klass
delegate :feature_category_not_owned?, :get_feature_category, delegate :feature_category_not_owned?, :get_feature_category, :get_tags,
:get_urgency, :get_weight, :get_worker_resource_boundary, :get_urgency, :get_weight, :get_worker_resource_boundary,
:idempotent?, :queue, :queue_namespace, :idempotent?, :queue, :queue_namespace,
:worker_has_external_dependencies?, :worker_has_external_dependencies?,
...@@ -52,7 +52,8 @@ module Gitlab ...@@ -52,7 +52,8 @@ module Gitlab
urgency: get_urgency, urgency: get_urgency,
resource_boundary: get_worker_resource_boundary, resource_boundary: get_worker_resource_boundary,
weight: get_weight, weight: get_weight,
idempotent: idempotent? idempotent: idempotent?,
tags: get_tags
} }
end end
......
...@@ -117,28 +117,32 @@ describe Gitlab::SidekiqConfig::CliMethods do ...@@ -117,28 +117,32 @@ describe Gitlab::SidekiqConfig::CliMethods do
feature_category: :category_a, feature_category: :category_a,
has_external_dependencies: false, has_external_dependencies: false,
urgency: :low, urgency: :low,
resource_boundary: :cpu resource_boundary: :cpu,
tags: [:no_disk_io, :git_access]
}, },
{ {
name: 'a:2', name: 'a:2',
feature_category: :category_a, feature_category: :category_a,
has_external_dependencies: false, has_external_dependencies: false,
urgency: :high, urgency: :high,
resource_boundary: :none resource_boundary: :none,
tags: [:git_access]
}, },
{ {
name: 'b', name: 'b',
feature_category: :category_b, feature_category: :category_b,
has_external_dependencies: true, has_external_dependencies: true,
urgency: :high, urgency: :high,
resource_boundary: :memory resource_boundary: :memory,
tags: [:no_disk_io]
}, },
{ {
name: 'c', name: 'c',
feature_category: :category_c, feature_category: :category_c,
has_external_dependencies: false, has_external_dependencies: false,
urgency: :throttled, urgency: :throttled,
resource_boundary: :memory resource_boundary: :memory,
tags: []
} }
] ]
end end
...@@ -177,6 +181,18 @@ describe Gitlab::SidekiqConfig::CliMethods do ...@@ -177,6 +181,18 @@ describe Gitlab::SidekiqConfig::CliMethods do
'resource_boundary=memory|resource_boundary=cpu' | %w(a b c) 'resource_boundary=memory|resource_boundary=cpu' | %w(a b c)
'resource_boundary!=memory,cpu' | %w(a:2) 'resource_boundary!=memory,cpu' | %w(a:2)
# tags
'tags=no_disk_io' | %w(a b)
'tags=no_disk_io,git_access' | %w(a a:2 b)
'tags=no_disk_io|tags=git_access' | %w(a a:2 b)
'tags=no_disk_io&tags=git_access' | %w(a)
'tags!=no_disk_io' | %w(a:2 c)
'tags!=no_disk_io,git_access' | %w(c)
'tags=unknown_tag' | []
'tags!=no_disk_io' | %w(a:2 c)
'tags!=no_disk_io,git_access' | %w(c)
'tags!=unknown_tag' | %w(a a:2 b c)
# combinations # combinations
'feature_category=category_a&urgency=high' | %w(a:2) 'feature_category=category_a&urgency=high' | %w(a:2)
'feature_category=category_a&urgency=high|feature_category=category_c' | %w(a:2 c) 'feature_category=category_a&urgency=high|feature_category=category_c' | %w(a:2 c)
......
...@@ -13,7 +13,8 @@ describe Gitlab::SidekiqConfig::Worker do ...@@ -13,7 +13,8 @@ describe Gitlab::SidekiqConfig::Worker do
get_worker_resource_boundary: attributes[:resource_boundary], get_worker_resource_boundary: attributes[:resource_boundary],
get_urgency: attributes[:urgency], get_urgency: attributes[:urgency],
worker_has_external_dependencies?: attributes[:has_external_dependencies], worker_has_external_dependencies?: attributes[:has_external_dependencies],
idempotent?: attributes[:idempotent] idempotent?: attributes[:idempotent],
get_tags: attributes[:tags]
) )
described_class.new(inner_worker, ee: false) described_class.new(inner_worker, ee: false)
...@@ -91,7 +92,8 @@ describe Gitlab::SidekiqConfig::Worker do ...@@ -91,7 +92,8 @@ describe Gitlab::SidekiqConfig::Worker do
urgency: :low, urgency: :low,
resource_boundary: :memory, resource_boundary: :memory,
weight: 2, weight: 2,
idempotent: true idempotent: true,
tags: []
} }
attributes_b = { attributes_b = {
...@@ -100,7 +102,8 @@ describe Gitlab::SidekiqConfig::Worker do ...@@ -100,7 +102,8 @@ describe Gitlab::SidekiqConfig::Worker do
urgency: :high, urgency: :high,
resource_boundary: :unknown, resource_boundary: :unknown,
weight: 3, weight: 3,
idempotent: false idempotent: false,
tags: [:no_disk_io]
} }
worker_a = create_worker(queue: 'a', **attributes_a) worker_a = create_worker(queue: 'a', **attributes_a)
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment