workhorse 1.2.16 → 1.2.17.rc0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 7c50e38fd05785d30e0dfa783d732f46df2be9b980ac0a54dca1a2d91264ff9d
4
- data.tar.gz: a4b282a25d39429da15c5380a41a1786b54b24b2b8afb4961786881380eecacf
3
+ metadata.gz: 25908f294cd9623ebde44ec8bba5181ee54965703f4fb93df18876b216718eb8
4
+ data.tar.gz: 568e620571a9ded165fee1fc4420efbb6810f073edd4365c6c8efbe7c3676052
5
5
  SHA512:
6
- metadata.gz: f8fefeb28bb6651e93163e5d9b8744994f681064bf55168b73d8ca5e9c72aee9e3f7642d03a86eb496ebd81bf15e724757cb4f0a6790dcb87e3ae5f3ef09344d
7
- data.tar.gz: '090f112b83a2a69015e0244345d30616af8701bf99f2a6814238006efa2cca49850dfe024b26d1359b2863d01bf2c84d0bbf84a7122419f540969ba7f8d66dea'
6
+ metadata.gz: 83b6ac441e3762f251e35f04dd213044d6fb904a005155235546391cdecd4f9c0c1db24be7c30371da4704b27e6f18aa6ce0b448b6c6c1dbc8c77eeb81faa9e3
7
+ data.tar.gz: 9c2940a6bfb7cd0be49170d81af2378f27395dbf597f6d8fa2c777bdc812b26d06cc849454ba5925fcf5f26b7724779b3d6e941bc6c9237d6dc251b7d071188f
data/CHANGELOG.md CHANGED
@@ -1,5 +1,14 @@
1
1
  # Workhorse Changelog
2
2
 
