workhorse 1.4.4 → 1.4.5
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.
- checksums.yaml +4 -4
- data/.releaser_config +1 -1
- data/CHANGELOG.md +12 -0
- data/README.md +11 -0
- data/RUBY_VERSION +1 -1
- data/VERSION +1 -1
- data/lib/workhorse/daemon/shell_handler.rb +2 -1
- data/lib/workhorse/daemon.rb +1 -1
- data/lib/workhorse.rb +10 -0
- data/test/workhorse/yjit_test.rb +37 -0
- data/workhorse.gemspec +9 -9
- metadata +4 -2
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: ef9cd623d06cab42a5c5a849f9a5c334c0bb8f4dd517f2c84e5ba3c4df611b24
|
|
4
|
+
data.tar.gz: 9681900417bc660a347afeeaebf6cf57fa342268afc38c24b4e5ce11479ce1e3
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 86a5b9f9db82efbd890dc77fa763dcc1052027df45d922358428e721bfe3e900670e28b1e55af06e04972fef7c6408fe8a445239443f0707063281d4baf344fe
|
|
7
|
+
data.tar.gz: 74f47b979b3589b5530947638c7ec7a6acbb9f85599c88bd9eccaf25fcecf5a92addecb58fa9357bc07eb840bf16b31e5a7fe7fe2f9a6e11fa697b31d9aaf526
|
data/.releaser_config
CHANGED
data/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,17 @@
|
|
|
1
1
|
# Workhorse Changelog
|
|
2
2
|
|
|
3
|
+
## 1.4.5 - 2026-05-09
|
|
4
|
+
|
|
5
|
+
* Close the lockfile after releasing the lock in the ShellHandler.
|
|
6
|
+
|
|
7
|
+
Sitrox reference: #120574.
|
|
8
|
+
|
|
9
|
+
* Prevent YJIT from being enabled when `RUBY_YJIT_ENABLE=0` is set. This allows
|
|
10
|
+
running workhorse commands in systemd services that set
|
|
11
|
+
`MemoryDenyWriteExecute=yes`.
|
|
12
|
+
|
|
13
|
+
Sitrox reference: #120574.
|
|
14
|
+
|
|
3
15
|
## 1.4.4 - 2026-04-28
|
|
4
16
|
|
|
5
17
|
* Make debug logging (enabled if `config.debug_log_path` is set) more verbose.
|
data/README.md
CHANGED
|
@@ -529,6 +529,17 @@ ActiveSupport.on_load :workhorse_db_job do
|
|
|
529
529
|
end
|
|
530
530
|
```
|
|
531
531
|
|
|
532
|
+
## Running in systemd services
|
|
533
|
+
|
|
534
|
+
When running workhorse commands inside a systemd service that sets
|
|
535
|
+
`MemoryDenyWriteExecute=yes`, Ruby's YJIT cannot allocate executable memory and
|
|
536
|
+
will crash. To prevent this, set `RUBY_YJIT_ENABLE=0` before invoking the
|
|
537
|
+
workhorse command:
|
|
538
|
+
|
|
539
|
+
```bash
|
|
540
|
+
RUBY_YJIT_ENABLE=0 ./bin/workhorse restart-logging
|
|
541
|
+
```
|
|
542
|
+
|
|
532
543
|
## Debug logging
|
|
533
544
|
|
|
534
545
|
Workhorse includes an optional debug log for diagnosing issues with signal
|
data/RUBY_VERSION
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
ruby-3.
|
|
1
|
+
ruby-3.3.5
|
data/VERSION
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
1.4.
|
|
1
|
+
1.4.5
|
|
@@ -88,6 +88,7 @@ module Workhorse
|
|
|
88
88
|
if lockfile
|
|
89
89
|
Workhorse.debug_log("ShellHandler: releasing lock for #{ARGV.first}")
|
|
90
90
|
lockfile.flock(File::LOCK_UN)
|
|
91
|
+
lockfile.close
|
|
91
92
|
end
|
|
92
93
|
Workhorse.debug_log("ShellHandler: exiting with status #{status}")
|
|
93
94
|
exit! status
|
|
@@ -145,7 +146,7 @@ module Workhorse
|
|
|
145
146
|
|
|
146
147
|
def self.acquire_lock(lockfile_path, flags)
|
|
147
148
|
if Workhorse.lock_shell_commands
|
|
148
|
-
lockfile = File.open(lockfile_path, 'a')
|
|
149
|
+
lockfile = File.open(lockfile_path, 'a') # rubocop:disable Style/FileOpen
|
|
149
150
|
result = lockfile.flock(flags)
|
|
150
151
|
|
|
151
152
|
if result == false
|
data/lib/workhorse/daemon.rb
CHANGED
|
@@ -310,7 +310,7 @@ module Workhorse
|
|
|
310
310
|
@lockfile&.close
|
|
311
311
|
# Reopen pipes to prevent #107576
|
|
312
312
|
$stdin.reopen File.open(File::NULL, 'r')
|
|
313
|
-
null_out = File.open
|
|
313
|
+
null_out = File.open(File::NULL, 'w') # rubocop:disable Style/FileOpen
|
|
314
314
|
$stdout.reopen null_out
|
|
315
315
|
$stderr.reopen null_out
|
|
316
316
|
|
data/lib/workhorse.rb
CHANGED
|
@@ -8,6 +8,16 @@ require 'workhorse/enqueuer'
|
|
|
8
8
|
require 'workhorse/scoped_env'
|
|
9
9
|
require 'workhorse/active_job_extension'
|
|
10
10
|
|
|
11
|
+
# Prevent YJIT from being enabled when RUBY_YJIT_ENABLE is explicitly set to 0.
|
|
12
|
+
# systemd's logrotate.service typically sets MemoryDenyWriteExecute=yes, which
|
|
13
|
+
# prevents mprotect(PROT_EXEC). Rails unconditionally calls
|
|
14
|
+
# RubyVM::YJIT.enable on boot, which triggers a fatal Ruby [BUG] in that
|
|
15
|
+
# environment. Set RUBY_YJIT_ENABLE=0 in the logrotate postrotate script
|
|
16
|
+
# to prevent this.
|
|
17
|
+
if ENV['RUBY_YJIT_ENABLE'] == '0' && defined?(RubyVM::YJIT) && !RubyVM::YJIT.enabled?
|
|
18
|
+
RubyVM::YJIT.define_singleton_method(:enable) { |**| nil }
|
|
19
|
+
end
|
|
20
|
+
|
|
11
21
|
# Main Gem module.
|
|
12
22
|
module Workhorse
|
|
13
23
|
# Check if the available Arel version is greater or equal than 7.0.0
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
require 'English'
|
|
2
|
+
require 'test_helper'
|
|
3
|
+
require 'bundler'
|
|
4
|
+
|
|
5
|
+
class Workhorse::YjitTest < ActiveSupport::TestCase
|
|
6
|
+
YJIT_CHECK_SCRIPT = <<~RUBY.freeze
|
|
7
|
+
require 'bundler/setup'
|
|
8
|
+
require 'workhorse'
|
|
9
|
+
RubyVM::YJIT.enable
|
|
10
|
+
print RubyVM::YJIT.enabled?
|
|
11
|
+
RUBY
|
|
12
|
+
|
|
13
|
+
def test_yjit_not_enabled_when_ruby_yjit_enable_is_zero
|
|
14
|
+
skip 'RubyVM::YJIT.enable not available' unless defined?(RubyVM::YJIT) && RubyVM::YJIT.respond_to?(:enable)
|
|
15
|
+
|
|
16
|
+
# Sanity check: YJIT can actually be enabled in this environment
|
|
17
|
+
without_env = run_ruby_script(YJIT_CHECK_SCRIPT, 'RUBY_YJIT_ENABLE' => nil)
|
|
18
|
+
skip 'YJIT cannot be enabled in this environment' unless without_env == 'true'
|
|
19
|
+
|
|
20
|
+
# With RUBY_YJIT_ENABLE=0, RubyVM::YJIT.enable should be a no-op
|
|
21
|
+
with_env = run_ruby_script(YJIT_CHECK_SCRIPT, 'RUBY_YJIT_ENABLE' => '0')
|
|
22
|
+
assert_equal 'false', with_env, 'YJIT should not be enabled when RUBY_YJIT_ENABLE=0'
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
private
|
|
26
|
+
|
|
27
|
+
def run_ruby_script(script, env = {})
|
|
28
|
+
output = nil
|
|
29
|
+
Bundler.with_unbundled_env do
|
|
30
|
+
IO.popen(env, %w[bundle exec ruby -e] + [script], chdir: Rails.root.to_s, err: %i[child out]) do |io|
|
|
31
|
+
output = io.read.strip
|
|
32
|
+
end
|
|
33
|
+
end
|
|
34
|
+
assert $CHILD_STATUS.success?, "Ruby subprocess failed (exit #{$CHILD_STATUS.exitstatus}): #{output}"
|
|
35
|
+
output
|
|
36
|
+
end
|
|
37
|
+
end
|
data/workhorse.gemspec
CHANGED
|
@@ -1,24 +1,24 @@
|
|
|
1
1
|
# -*- encoding: utf-8 -*-
|
|
2
|
-
# stub: workhorse 1.4.
|
|
2
|
+
# stub: workhorse 1.4.5 ruby lib
|
|
3
3
|
|
|
4
4
|
Gem::Specification.new do |s|
|
|
5
5
|
s.name = "workhorse".freeze
|
|
6
|
-
s.version = "1.4.
|
|
6
|
+
s.version = "1.4.5".freeze
|
|
7
7
|
|
|
8
8
|
s.required_rubygems_version = Gem::Requirement.new(">= 0".freeze) if s.respond_to? :required_rubygems_version=
|
|
9
9
|
s.require_paths = ["lib".freeze]
|
|
10
10
|
s.authors = ["Sitrox".freeze]
|
|
11
|
-
s.date = "2026-
|
|
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/daemon_test.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]
|
|
11
|
+
s.date = "2026-05-09"
|
|
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/daemon_test.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, "test/workhorse/yjit_test.rb".freeze, "workhorse.gemspec".freeze]
|
|
13
13
|
s.homepage = "https://github.com/sitrox/workhorse".freeze
|
|
14
14
|
s.licenses = ["MIT".freeze]
|
|
15
|
-
s.rubygems_version = "3.
|
|
15
|
+
s.rubygems_version = "3.5.18".freeze
|
|
16
16
|
s.summary = "Multi-threaded job backend with database queuing for ruby.".freeze
|
|
17
|
-
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/daemon_test.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]
|
|
17
|
+
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/daemon_test.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, "test/workhorse/yjit_test.rb".freeze]
|
|
18
18
|
|
|
19
19
|
s.specification_version = 4
|
|
20
20
|
|
|
21
|
-
s.add_runtime_dependency(%q<activesupport>.freeze, [">= 7.0.0"])
|
|
22
|
-
s.add_runtime_dependency(%q<activerecord>.freeze, [">= 7.0.0"])
|
|
23
|
-
s.add_runtime_dependency(%q<concurrent-ruby>.freeze, [">= 0"])
|
|
21
|
+
s.add_runtime_dependency(%q<activesupport>.freeze, [">= 7.0.0".freeze])
|
|
22
|
+
s.add_runtime_dependency(%q<activerecord>.freeze, [">= 7.0.0".freeze])
|
|
23
|
+
s.add_runtime_dependency(%q<concurrent-ruby>.freeze, [">= 0".freeze])
|
|
24
24
|
end
|
metadata
CHANGED
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: workhorse
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 1.4.
|
|
4
|
+
version: 1.4.5
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Sitrox
|
|
8
8
|
bindir: bin
|
|
9
9
|
cert_chain: []
|
|
10
|
-
date: 2026-
|
|
10
|
+
date: 2026-05-09 00:00:00.000000000 Z
|
|
11
11
|
dependencies:
|
|
12
12
|
- !ruby/object:Gem::Dependency
|
|
13
13
|
name: activesupport
|
|
@@ -99,6 +99,7 @@ files:
|
|
|
99
99
|
- test/workhorse/poller_test.rb
|
|
100
100
|
- test/workhorse/pool_test.rb
|
|
101
101
|
- test/workhorse/worker_test.rb
|
|
102
|
+
- test/workhorse/yjit_test.rb
|
|
102
103
|
- workhorse.gemspec
|
|
103
104
|
homepage: https://github.com/sitrox/workhorse
|
|
104
105
|
licenses:
|
|
@@ -133,3 +134,4 @@ test_files:
|
|
|
133
134
|
- test/workhorse/poller_test.rb
|
|
134
135
|
- test/workhorse/pool_test.rb
|
|
135
136
|
- test/workhorse/worker_test.rb
|
|
137
|
+
- test/workhorse/yjit_test.rb
|