solid-jobs 0.1.3 → 0.4.0

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 (38) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +73 -4
  3. data/README.md +149 -118
  4. data/docs/reliability.md +73 -91
  5. data/exe/solid-jobs +2 -3
  6. data/lib/active_job/queue_adapters/solid_jobs_adapter.rb +7 -8
  7. data/lib/solid_jobs/{config.rb → blueprint.rb} +51 -51
  8. data/lib/solid_jobs/catalog.rb +427 -0
  9. data/lib/solid_jobs/claim.rb +315 -0
  10. data/lib/solid_jobs/{server.rb → conductor.rb} +10 -10
  11. data/lib/solid_jobs/{cli.rb → console.rb} +12 -9
  12. data/lib/solid_jobs/{processor.rb → engine.rb} +33 -33
  13. data/lib/solid_jobs/errors.rb +1 -1
  14. data/lib/solid_jobs/executor.rb +34 -0
  15. data/lib/solid_jobs/failure_policy.rb +98 -0
  16. data/lib/solid_jobs/heartbeat.rb +15 -13
  17. data/lib/solid_jobs/integrity_check.rb +39 -36
  18. data/lib/solid_jobs/interceptor_registry.rb +57 -0
  19. data/lib/solid_jobs/keyspace.rb +42 -0
  20. data/lib/solid_jobs/{testing.rb → lab.rb} +19 -19
  21. data/lib/solid_jobs/publisher.rb +186 -0
  22. data/lib/solid_jobs/rails_adapter.rb +13 -0
  23. data/lib/solid_jobs/{rails.rb → railtie.rb} +1 -2
  24. data/lib/solid_jobs/recovery.rb +8 -7
  25. data/lib/solid_jobs/task.rb +147 -0
  26. data/lib/solid_jobs/{scheduler.rb → timer.rb} +8 -8
  27. data/lib/solid_jobs/utilities.rb +5 -11
  28. data/lib/solid_jobs/version.rb +1 -1
  29. data/lib/solid_jobs.rb +28 -27
  30. metadata +19 -18
  31. data/lib/solid_jobs/active_job.rb +0 -16
  32. data/lib/solid_jobs/api.rb +0 -457
  33. data/lib/solid_jobs/client.rb +0 -202
  34. data/lib/solid_jobs/fetch.rb +0 -310
  35. data/lib/solid_jobs/job.rb +0 -156
  36. data/lib/solid_jobs/middleware/chain.rb +0 -104
  37. data/lib/solid_jobs/retry_service.rb +0 -100
  38. data/lib/solid_jobs/worker.rb +0 -35
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 52c2c82a111ab574881c9efe6f5c692c145b50ad85542844e34de74a44860a8e
4
- data.tar.gz: 7a23ba9ea19c901c7c888680351b018b8f554cac0192a17195682aaa3725bd82
3
+ metadata.gz: 7f95c0daf98dbfa77203eaa6d182f0b0a5ce4c22738a29f7d81b587c9f3abe3a
4
+ data.tar.gz: bf5524aa572a45f439732ec30e5ad12d5ad25b37a98462381d39bd90b5dd7c91
5
5
  SHA512:
6
- metadata.gz: 63447e81affab81cac25ed04aed7fa8cc8b27d89e5fd6425db087ed0feadc4d950266c35c16df6e91f27f5a5562844610516048ccbc4120f5132f9ab83456970
7
- data.tar.gz: 3da40a61ca01cd8f868ebc0dd734b925ad0d46852517f34ea73b23cb8e9762c05b09db55caf218729a734975c579cb97d27253666142dbc694e0c5a018df427a
6
+ metadata.gz: cecbfb4efd3abe1598e66b1764ca07da25e4d103c5e59b66c14f84f5f8f3af6b45e91710d535b0b15ee69636a9396629a0e980451202f390a8aebb8a6b41091b
7
+ data.tar.gz: cf40a09b495d1ea62e0789ea8688b530b26bfc7414e77cd2d4cc30f8c874c1a8f6c19b20f2eb2c493c8ca27bbeb2a319a62024dff639d6748d720b1ab13c04d6
data/CHANGELOG.md CHANGED
@@ -2,6 +2,73 @@
2
2
 
3
3
  All notable changes to this project will be documented in this file.
4
4
 
