summaryrefslogtreecommitdiff
path: root/app/workers/concerns/worker_attributes.rb
blob: 55feba673c4e9b506964a994705eee0547e3f926 (plain)
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
# frozen_string_literal: true

module WorkerAttributes
  extend ActiveSupport::Concern

  # Resource boundaries that workers can declare through the
  # `worker_resource_boundary` attribute
  VALID_RESOURCE_BOUNDARIES = [:memory, :cpu, :unknown].freeze

  NAMESPACE_WEIGHTS = {
    auto_devops: 2,
    auto_merge: 3,
    chaos: 2,
    deployment: 3,
    mail_scheduler: 2,
    notifications: 2,
    pipeline_cache: 3,
    pipeline_creation: 4,
    pipeline_default: 3,
    pipeline_hooks: 2,
    pipeline_processing: 5,

    # EE-specific
    epics: 2,
    incident_management: 2,
    security_scans: 2
  }.stringify_keys.freeze

  class_methods do
    def feature_category(value)
      raise "Invalid category. Use `feature_category_not_owned!` to mark a worker as not owned" if value == :not_owned

      worker_attributes[:feature_category] = value
    end

    # Special case: mark this work as not associated with a feature category
    # this should be used for cross-cutting concerns, such as mailer workers.
    def feature_category_not_owned!
      worker_attributes[:feature_category] = :not_owned
    end

    def get_feature_category
      get_worker_attribute(:feature_category)
    end

    def feature_category_not_owned?
      get_worker_attribute(:feature_category) == :not_owned
    end

    # This should be set for jobs that need to be run immediately, or, if
    # they are delayed, risk creating inconsistencies in the application
    # that could being perceived by the user as incorrect behavior
    # (ie, a bug)
    # See doc/development/sidekiq_style_guide.md#Latency-Sensitive-Jobs
    # for details
    def latency_sensitive_worker!
      worker_attributes[:latency_sensitive] = true
    end

    # Returns a truthy value if the worker is latency sensitive.
    # See doc/development/sidekiq_style_guide.md#Latency-Sensitive-Jobs
    # for details
    def latency_sensitive_worker?
      worker_attributes[:latency_sensitive]
    end

    # Set this attribute on a job when it will call to services outside of the
    # application, such as 3rd party applications, other k8s clusters etc See
    # doc/development/sidekiq_style_guide.md#Jobs-with-External-Dependencies for
    # details
    def worker_has_external_dependencies!
      worker_attributes[:external_dependencies] = true
    end

    # Returns a truthy value if the worker has external dependencies.
    # See doc/development/sidekiq_style_guide.md#Jobs-with-External-Dependencies
    # for details
    def worker_has_external_dependencies?
      worker_attributes[:external_dependencies]
    end

    def worker_resource_boundary(boundary)
      raise "Invalid boundary" unless VALID_RESOURCE_BOUNDARIES.include? boundary

      worker_attributes[:resource_boundary] = boundary
    end

    def get_worker_resource_boundary
      worker_attributes[:resource_boundary] || :unknown
    end

    def idempotent!
      worker_attributes[:idempotent] = true
    end

    def idempotent?
      worker_attributes[:idempotent]
    end

    def weight(value)
      worker_attributes[:weight] = value
    end

    def get_weight
      worker_attributes[:weight] ||
        NAMESPACE_WEIGHTS[queue_namespace] ||
        1
    end

    protected

    # Returns a worker attribute declared on this class or its parent class.
    # This approach allows declared attributes to be inherited by
    # child classes.
    def get_worker_attribute(name)
      worker_attributes[name] || superclass_worker_attributes(name)
    end

    private

    def worker_attributes
      @attributes ||= {}
    end

    def superclass_worker_attributes(name)
      return unless superclass.include? WorkerAttributes

      superclass.get_worker_attribute(name)
    end
  end
end