sidekiq 7.1.4 → 8.0.9

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (128) hide show
  1. checksums.yaml +4 -4
  2. data/Changes.md +333 -0
  3. data/README.md +16 -13
  4. data/bin/multi_queue_bench +271 -0
  5. data/bin/sidekiqload +31 -22
  6. data/bin/webload +69 -0
  7. data/lib/active_job/queue_adapters/sidekiq_adapter.rb +121 -0
  8. data/lib/generators/sidekiq/job_generator.rb +2 -0
  9. data/lib/generators/sidekiq/templates/job.rb.erb +1 -1
  10. data/lib/sidekiq/api.rb +260 -67
  11. data/lib/sidekiq/capsule.rb +17 -8
  12. data/lib/sidekiq/cli.rb +19 -20
  13. data/lib/sidekiq/client.rb +48 -15
  14. data/lib/sidekiq/component.rb +64 -3
  15. data/lib/sidekiq/config.rb +60 -18
  16. data/lib/sidekiq/deploy.rb +4 -2
  17. data/lib/sidekiq/embedded.rb +4 -1
  18. data/lib/sidekiq/fetch.rb +2 -1
  19. data/lib/sidekiq/iterable_job.rb +56 -0
  20. data/lib/sidekiq/job/interrupt_handler.rb +24 -0
  21. data/lib/sidekiq/job/iterable/active_record_enumerator.rb +53 -0
  22. data/lib/sidekiq/job/iterable/csv_enumerator.rb +47 -0
  23. data/lib/sidekiq/job/iterable/enumerators.rb +135 -0
  24. data/lib/sidekiq/job/iterable.rb +322 -0
  25. data/lib/sidekiq/job.rb +16 -5
  26. data/lib/sidekiq/job_logger.rb +15 -12
  27. data/lib/sidekiq/job_retry.rb +41 -13
  28. data/lib/sidekiq/job_util.rb +7 -1
  29. data/lib/sidekiq/launcher.rb +23 -11
  30. data/lib/sidekiq/loader.rb +57 -0
  31. data/lib/sidekiq/logger.rb +25 -69
  32. data/lib/sidekiq/manager.rb +0 -1
  33. data/lib/sidekiq/metrics/query.rb +76 -45
  34. data/lib/sidekiq/metrics/shared.rb +23 -9
  35. data/lib/sidekiq/metrics/tracking.rb +32 -15
  36. data/lib/sidekiq/middleware/current_attributes.rb +39 -14
  37. data/lib/sidekiq/middleware/i18n.rb +2 -0
  38. data/lib/sidekiq/middleware/modules.rb +2 -0
  39. data/lib/sidekiq/monitor.rb +6 -9
  40. data/lib/sidekiq/paginator.rb +16 -3
  41. data/lib/sidekiq/processor.rb +37 -20
  42. data/lib/sidekiq/profiler.rb +73 -0
  43. data/lib/sidekiq/rails.rb +47 -57
  44. data/lib/sidekiq/redis_client_adapter.rb +25 -8
  45. data/lib/sidekiq/redis_connection.rb +49 -9
  46. data/lib/sidekiq/ring_buffer.rb +3 -0
  47. data/lib/sidekiq/scheduled.rb +2 -2
  48. data/lib/sidekiq/systemd.rb +2 -0
  49. data/lib/sidekiq/testing.rb +34 -15
  50. data/lib/sidekiq/transaction_aware_client.rb +20 -5
  51. data/lib/sidekiq/version.rb +6 -2
  52. data/lib/sidekiq/web/action.rb +149 -64
  53. data/lib/sidekiq/web/application.rb +367 -297
  54. data/lib/sidekiq/web/config.rb +120 -0
  55. data/lib/sidekiq/web/csrf_protection.rb +8 -5
  56. data/lib/sidekiq/web/helpers.rb +146 -64
  57. data/lib/sidekiq/web/router.rb +61 -74
  58. data/lib/sidekiq/web.rb +53 -106
  59. data/lib/sidekiq.rb +11 -4
  60. data/sidekiq.gemspec +6 -5
  61. data/web/assets/images/logo.png +0 -0
  62. data/web/assets/images/status.png +0 -0
  63. data/web/assets/javascripts/application.js +66 -24
  64. data/web/assets/javascripts/base-charts.js +30 -16
  65. data/web/assets/javascripts/chartjs-adapter-date-fns.min.js +7 -0
  66. data/web/assets/javascripts/dashboard-charts.js +37 -11
  67. data/web/assets/javascripts/dashboard.js +15 -11
  68. data/web/assets/javascripts/metrics.js +50 -34
  69. data/web/assets/stylesheets/style.css +776 -0
  70. data/web/locales/ar.yml +2 -0
  71. data/web/locales/cs.yml +2 -0
  72. data/web/locales/da.yml +2 -0
  73. data/web/locales/de.yml +2 -0
  74. data/web/locales/el.yml +2 -0
  75. data/web/locales/en.yml +12 -1
  76. data/web/locales/es.yml +25 -2
  77. data/web/locales/fa.yml +2 -0
  78. data/web/locales/fr.yml +2 -1
  79. data/web/locales/gd.yml +2 -1
  80. data/web/locales/he.yml +2 -0
  81. data/web/locales/hi.yml +2 -0
  82. data/web/locales/it.yml +41 -1
  83. data/web/locales/ja.yml +2 -1
  84. data/web/locales/ko.yml +2 -0
  85. data/web/locales/lt.yml +2 -0
  86. data/web/locales/nb.yml +2 -0
  87. data/web/locales/nl.yml +2 -0
  88. data/web/locales/pl.yml +2 -0
  89. data/web/locales/{pt-br.yml → pt-BR.yml} +4 -3
  90. data/web/locales/pt.yml +2 -0
  91. data/web/locales/ru.yml +2 -0
  92. data/web/locales/sv.yml +2 -0
  93. data/web/locales/ta.yml +2 -0
  94. data/web/locales/tr.yml +102 -0
  95. data/web/locales/uk.yml +29 -4
  96. data/web/locales/ur.yml +2 -0
  97. data/web/locales/vi.yml +2 -0
  98. data/web/locales/{zh-cn.yml → zh-CN.yml} +86 -74
  99. data/web/locales/{zh-tw.yml → zh-TW.yml} +3 -2
  100. data/web/views/_footer.erb +31 -22
  101. data/web/views/_job_info.erb +91 -89
  102. data/web/views/_metrics_period_select.erb +13 -10
  103. data/web/views/_nav.erb +14 -21
  104. data/web/views/_paging.erb +22 -21
  105. data/web/views/_poll_link.erb +2 -2
  106. data/web/views/_summary.erb +23 -23
  107. data/web/views/busy.erb +123 -125
  108. data/web/views/dashboard.erb +71 -82
  109. data/web/views/dead.erb +31 -27
  110. data/web/views/filtering.erb +6 -0
  111. data/web/views/layout.erb +13 -29
  112. data/web/views/metrics.erb +70 -68
  113. data/web/views/metrics_for_job.erb +30 -40
  114. data/web/views/morgue.erb +65 -70
  115. data/web/views/profiles.erb +43 -0
  116. data/web/views/queue.erb +54 -52
  117. data/web/views/queues.erb +43 -37
  118. data/web/views/retries.erb +70 -75
  119. data/web/views/retry.erb +32 -27
  120. data/web/views/scheduled.erb +63 -55
  121. data/web/views/scheduled_job_info.erb +3 -3
  122. metadata +49 -27
  123. data/web/assets/stylesheets/application-dark.css +0 -147
  124. data/web/assets/stylesheets/application-rtl.css +0 -153
  125. data/web/assets/stylesheets/application.css +0 -724
  126. data/web/assets/stylesheets/bootstrap-rtl.min.css +0 -9
  127. data/web/assets/stylesheets/bootstrap.css +0 -5
  128. data/web/views/_status.erb +0 -4