3
+ ## 1.2.17.rc0 - 2024-02-05
4
+
5
+ * Add option `config.max_worker_memory_mb` for automatic restart of workers
6
+ exceeding the specified memory threshold using the `watch` command. Default is
7
+ `0`, deactivating this feature. See [memory
8
+ handling](README.md#memory-handling) for more information.
9
+
10
+ Sitrox reference: #121312.
11
+
3
12
  ## 1.2.16 - 2023-09-18
4
13
 
5
14
  * Add support for `--skip-initializer` flag to install generator.
data/LICENSE CHANGED
@@ -1,6 +1,6 @@
1
1
  MIT License
2
2
 
3
- Copyright (c) 2017 - 2023 Sitrox
3
+ Copyright (c) 2017 - 2024 Sitrox
4
4
 
5
5
  Permission is hereby granted, free of charge, to any person obtaining a copy
6
6
  of this software and associated documentation files (the "Software"), to deal
data/README.md CHANGED
@@ -464,6 +464,29 @@ jobs database on a regular interval. Workhorse provides the job
464
464
  `Workhorse::Jobs::CleanupSucceededJobs` for this purpose that cleans up all
465
465
  succeeded jobs. You can run this using your scheduler in a specific interval.
466
466
 
467
+ ## Memory handling
468
+
469
+ When dealing with jobs that may exhibit a large memory footprint, it's important
470
+ to note that Ruby might not release consumed memory back to the operating
471
+ system. Consequently, your job workers could accumulate a significant amount of
472
+ memory over time. To address this, Workhorse provides the
473
+ `config.max_worker_memory_mb` option.
474
+
475
+ If `config.max_worker_memory_mb` is set to a value above `0`, the `watch`
476
+ command will check the memory footprint (RSS / resident size) of all worker
477
+ processes. If any worker exceeds the specified footprint, Workhorse will
478
+ silently restart it to ensure proper memory release. This process does not
479
+ produce any output in the `watch` command.
480
+
481
+ Example configuration:
482
+
483
+ ```ruby
484
+ # config/initializers/workhorse.rb
485
+ Workhorse.setup do |config|
486
+ config.max_worker_memory_mb = 512 # Set the memory threshold to 512 megabytes
487
+ end
488
+ ```
489
+
467
490
  ## Load hooks
468
491
 
469
492
  Using the load hook `:workhorse_db_job`, you can inject custom code into the
@@ -540,4 +563,4 @@ Please consult the [FAQ](FAQ.md).
540
563
 
541
564
  ## Copyright
542
565
 
543
- Copyright © 2017 - 2023 Sitrox. See `LICENSE` for further details.
566
+ Copyright © 2017 - 2024 Sitrox. See `LICENSE` for further details.
data/RUBY_VERSION CHANGED
@@ -1 +1 @@
1
- ruby-2.7.1-p83
1
+ ruby-3.2.1-p31
data/VERSION CHANGED
@@ -1 +1 @@
1
- 1.2.16
1
+ 1.2.17.rc0
@@ -113,10 +113,14 @@ module Workhorse
113
113
  end
114
114
 
115
115
  if should_be_running && status(quiet: true) != 0
116
- return start(quiet: Workhorse.silence_watcher)
116
+ code = start(quiet: Workhorse.silence_watcher)
117
117
  else
118
- return 0
118
+ code = 0
119
119
  end
120
+
121
+ watch_memory! if should_be_running
122
+
123
+ return code
120
124
  end
121
125
 
122
126
  def restart
@@ -144,6 +148,30 @@ module Workhorse
144
148
 
145
149
  private
146
150
 
151
+ def watch_memory!
152
+ return if Workhorse.max_worker_memory_mb == 0
153
+
154
+ for_each_worker do |worker|
155
+ pid_file, pid = read_pid(worker)
156
+ next unless pid_file && pid
157
+
158
+ memory = memory_for(pid)
159
+ next unless memory
160
+
161
+ if memory > Workhorse.max_worker_memory_mb
162
+ stop_worker pid_file, pid
163
+ start_worker worker
164
+ end
165
+ end
166
+ end
167
+
168
+ # Returns the memory (RSS) in MB for the given process.
169
+ def memory_for(pid)
170
+ mem = `ps -p #{pid} -o rss=`&.strip
171
+ return nil if mem.blank?
172
+ return mem.to_i / 1024
173
+ end
174
+
147
175
  def for_each_worker(&block)
148
176
  @workers.each(&block)
149
177
  end
data/lib/workhorse.rb CHANGED
@@ -75,6 +75,12 @@ module Workhorse
75
75
  mattr_accessor :stale_detection_run_time_threshold
76
76
  self.stale_detection_run_time_threshold = 12 * 60
77
77
 
78
+ # Maximum memory for a worker in MB. If this memory limit (RSS / resident
79
+ # size) is reached for a worker process, the 'watch' command will restart said
80
+ # worker. Set this to 0 disable this feature.
81
+ mattr_accessor :max_worker_memory_mb
82
+ self.max_worker_memory_mb = 0
83
+
78
84
  def self.setup
79
85
  yield self
80
86
  end
data/workhorse.gemspec CHANGED
@@ -1,48 +1,31 @@
1
1
  # -*- encoding: utf-8 -*-
2
- # stub: workhorse 1.2.16 ruby lib
2
+ # stub: workhorse 1.2.17.rc0 ruby lib
3
3
 
4
4
  Gem::Specification.new do |s|
5
5
  s.name = "workhorse".freeze
6
- s.version = "1.2.16"
6
+ s.version = "1.2.17.rc0"
7
7
 
8
- s.required_rubygems_version = Gem::Requirement.new(">= 0".freeze) if s.respond_to? :required_rubygems_version=
8
+ s.required_rubygems_version = Gem::Requirement.new("> 1.3.1".freeze) if s.respond_to? :required_rubygems_version=
9
9
  s.require_paths = ["lib".freeze]
10
10
  s.authors = ["Sitrox".freeze]
11
- s.date = "2023-09-18"
11
+ s.date = "2024-02-05"
12
12
  s.files = [".github/workflows/ruby.yml".freeze, ".gitignore".freeze, ".releaser_config".freeze, ".rubocop.yml".freeze, "CHANGELOG.md".freeze, "FAQ.md".freeze, "Gemfile".freeze, "LICENSE".freeze, "README.md".freeze, "RUBY_VERSION".freeze, "Rakefile".freeze, "VERSION".freeze, "bin/rubocop".freeze, "lib/active_job/queue_adapters/workhorse_adapter.rb".freeze, "lib/generators/workhorse/install_generator.rb".freeze, "lib/generators/workhorse/templates/bin/workhorse.rb".freeze, "lib/generators/workhorse/templates/config/initializers/workhorse.rb".freeze, "lib/generators/workhorse/templates/create_table_jobs.rb".freeze, "lib/workhorse.rb".freeze, "lib/workhorse/active_job_extension.rb".freeze, "lib/workhorse/daemon.rb".freeze, "lib/workhorse/daemon/shell_handler.rb".freeze, "lib/workhorse/db_job.rb".freeze, "lib/workhorse/enqueuer.rb".freeze, "lib/workhorse/jobs/cleanup_succeeded_jobs.rb".freeze, "lib/workhorse/jobs/detect_stale_jobs_job.rb".freeze, "lib/workhorse/jobs/run_active_job.rb".freeze, "lib/workhorse/jobs/run_rails_op.rb".freeze, "lib/workhorse/performer.rb".freeze, "lib/workhorse/poller.rb".freeze, "lib/workhorse/pool.rb".freeze, "lib/workhorse/scoped_env.rb".freeze, "lib/workhorse/worker.rb".freeze, "test/active_job/queue_adapters/workhorse_adapter_test.rb".freeze, "test/lib/db_schema.rb".freeze, "test/lib/jobs.rb".freeze, "test/lib/test_helper.rb".freeze, "test/workhorse/db_job_test.rb".freeze, "test/workhorse/enqueuer_test.rb".freeze, "test/workhorse/performer_test.rb".freeze, "test/workhorse/poller_test.rb".freeze, "test/workhorse/pool_test.rb".freeze, "test/workhorse/worker_test.rb".freeze, "workhorse.gemspec".freeze]
13
- s.rubygems_version = "3.1.2".freeze
13
+ s.rubygems_version = "3.4.6".freeze
14
14
  s.summary = "Multi-threaded job backend with database queuing for ruby.".freeze
15
15
  s.test_files = ["test/active_job/queue_adapters/workhorse_adapter_test.rb".freeze, "test/lib/db_schema.rb".freeze, "test/lib/jobs.rb".freeze, "test/lib/test_helper.rb".freeze, "test/workhorse/db_job_test.rb".freeze, "test/workhorse/enqueuer_test.rb".freeze, "test/workhorse/performer_test.rb".freeze, "test/workhorse/poller_test.rb".freeze, "test/workhorse/pool_test.rb".freeze, "test/workhorse/worker_test.rb".freeze]
16
16
 
17
- if s.respond_to? :specification_version then
18
- s.specification_version = 4
19
- end
17
+ s.specification_version = 4
20
18
 
21
- if s.respond_to? :add_runtime_dependency then
22
- s.add_development_dependency(%q<bundler>.freeze, [">= 0"])
23
- s.add_development_dependency(%q<rake>.freeze, [">= 0"])
24
- s.add_development_dependency(%q<rubocop>.freeze, ["~> 1.28.0"])
25
- s.add_development_dependency(%q<minitest>.freeze, [">= 0"])
26
- s.add_development_dependency(%q<mysql2>.freeze, [">= 0"])
27
- s.add_development_dependency(%q<colorize>.freeze, [">= 0"])
28
- s.add_development_dependency(%q<benchmark-ips>.freeze, [">= 0"])
29
- s.add_development_dependency(%q<activejob>.freeze, [">= 0"])
30
- s.add_development_dependency(%q<pry>.freeze, [">= 0"])
31
- s.add_runtime_dependency(%q<activesupport>.freeze, [">= 0"])
32
- s.add_runtime_dependency(%q<activerecord>.freeze, [">= 0"])
33
- s.add_runtime_dependency(%q<concurrent-ruby>.freeze, [">= 0"])
34
- else
35
- s.add_dependency(%q<bundler>.freeze, [">= 0"])
36
- s.add_dependency(%q<rake>.freeze, [">= 0"])
37
- s.add_dependency(%q<rubocop>.freeze, ["~> 1.28.0"])
38
- s.add_dependency(%q<minitest>.freeze, [">= 0"])
39
- s.add_dependency(%q<mysql2>.freeze, [">= 0"])
40
- s.add_dependency(%q<colorize>.freeze, [">= 0"])
41
- s.add_dependency(%q<benchmark-ips>.freeze, [">= 0"])
42
- s.add_dependency(%q<activejob>.freeze, [">= 0"])
43
- s.add_dependency(%q<pry>.freeze, [">= 0"])
44
- s.add_dependency(%q<activesupport>.freeze, [">= 0"])
45
- s.add_dependency(%q<activerecord>.freeze, [">= 0"])
46
- s.add_dependency(%q<concurrent-ruby>.freeze, [">= 0"])
47
- end
19
+ s.add_development_dependency(%q<bundler>.freeze, [">= 0"])
20
+ s.add_development_dependency(%q<rake>.freeze, [">= 0"])
21
+ s.add_development_dependency(%q<rubocop>.freeze, ["~> 1.28.0"])
22
+ s.add_development_dependency(%q<minitest>.freeze, [">= 0"])
23
+ s.add_development_dependency(%q<mysql2>.freeze, [">= 0"])
24
+ s.add_development_dependency(%q<colorize>.freeze, [">= 0"])
25
+ s.add_development_dependency(%q<benchmark-ips>.freeze, [">= 0"])
26
+ s.add_development_dependency(%q<activejob>.freeze, [">= 0"])
27
+ s.add_development_dependency(%q<pry>.freeze, [">= 0"])
28
+ s.add_runtime_dependency(%q<activesupport>.freeze, [">= 0"])
29
+ s.add_runtime_dependency(%q<activerecord>.freeze, [">= 0"])
30
+ s.add_runtime_dependency(%q<concurrent-ruby>.freeze, [">= 0"])
48
31
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: workhorse
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.2.16
4
+ version: 1.2.17.rc0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Sitrox
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2023-09-18 00:00:00.000000000 Z
11
+ date: 2024-02-05 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler
@@ -242,11 +242,11 @@ required_ruby_version: !ruby/object:Gem::Requirement
242
242
  version: '0'
243
243
  required_rubygems_version: !ruby/object:Gem::Requirement
244
244
  requirements:
245
- - - ">="
245
+ - - ">"
246
246
  - !ruby/object:Gem::Version
247
- version: '0'
247
+ version: 1.3.1
248
248
  requirements: []
249
- rubygems_version: 3.4.6
249
+ rubygems_version: 3.4.10
250
250
  signing_key:
251
251
  specification_version: 4
252
252
  summary: Multi-threaded job backend with database queuing for ruby.