5
+ ## [0.4.0] - 2026-10-03
6
+
7
+ ### Changed
8
+
9
+ - Keep the independent SolidJobs runtime, envelope, `solid_jobs:` keyspace,
10
+ interceptors, claims, and renamed component vocabulary from 0.3.0.
11
+ - Remaining shared names with other Ruby job libraries are limited to
12
+ `version.rb`, Rails Active Job adapter contracts (`ActiveJob`,
13
+ `QueueAdapters`, `enqueue_at`), and generic Ruby methods.
14
+
15
+ ## [0.3.0] - 2026-10-03
16
+
17
+ ### Breaking
18
+
19
+ - Rename the runtime components to SolidJobs-specific names:
20
+ `Config` to `Blueprint`, `Server` to `Conductor`, `Processor` to `Engine`,
21
+ `CLI` to `Console`, `Testing` to `Lab`, and `Metrics` to `Counters`.
22
+ - Rename the task execution callback from `perform` to `execute_task`.
23
+ - Rename `Task.enqueue_at` to `Task.schedule_at`. The Active Job adapter keeps
24
+ its Rails-required `enqueue_at` method.
25
+ - Rename the Active Job execution task from `ActiveJob::Wrapper` to
26
+ `RailsAdapter::AdapterTask`.
27
+ - Rename generic implementation files to match the new component vocabulary.
28
+ `version.rb` remains unchanged as the standard Ruby gem version entry point.
29
+ - Remove the remaining generic internal constants `ClassMethods`,
30
+ `EmptyQueueError`, and `Shutdown` in favor of `TaskMethods`,
31
+ `NoCapturedTask`, and `ExecutionHalt`.
32
+ - Replace `Node#quiet`, `Node#stop`, and `Node#dump_threads` with
33
+ `Node#request_control(:pause)`, `:shutdown`, or `:backtraces`.
34
+
35
+ ### Changed
36
+
37
+ - Update the executable, Rails adapter, documentation, benchmarks, and test
38
+ suite to use the new vocabulary consistently.
39
+ - Keep the SolidJobs task API, envelope, `solid_jobs:` Redis keyspace, claims,
40
+ interceptors, and failure model introduced in 0.2.0.
41
+ - Convert configuration keys using Ruby hash transformations, preserving
42
+ nested values and leaving the original input unchanged.
43
+
44
+ ## [0.2.0] - 2026-10-03
45
+
46
+ ### Breaking
47
+
48
+ - Replace the previous job API with the independent `SolidJobs::Task` API:
49
+ `enqueue`, `enqueue_after`, `schedule_at`, `enqueue_many`, `execute`, and
50
+ `with_options`.
51
+ - Replace the previous payload with a SolidJobs envelope using `id`, `task`,
52
+ `arguments`, `channel`, `run_at`, `created_ms`, and `queued_ms`.
53
+ - Move all Redis data into the `solid_jobs:` keyspace. Existing queued data is
54
+ not read or migrated automatically.
55
+ - Replace middleware chains with `publish_interceptors` and
56
+ `execute_interceptors`, whose interceptors implement `around(context)`.
57
+ - Replace the administrative API with `Counters`, `Channel`, `StoredTask`,
58
+ `PlannedTasks`, `RetryingTasks`, `DiscardedTasks`, `Node`, `Nodes`,
59
+ `Execution`, and `Claims`.
60
+ - Replace queue configuration with channels and the `:weighted`, `:priority`,
61
+ and `:shuffle` ordering modes.
62
+ - Remove all Sidekiq compatibility aliases and wire-format compatibility.
63
+
64
+ ### Changed
65
+
66
+ - Claims use UUID task IDs and claim tokens, with generation-fenced completion
67
+ and requeue operations.
68
+ - Failure handling uses `max_failures`, `retry_within`, `retry_delay`, and
69
+ `after_final_failure`.
70
+ - Lab modes are now `:capture` and `:execute`.
71
+
5
72
  ## [0.1.3] - 2026-10-01
6
73
 
7
74
  ### Changed
@@ -13,9 +80,9 @@ All notable changes to this project will be documented in this file.
13
80
 
14
81
  ### Added
15
82
 
16
- - `Server#start` logs a warning on Ruby < 4 when `concurrency > 1`, pointing
83
+ - `Conductor#start` logs a warning on Ruby < 4 when `concurrency > 1`, pointing
17
84
  to the Ruby 3.4 Ractor GC-barrier deadlock and the recommended setups.
18
- - `Server#stop` is bounded: components get `shutdown_timeout + STOP_GRACE`
85
+ - `Conductor#stop` is bounded: components get `shutdown_timeout + STOP_GRACE`
19
86
  to return, `:stop` is re-sent up to `STOP_RESENDS` times, then the