data/lib/sidekiq/web.rb CHANGED
@@ -1,20 +1,12 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  require "erb"
4
-
5
- require "sidekiq"
6
- require "sidekiq/api"
7
- require "sidekiq/paginator"
8
- require "sidekiq/web/helpers"
9
-
10
- require "sidekiq/web/router"
11
- require "sidekiq/web/action"
12
- require "sidekiq/web/application"
13
- require "sidekiq/web/csrf_protection"
14
-
15
- require "rack/content_length"
4
+ require "securerandom"
16
5
  require "rack/builder"
17
6
  require "rack/static"
7
+ require "sidekiq"
8
+ require "sidekiq/api"
9
+ require "sidekiq/web/config"
18
10
 
19
11
  module Sidekiq
20
12
  class Web
@@ -31,125 +23,85 @@ module Sidekiq
31
23
  "Retries" => "retries",
32
24
  "Scheduled" => "scheduled",
33
25
  "Dead" => "morgue",
34
- "Metrics" => "metrics"
26
+ "Metrics" => "metrics",
27
+ "Profiles" => "profiles"
35
28
  }
36
29
 
37
- if Gem::Version.new(Rack::RELEASE) < Gem::Version.new("3")
38
- CONTENT_LANGUAGE = "Content-Language"
39
- CONTENT_SECURITY_POLICY = "Content-Security-Policy"
40
- LOCATION = "Location"
41
- X_CASCADE = "X-Cascade"
42
- else
43
- CONTENT_LANGUAGE = "content-language"
44
- CONTENT_SECURITY_POLICY = "content-security-policy"
45
- LOCATION = "location"
46
- X_CASCADE = "x-cascade"
47
- end
30
+ @@config = Sidekiq::Web::Config.new
48
31
 
49
32
  class << self
50
- def settings
51
- self
33
+ def configure
34
+ if block_given?
35
+ yield @@config
36
+ else
37
+ @@config
38
+ end
52
39
  end
53
40
 
54
- def default_tabs
55
- DEFAULT_TABS
41
+ def app_url=(url)
42
+ @@config.app_url = url
56
43
  end
57
44
 
58
- def custom_tabs
59
- @custom_tabs ||= {}
60
- end
61
- alias_method :tabs, :custom_tabs
45
+ def tabs = @@config.tabs
62
46
 
63
- def custom_job_info_rows
64
- @custom_job_info_rows ||= []
65
- end
47
+ def locales = @@config.locales
66
48
 
67
- def locales
68
- @locales ||= LOCALES
69
- end
49
+ def views = @@config.views
70
50
 
71
- def views
72
- @views ||= VIEWS
73
- end
51
+ def custom_job_info_rows = @@config.custom_job_info_rows
74
52
 
75
- def enable(*opts)
76
- opts.each { |key| set(key, true) }
53
+ def redis_pool
54
+ @pool || Sidekiq.default_configuration.redis_pool
77
55
  end
78
56
 
79
- def disable(*opts)
80
- opts.each { |key| set(key, false) }
57
+ def redis_pool=(pool)
58
+ @pool = pool
81
59
  end
82
60
 
83
- def middlewares
84
- @middlewares ||= []
85
- end
61
+ def middlewares = @@config.middlewares
86
62
 
87
- def use(*args, &block)
88
- middlewares << [args, block]
89
- end
63
+ def use(*args, &block) = @@config.middlewares << [args, block]
90
64
 
91
- def set(attribute, value)
92
- send(:"#{attribute}=", value)
65
+ def register(*args, **kw, &block)
66
+ Sidekiq.logger.warn { "`Sidekiq::Web.register` is deprecated, use `Sidekiq::Web.configure {|cfg| cfg.register(...) }`" }
67
+ @@config.register(*args, **kw, &block)
93
68
  end
94
-
95
- attr_accessor :app_url, :redis_pool
96
- attr_writer :locales, :views
97
69
  end
98
70
 
99
- def self.inherited(child)
100
- child.app_url = app_url
101
- child.redis_pool = redis_pool
102
- end
103
-
104
- def settings
105
- self.class.settings
106
- end
107
-
108
- def middlewares
109
- @middlewares ||= self.class.middlewares
71
+ # Allow user to say
72
+ # run Sidekiq::Web
73
+ # rather than:
74
+ # run Sidekiq::Web.new
75
+ def self.call(env)
76
+ @inst ||= new
77
+ @inst.call(env)
110
78
  end