20
87
  component is abandoned with an error log instead of hanging shutdown.
21
88
  - `test/support/ractor_barrier_repro.rb`: standalone reproducer of the Ruby
@@ -23,7 +90,7 @@ All notable changes to this project will be documented in this file.
23
90
 
24
91
  ### Changed
25
92
 
26
- - Server-based stress tests are skipped on Ruby < 4: Ruby 3.4's Ractor
93
+ - Conductor-based stress tests are skipped on Ruby < 4: Ruby 3.4's Ractor
27
94
  scheduler deadlocks the VM on a GC barrier under cross-Ractor `move:`
28
95
  traffic. Multi-Ractor servers are recommended on Ruby ≥ 4.0 (see
29
96
  `docs/reliability.md`). CI jobs now time out after 20 minutes.
@@ -46,7 +113,7 @@ All notable changes to this project will be documented in this file.
46
113
 
47
114
  ### Added
48
115
 
49
- - Ractor-oriented client, Processor, Scheduler, Heartbeat, and Server runtime.
116
+ - Ractor-oriented client, Engine, Scheduler, Heartbeat, and Conductor runtime.
50
117
  - Sidekiq-compatible Redis queue keys and open-source job payload format.
51
118
  - Immediate, scheduled, retry, and dead-job handling.
52
119
  - At-least-once reservations with atomic journaling, generation-fenced ACK
@@ -61,6 +128,8 @@ All notable changes to this project will be documented in this file.
61
128
  - Reliable-hot-path and CPU-scaling profilers plus the independent Sidekiq
62
129
  comparison benchmark.
63
130
 
131
+ [0.3.0]: https://github.com/nicolasva/solid-jobs/compare/v0.2.0...v0.3.0
132
+ [0.2.0]: https://github.com/nicolasva/solid-jobs/compare/v0.1.3...v0.2.0
64
133
  [0.1.3]: https://github.com/nicolasva/solid-jobs/compare/v0.1.2...v0.1.3
65
134
  [0.1.2]: https://github.com/nicolasva/solid-jobs/compare/v0.1.1...v0.1.2
66
135
  [0.1.1]: https://github.com/nicolasva/solid-jobs/compare/v0.1.0...v0.1.1
data/README.md CHANGED
@@ -1,164 +1,195 @@
1
1
  # SolidJobs
2
2
 