111
79
 
112
- def use(*args, &block)
113
- middlewares << [args, block]
80
+ # testing, internal use only
81
+ def self.reset!
82
+ @@config.reset!
83
+ @inst = nil
114
84
  end
115
85
 
116
86
  def call(env)
87
+ env[:web_config] = Sidekiq::Web.configure
88
+ env[:csp_nonce] = SecureRandom.hex(8)
89
+ env[:redis_pool] = self.class.redis_pool
117
90
  app.call(env)
118
91
  end
119
92
 
120
- def self.call(env)
121
- @app ||= new
122
- @app.call(env)
123
- end
124
-
125
93
  def app
126
- @app ||= build
127
- end
128
-
129
- def enable(*opts)
130
- opts.each { |key| set(key, true) }
131
- end
132
-
133
- def disable(*opts)
134
- opts.each { |key| set(key, false) }
135
- end
136
-
137
- def set(attribute, value)
138
- send(:"#{attribute}=", value)
139
- end
140
-
141
- def self.register(extension)
142
- extension.registered(WebApplication)
94
+ @app ||= build(@@config)
143
95
  end
144
96
 
145
97
  private
146
98
 
147
- def build
148
- klass = self.class
149
- m = middlewares
99
+ def build(cfg)
100
+ cfg.freeze
101
+ m = cfg.middlewares
150
102
 
151
103
  rules = []
152
- rules = [[:all, {Rack::CACHE_CONTROL => "private, max-age=86400"}]] unless ENV["SIDEKIQ_WEB_TESTING"]
104
+ rules = [[:all, {"cache-control" => "private, max-age=86400"}]] unless ENV["SIDEKIQ_WEB_TESTING"]
153
105
 
154
106
  ::Rack::Builder.new do
155
107
  use Rack::Static, urls: ["/stylesheets", "/images", "/javascripts"],
@@ -157,18 +109,13 @@ module Sidekiq
157
109
  cascade: true,
158
110
  header_rules: rules
159
111
  m.each { |middleware, block| use(*middleware, &block) }
160
- use Sidekiq::Web::CsrfProtection unless $TESTING
161
- run WebApplication.new(klass)
112
+ use CsrfProtection if cfg[:csrf]
113
+ run Sidekiq::Web::Application.new(self.class)
162
114
  end
163
115
  end
164
116
  end
165
-
166
- Sidekiq::WebApplication.helpers WebHelpers
167
- Sidekiq::WebApplication.helpers Sidekiq::Paginator
168
-
169
- Sidekiq::WebAction.class_eval <<-RUBY, __FILE__, __LINE__ + 1
170
- def _render
171
- #{ERB.new(File.read(Web::LAYOUT)).src}
172
- end
173
- RUBY
174
117
  end
118
+
119
+ require "sidekiq/web/router"
120
+ require "sidekiq/web/action"
121
+ require "sidekiq/web/application"
data/lib/sidekiq.rb CHANGED
@@ -1,7 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  require "sidekiq/version"
4
- fail "Sidekiq #{Sidekiq::VERSION} does not support Ruby versions below 2.7.0." if RUBY_PLATFORM != "java" && Gem::Version.new(RUBY_VERSION) < Gem::Version.new("2.7.0")
4
+ fail "Sidekiq #{Sidekiq::VERSION} does not support Ruby versions below 3.2.0." if RUBY_PLATFORM != "java" && Gem::Version.new(RUBY_VERSION) < Gem::Version.new("3.2.0")
5
5
 
6
6
  begin
7
7
  require "sidekiq-ent/version"
@@ -29,9 +29,11 @@ end
29
29
 
30
30
  require "sidekiq/config"
31
31
  require "sidekiq/logger"
32
+ require "sidekiq/loader"
32
33
  require "sidekiq/client"
33
34
  require "sidekiq/transaction_aware_client"
34
35
  require "sidekiq/job"
36
+ require "sidekiq/iterable_job"
35
37
  require "sidekiq/worker_compatibility_alias"
36
38
  require "sidekiq/redis_client_adapter"
37
39
 
@@ -93,6 +95,10 @@ module Sidekiq
93
95
  default_configuration.logger
94
96
  end
95
97
 
98
+ def self.loader
99
+ @loader ||= Loader.new
100
+ end
101
+
96
102
  def self.configure_server(&block)
97
103
  (@config_blocks ||= []) << block
98
104
  yield default_configuration if server?
@@ -101,18 +107,19 @@ module Sidekiq
101
107
  def self.freeze!
102
108
  @frozen = true
103
109
  @config_blocks = nil
110
+ default_configuration.freeze!
104
111
  end
105
112
 
106
113
  # Creates a Sidekiq::Config instance that is more tuned for embedding
107
114
  # within an arbitrary Ruby process. Notably it reduces concurrency by
108
115
  # default so there is less contention for CPU time with other threads.
109
116
  #
110
- # inst = Sidekiq.configure_embed do |config|
117
+ # instance = Sidekiq.configure_embed do |config|
111
118
  # config.queues = %w[critical default low]
112
119
  # end
113
- # inst.run
120
+ # instance.run
114
121
  # sleep 10
115
- # inst.terminate
122
+ # instance.stop
116
123
  #
117
124
  # NB: it is really easy to overload a Ruby process with threads due to the GIL.
118
125
  # I do not recommend setting concurrency higher than 2-3.
data/sidekiq.gemspec CHANGED
@@ -12,7 +12,7 @@ Gem::Specification.new do |gem|
12
12
  gem.files = %w[sidekiq.gemspec README.md Changes.md LICENSE.txt] + `git ls-files | grep -E '^(bin|lib|web)'`.split("\n")
13
13
  gem.name = "sidekiq"
14
14
  gem.version = Sidekiq::VERSION
15
- gem.required_ruby_version = ">= 2.7.0"
15
+ gem.required_ruby_version = ">= 3.2.0"
16
16
 
17
17
  gem.metadata = {
18
18
  "homepage_uri" => "https://sidekiq.org",
@@ -23,8 +23,9 @@ Gem::Specification.new do |gem|
23
23
  "rubygems_mfa_required" => "true"
24
24
  }
25
25
 
26
- gem.add_dependency "redis-client", ">= 0.14.0"
27
- gem.add_dependency "connection_pool", ">= 2.3.0"
28
- gem.add_dependency "rack", ">= 2.2.4"
29
- gem.add_dependency "concurrent-ruby", "< 2"
26
+ gem.add_dependency "redis-client", ">= 0.23.2"
27
+ gem.add_dependency "connection_pool", ">= 2.5.0"
28
+ gem.add_dependency "rack", ">= 3.1.0"
29
+ gem.add_dependency "json", ">= 2.9.0"
30
+ gem.add_dependency "logger", ">= 1.6.2"
30
31
  end
File without changes
File without changes
@@ -18,21 +18,15 @@ function addListeners() {
18
18
  })
19
19
  });
20
20
 
21
- document.querySelectorAll("input[data-confirm]").forEach(node => {
22
- node.addEventListener("click", event => {
23
- if (!window.confirm(node.getAttribute("data-confirm"))) {
24
- event.preventDefault();
25
- event.stopPropagation();
26
- }
27
- })
28
- })
29
-
30
21
  document.querySelectorAll("[data-toggle]").forEach(node => {
31
22
  node.addEventListener("click", addDataToggleListeners)
32
23
  })
33
24
 
34
- addShiftClickListeners()
25
+ initializeBulkToggle();
26
+ addShiftClickListeners();
35
27
  updateFuzzyTimes();
28
+ updateNumbers();
29
+ updateProgressBars();
36
30
  setLivePollFromUrl();
37
31
 
38
32
  var buttons = document.querySelectorAll(".live-poll");
@@ -46,6 +40,8 @@ function addListeners() {
46
40
  scheduleLivePoll();
47
41
  }
48
42
  }
43
+
44
+ document.getElementById("locale-select").addEventListener("change", updateLocale);
49
45
  }
50
46
 