3
3
  [![Build Status](https://github.com/nicolasva/solid-jobs/actions/workflows/ci.yml/badge.svg)](https://github.com/nicolasva/solid-jobs/actions/workflows/ci.yml)
4
- [![Code Climate](https://codeclimate.com/github/nicolasva/solid-jobs/badges/gpa.svg)](https://codeclimate.com/github/nicolasva/solid-jobs)
5
4
  [![Gem Version](https://badge.fury.io/rb/solid-jobs.svg)](https://rubygems.org/gems/solid-jobs)
6
- [![Documentation Status](https://img.shields.io/badge/docs-rubydoc.info-blue.svg)](https://www.rubydoc.info/gems/solid-jobs)
7
- [![Downloads](https://img.shields.io/gem/dt/solid-jobs.svg)](https://rubygems.org/gems/solid-jobs)
8
5
 
9
- SolidJobs is a Ractor-oriented Redis background job system for Ruby. It uses
10
- `solid-redis` for Redis access and keeps mutable clients, pools, middleware,
11
- and runtime state local to their owning Ractor.
6
+ SolidJobs is a Ractor-oriented Redis task runner for Ruby. It provides its own
7
+ task API, Redis envelope, keyspace, interceptor model, failure policy, and
8
+ inspection API.
12
9
 
13
- SolidJobs is an independent implementation. It does not depend on or load the
14
- Sidekiq gem. Its Redis job payloads and queue keys are designed to be
15
- compatible with the Sidekiq 8 open-source data format.
16
-
17
- SolidJobs and its required gems use pure Ruby and do not require native
18
- extensions. Hot paths are designed around bounded buffers, reusable immutable
19
- configuration, and low-allocation command batches.
10
+ SolidJobs is **not compatible with Sidekiq**. It does not read Sidekiq queues,
11
+ does not write Sidekiq payloads, and does not expose Sidekiq's job API. Existing
12
+ applications and queued work must be migrated explicitly.
20
13
 
21
14
  ## Installation
22
15
 
23
- Add SolidJobs 0.1 to your bundle:
24
-
25
16
  ```ruby
26
- gem "solid-jobs", "~> 0.1.0"
17
+ gem "solid-jobs"
27
18
  ```
28
19
 
29
- Then run:
30
-
31
- ```sh
32
- bundle install
33
- ```
34
-
35
- ## Delivery semantics
36
-
37
- SolidJobs provides **at-least-once** job delivery. A worker atomically moves a
38
- job from `queue:<name>` to a process reservation list before execution and
39
- removes it only after a successful ACK. Graceful shutdown requeues unfinished
40
- jobs; reservations owned by a crashed process are recovered into their
41
- original queues.
20
+ Then run `bundle install`.
42
21
 
43
- A process can still crash after the application side effect and before the
44
- ACK. The recovered job will then run again. Jobs must therefore be idempotent
45
- or implement an application-level deduplication key when duplicate side
46
- effects are unsafe. SolidJobs does not claim exactly-once execution.
22
+ ## Defining and submitting tasks
47
23
 
48
24
  ```ruby
49
- class HardJob
50
- include SolidJobs::Job
25
+ class RecalculateAccount
26
+ include SolidJobs::Task
51
27
 
52
- solid_jobs_options queue: "critical", retry: 10
28
+ task_options channel: "critical", max_failures: 10
53
29
 
54
- def perform(account_id)
30
+ def execute_task(account_id)
55
31
  Account.find(account_id).recalculate!
56
32
  end
57
33
  end
58
34
 
59
- HardJob.perform_async(42)
60
- HardJob.perform_in(30, 42)
35
+ RecalculateAccount.enqueue(42)
36
+ RecalculateAccount.enqueue_after(30, 42)
37
+ RecalculateAccount.schedule_at(Time.now + 300, 42)
38
+ RecalculateAccount.enqueue_many([[42], [43], [44]])
39
+ ```
40
+
41
+ The persisted envelope is specific to SolidJobs:
42
+
43
+ ```json
44
+ {
45
+ "id": "7ec33ed5-1b77-4bde-8960-bd77231f10ef",
46
+ "task": "RecalculateAccount",
47
+ "arguments": [42],
48
+ "channel": "critical",
49
+ "max_failures": 10,
50
+ "created_ms": 1790981000000,
51
+ "queued_ms": 1790981000001
52
+ }
61
53
  ```
62
54
 
63
- Run workers:
55
+ All internal Redis keys use the `solid_jobs:` namespace. Ready work is stored
56
+ under `solid_jobs:channel:<name>`; planned, retrying, discarded, node, claim,
57
+ attempt, and metric data use separate namespaced keys.
58
+
59
+ Run executors:
64
60
 
65
61
  ```sh
66
62
  bundle exec solid-jobs --require ./config/environment \
67
- --concurrency 8 --queue critical,3 --queue default
63
+ --concurrency 8 --channel critical,3 --channel default
64
+ ```
65
+
66
+ ## Configuration
67
+
68
+ ```ruby
69
+ SolidJobs.configure do |config|
70
+ config.channels = [["critical", 3], "default"]
71
+ config.channel_order = :weighted
72
+ config.concurrency = 8
73
+ config.shutdown_timeout = 25
74
+ config.default_task_options = {
75
+ channel: "default",
76
+ max_failures: 25,
77
+ }
78
+ end
68
79
  ```
69
80
 
70
- ## Tests
81
+ `channel_order` accepts `:weighted` for bounded weighted round-robin,
82
+ `:priority` for declaration-order priority, and `:shuffle` for random
83
+ selection from the weighted channel list.
71
84
 
72
- SolidJobs uses Minitest exclusively:
85
+ ## Interceptors
73
86
 
74
- ```sh
75
- # Unit and bounded Redis integration tests
76
- bundle exec rake test
87
+ Publication and execution use SolidJobs interceptors. An interceptor implements
88
+ `around(context)` and yields to continue:
77
89
 
78
- # Bounded concurrency and multi-process recovery stress
79
- STRESS_JOBS=10000 bundle exec rake stress
90
+ ```ruby
91
+ class TraceExecution
92
+ def around(context)
93
+ Telemetry.start(context.envelope.fetch("id"))
94
+ yield
95
+ ensure
96
+ Telemetry.finish
97
+ end
98
+ end
80
99
 
81
- # Reproducible random-fault campaign
82
- SOLID_JOBS_TORTURE=1 STRESS_JOBS=100000 bundle exec rake torture
100
+ SolidJobs.configure do |config|
101
+ config.execute_interceptors.use(TraceExecution)
102
+ end
103
+ ```
83
104
 
84
- # Re-run an exact failure sequence
85
- SOLID_JOBS_TORTURE=1 STRESS_JOBS=100000 STRESS_SEED=123456 bundle exec rake torture
105
+ Publication interceptors receive `SolidJobs::Publisher::Publication`; execution
106
+ interceptors receive `SolidJobs::Executor::Execution`.
86
107
 
87
- # Repeated fresh-process RESP/Ractor startup torture
88
- STARTUP_TORTURE_CYCLES=1000 \
89
- STARTUP_TORTURE_READERS=100 \
90
- bundle exec rake startup_torture
108
+ ## Failure handling
91
109
 
92
- # Long-running stability; defaults to 24 hours
93
- SOLID_JOBS_SOAK=1 SOLID_JOBS_SOAK_SECONDS=86400 bundle exec rake soak
110
+ Tasks default to 25 failures. A task can customize the delay or final action:
111
+
112
+ ```ruby
113
+ class ImportCatalog
114
+ include SolidJobs::Task
115
+
116
+ task_options max_failures: 8, retry_within: 3_600
117
+
118
+ retry_delay do |failure_count, error, envelope|
119
+ :drop if error.is_a?(InvalidCatalog)
120
+ end
121
+
122
+ after_final_failure do |envelope, error|
123
+ Alerts.catalog_import_failed(envelope.fetch("id"), error)
124
+ end
125
+ end
94
126
  ```
95
127
 
96
- The torture report reconciles enqueued, uniquely completed, duplicate,
97
- dead, queued, and reserved jobs. Any non-zero `LOST` value fails the test.
128
+ `retry_delay` may return a delay in seconds, `:drop`, or `:archive`. Without an
129
+ override, SolidJobs uses capped exponential backoff with equal jitter.
130
+
131
+ ## Delivery semantics
98
132
 
99
- Profile the reliable execution path independently from application work:
133
+ SolidJobs provides **at-least-once** delivery. An executor atomically claims a
134
+ task before execution and completes the claim only after `execute_task` returns.
135
+ Graceful shutdown requeues unfinished tasks. Claims owned by a crashed node are
136
+ recovered into their original channels.
100
137
 
101
- ```sh
102
- REDIS_URL=redis://127.0.0.1:6379/0 \
103
- HOT_PATH_JOBS=10000 \
104
- bundle exec rake benchmark:hot_path
138
+ A process can still crash after an application side effect and before claim
139
+ completion. The recovered task then runs again. Tasks must be idempotent or use
140
+ application-level deduplication when duplicate effects are unsafe.
141
+
142
+ See [docs/reliability.md](docs/reliability.md) for the state machine, claim
143
+ fencing, recovery rules, and Ruby Ractor caveats.
144
+
145
+ ## Node control
146
+
147
+ ```ruby
148
+ node = SolidJobs::Nodes.new.first
149
+ node.request_control(:pause)
150
+ node.request_control(:backtraces)
151
+ node.request_control(:shutdown)
105
152
  ```
106
153
 
107
- The report separates time and allocations for reservation, payload reuse,
108
- observability registration, dispatch/perform wrapping, observability cleanup,
109
- and fenced ACK. Fetch decodes the payload once for both reservation metadata
110
- and dispatch; its job body is intentionally empty.
154
+ Control requests are asynchronous and use the selected node's namespaced Redis
155
+ mailbox. Unknown actions raise `KeyError` without writing a request.
111
156
 
112
- Diagnose CPU scaling independently from Redis:
157
+ ## Lab
158
+
159
+ ```ruby
160
+ SolidJobs.testing!(:capture) do
161
+ RecalculateAccount.enqueue(42)
162
+ RecalculateAccount.captured
163
+ end
164
+
165
+ SolidJobs.testing!(:execute) do
166
+ RecalculateAccount.enqueue(42)
167
+ end
168
+ ```
169
+
170
+ Run the project suites:
113
171
 
114
172
  ```sh
115
- CPU_SCALING_JOBS=1000 \
116
- CPU_SCALING_ITERATIONS=210000 \
117
- bundle exec rake benchmark:cpu_scaling
173
+ bundle exec rake test
174
+ STRESS_JOBS=10000 bundle exec rake stress
175
+ SOLID_JOBS_TORTURE=1 STRESS_JOBS=100000 bundle exec rake torture
176
+ SOLID_JOBS_SOAK=1 SOLID_JOBS_SOAK_SECONDS=86400 bundle exec rake soak
118
177
  ```
119
178
 
120
- This runs the identical CPU loop through pure Ractors and through the
121
- SolidJobs in-memory dispatch path. Each 1/2/4/8 case uses fresh processes and
122
- reports execution latency, scaling efficiency, CPU-seconds per 1,000 jobs,
123
- RSS, allocations, GC time, heap slots, and malloc growth.
124
-
125
- ## Sidekiq comparison
126
-
127
- The separate `benchmark_sidekiq_solid-jobs` bundle runs Sidekiq and SolidJobs
128
- against the same isolated Redis server. It covers enqueue, bulk enqueue,
129
- CPU-bound processing, I/O-bound processing, mixed processing, and long-running
130
- stability. Every measurement runs in a fresh Ruby process; client order
131
- alternates and the default report uses the median of six repetitions.
132
-
133
- The current homogeneous CPU-processing reference uses Ruby 4.0.1,
134
- Sidekiq 8.1.7, SolidJobs 0.1.2, a 100,000-iteration integer workload, and
135
- 2,000 jobs per case:
136
-
137
- | Concurrency | Sidekiq jobs/s | SolidJobs jobs/s | SolidJobs scaling | Sidekiq CPU-s/1k | SolidJobs CPU-s/1k | Sidekiq RSS | SolidJobs RSS | Sidekiq alloc/job | SolidJobs alloc/job |
138
- |---:|---:|---:|---:|---:|---:|---:|---:|---:|---:|
139
- | 1 | 289 | 281 | 100.0% | 3.35 | 3.40 | 41.4 MiB | 81.8 MiB | 117.2 | 84.0 |
140
- | 2 | 296 | 549 | 97.7% | 3.38 | 3.44 | 41.7 MiB | 83.1 MiB | 116.8 | 79.7 |
141
- | 4 | 298 | 1,090 | 97.0% | 3.37 | 3.43 | 41.8 MiB | 79.5 MiB | 111.1 | 77.7 |
142
- | 8 | 298 | 2,053 | 91.4% | 3.36 | 3.67 | 42.4 MiB | 74.1 MiB | 108.1 | 74.3 |
143
-
144
- At eight concurrency units, SolidJobs reaches 2,053 jobs/s versus 298 jobs/s
145
- for Sidekiq. This is Ractor parallelism rather than equal CPU efficiency:
146
- SolidJobs consumes 752.6% CPU and 3.67 CPU-seconds per 1,000 jobs, while
147
- Sidekiq consumes 100.2% CPU and 3.36 CPU-seconds per 1,000 jobs. SolidJobs
148
- also uses more RSS, but reaches 27.71 jobs/s/MiB versus 7.03 for Sidekiq.
149
-
150
- These are local synthetic measurements, not application-capacity claims.
151
- Queue p95/p99 values in this run use sparse sampling and are excluded from the
152
- summary until the final latency campaign increases the sample count. Ruby
153
- 3.4.4 eight-Ractor results are also excluded: Ruby 3.4's Ractor scheduler
154
- crashed (concurrent TCP/RESP initialization, reproduced on macOS arm64 and
155
- Linux x86_64) or deadlocked VM-wide on a GC barrier under cross-Ractor
156
- message traffic (`test/support/ractor_barrier_repro.rb` reproduces it without
157
- SolidJobs).
158
- Ruby 4.0.1 passed the equivalent reproducers, and `StartupBarrier` serializes
159
- component initialization before releasing normal parallel processing.
160
- **Multi-Ractor servers are recommended on Ruby ≥ 4.0**; see
161
- `docs/reliability.md`.
162
-
163
- The project is under active development. The Web UI and commercial Sidekiq
164
- features are not part of the initial scope.
179
+ ## Migrating from Sidekiq
180
+
181
+ There is no transparent migration path because compatibility is intentionally
182
+ absent:
183
+
184
+ 1. Replace `include Sidekiq::Job` with `include SolidJobs::Task`.
185
+ 2. Replace `sidekiq_options` with `task_options`.
186
+ 3. Replace `perform_async`, `perform_in`, and `perform_bulk` with `enqueue`,
187
+ `enqueue_after`, and `enqueue_many`.
188
+ 4. Replace middleware with SolidJobs interceptors.
189
+ 5. Drain or export existing Sidekiq queues before switching. SolidJobs will not
190
+ consume them.
191
+ 6. Start SolidJobs with `--channel`; `--queue` is not accepted.
192
+
193
+ The Active Job adapter remains available as
194
+ `ActiveJob::QueueAdapters::SolidJobsAdapter`, but it writes only SolidJobs
195
+ envelopes and keys.