51
47
  function addPollingListeners(_event) {
@@ -63,13 +59,24 @@ function addPollingListeners(_event) {
63
59
 
64
60
  function addDataToggleListeners(event) {
65
61
  var source = event.target || event.srcElement;
66
- var targName = source.getAttribute("data-toggle");
62
+ var targName = source.dataset.toggle;
67
63
  var full = document.getElementById(targName);
68
- if (full.style.display == "block") {
69
- full.style.display = 'none';
70
- } else {
71
- full.style.display = 'block';
72
- }
64
+ full.classList.toggle("is-open");
65
+ }
66
+
67
+ function toggleBulkButtons() {
68
+ const checkboxes = document.querySelectorAll('.select-item-checkbox, .check-all-items');
69
+ const anyChecked = Array.from(checkboxes).some(cb => cb.checked);
70
+ const buttons = document.querySelectorAll('.bulk-action-buttons');
71
+ buttons.forEach(btn => {
72
+ btn.style.display = anyChecked ? 'none' : 'block';
73
+ });
74
+ }
75
+
76
+ function initializeBulkToggle(){
77
+ document.querySelectorAll('.check-all-items, .select-item-checkbox').forEach(cb => {
78
+ cb.addEventListener('change', toggleBulkButtons);
79
+ });
73
80
  }
74
81
 
75
82
  function addShiftClickListeners() {
@@ -90,7 +97,7 @@ function addShiftClickListeners() {
90
97
  }
91
98
 
92
99
  function updateFuzzyTimes() {
93
- var locale = document.body.getAttribute("data-locale");
100
+ var locale = document.body.dataset.locale;
94
101
  var parts = locale.split('-');
95
102
  if (typeof parts[1] !== 'undefined') {
96
103
  parts[1] = parts[1].toUpperCase();
@@ -102,6 +109,20 @@ function updateFuzzyTimes() {
102
109
  t.cancel();
103
110
  }
104
111
 
112
+ function updateNumbers() {
113
+ document.querySelectorAll("[data-nwp]").forEach(node => {
114
+ let number = parseFloat(node.textContent);
115
+ let precision = parseInt(node.dataset.nwp || 0);
116
+ if (typeof number === "number") {
117
+ let formatted = number.toLocaleString(undefined, {
118
+ minimumFractionDigits: precision,
119
+ maximumFractionDigits: precision,
120
+ });
121
+ node.textContent = formatted;
122
+ }
123
+ });
124
+ }
125
+
105
126
  function setLivePollFromUrl() {
106
127
  var url_params = new URL(window.location.href).searchParams
107
128
 
@@ -112,11 +133,11 @@ function setLivePollFromUrl() {
112
133
 
113
134
  function updateLivePollButton() {
114
135
  if (localStorage.sidekiqLivePoll == "enabled") {
115
- document.querySelectorAll('.live-poll-stop').forEach(box => { box.style.display = "inline-block" })
116
- document.querySelectorAll('.live-poll-start').forEach(box => { box.style.display = "none" })
136
+ document.querySelectorAll('.live-poll-stop').forEach(box => { box.classList.add("active") })
137
+ document.querySelectorAll('.live-poll-start').forEach(box => { box.classList.remove("active") })
117
138
  } else {
118
- document.querySelectorAll('.live-poll-start').forEach(box => { box.style.display = "inline-block" })
119
- document.querySelectorAll('.live-poll-stop').forEach(box => { box.style.display = "none" })
139
+ document.querySelectorAll('.live-poll-start').forEach(box => { box.classList.add("active") })
140
+ document.querySelectorAll('.live-poll-stop').forEach(box => { box.classList.remove("active") })
120
141
  }
121
142
  }
122
143
 
@@ -151,12 +172,33 @@ function replacePage(text) {
151
172
  var page = doc.querySelector('#page')
152
173
  document.querySelector("#page").replaceWith(page)
153
174
 
154
- var header_status = doc.querySelector('.status')
155
- document.querySelector('.status').replaceWith(header_status)
156
-
157
175
  addListeners();
158
176
  }
159
177
 
160
178
  function showError(error) {
161
179
  console.error(error)
162
180
  }
181
+
182
+ function updateLocale(event) {
183
+ event.target.form.submit();
184
+ }
185
+
186
+ function updateProgressBars() {
187
+ document.querySelectorAll('.progress-bar').forEach(bar => { bar.style.width = bar.dataset.width + "%"})
188
+ }
189
+
190
+ function handleConfirmDialog (event) {
191
+ const target = event.target
192
+
193
+ if (target.localName !== "input") { return }
194
+ const confirmMessage = target.dataset.confirm
195
+
196
+ if (confirmMessage === undefined) { return }
197
+
198
+ if (!window.confirm(confirmMessage)) {
199
+ event.preventDefault()
200
+ event.stopPropagation()
201
+ }
202
+ }
203
+
204
+ document.addEventListener("click", handleConfirmDialog)
@@ -1,27 +1,35 @@
1
1
  if (window.matchMedia("(prefers-color-scheme: dark)").matches) {
2
2
  Chart.defaults.borderColor = "#333";
3
3
  Chart.defaults.color = "#aaa";
4
+ // Chart.defaults.borderColor = "oklch(22% 0.01 256)";
5
+ // Chart.defaults.color = "oklch(65% 0.01 256)";
4
6
  }
5
7
 
6
8
  class Colors {
7
9
  constructor() {
8
10
  this.assignments = {};
9
- this.success = "#006f68";
10
- this.failure = "#af0014";
11
- this.fallback = "#999";
12
- this.primary = "#537bc4";
11
+ if (window.matchMedia("(prefers-color-scheme: dark)").matches) {
12
+ this.light = "65%";
13
+ this.chroma = "0.15";
14
+ } else {
15
+ this.light = "48%";
16
+ this.chroma = "0.2";
17
+ }
18
+ this.success = "oklch(" + this.light + " " + this.chroma + " 179)";
19
+ this.failure = "oklch(" + this.light + " " + this.chroma + " 29)";
20
+ this.fallback = "oklch(" + this.light + " 0.02 269)";
21
+ this.primary = "oklch(" + this.light + " " + this.chroma + " 269)";
13
22
  this.available = [
14
- // Colors taken from https://www.chartjs.org/docs/latest/samples/utils.html
15
- "#537bc4",
16
- "#4dc9f6",
17
- "#f67019",
18
- "#f53794",
19
- "#acc236",
20
- "#166a8f",
21
- "#00a950",
22
- "#58595b",
23
- "#8549ba",
24
- "#991b1b",
23
+ "oklch(" + this.light + " " + this.chroma + " 256)",
24
+ "oklch(" + this.light + " " + this.chroma + " 196)",
25
+ "oklch(" + this.light + " " + this.chroma + " 46)",
26
+ "oklch(" + this.light + " " + this.chroma + " 316)",
27
+ "oklch(" + this.light + " " + this.chroma + " 106)",
28
+ "oklch(" + this.light + " " + this.chroma + " 226)",
29
+ "oklch(" + this.light + " " + this.chroma + " 136)",
30
+ "oklch(" + this.light + " 0.02 269)",
31
+ "oklch(" + this.light + " " + this.chroma + " 286)",
32
+ "oklch(" + this.light + " " + this.chroma + " 16)",
25
33
  ];
26
34
  }
27
35
 
@@ -90,12 +98,18 @@ class BaseChart {
90
98
  };
91
99
 
92
100
  if (this.options.marks) {
101
+ if (window.matchMedia("(prefers-color-scheme: dark)").matches) {
102
+ this.Borderlight = "30%";
103
+ } else {
104
+ this.Borderlight = "65%";
105
+ }
106
+
93
107
  this.options.marks.forEach(([bucket, label], i) => {
94
108
  chartOptions.plugins.annotation.annotations[`deploy-${i}`] = {
95
109
  type: "line",
96
110
  xMin: bucket,
97
111
  xMax: bucket,
98
- borderColor: "rgba(220, 38, 38, 0.4)",
112
+ borderColor: "oklch(" + this.Borderlight + " 0.01 256)",
99
113
  borderWidth: 2,
100
114
  };
101
115
  });