Created
October 7, 2026 07:29
-
-
Save ejoubaud/ee9c9b3d122cd25c1cf6aff3cc053e0b to your computer and use it in GitHub Desktop.
Ruby NATS worker: n threads pulling from m streams
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| # bin/nats_worker | |
| require_relative "../config/environment" | |
| Rails.application.eager_load! | |
| def backoff_delay(attempt) | |
| # 1s, 2s, 4s… capped at 3 days, with 50–100% jitter | |
| [2**(attempt - 1), 3 * 24 * 3600].min * (0.5 + rand * 0.5) | |
| end | |
| nc = NATS.connect(ENV.fetch("NATS_URL")) | |
| js = nc.jetstream | |
| stopping = false | |
| %w[TERM INT].each { |sig| trap(sig) { stopping = true } } | |
| threads = Integer(ENV.fetch("WORKER_THREADS", 5)).times.map do | |
| Thread.new do | |
| sub = js.pull_subscribe(nil, "rails-workers", stream: "EVENTS") | |
| until stopping | |
| begin | |
| msg = sub.fetch(1, timeout: 2).first | |
| job_metadata = { subject: msg.subject, attempt: msg.metadata.num_delivered } | |
| begin | |
| Rails.application.executor.wrap { Handlers.dispatch(msg.subject, msg.data) } | |
| msg.ack | |
| O11y.log(job_metadata.merge(status: :ok)) | |
| rescue => e | |
| O11y.log(job_metadata.merge(status: :error, error: e.class.name)) | |
| ErrorTracker.notify(e, job_metadata) | |
| msg.nak(delay: backoff_delay(job_metadata[:attempt])) | |
| end | |
| rescue NATS::IO::Timeout | |
| # nothing to fetch, loop again | |
| end | |
| end | |
| end | |
| end | |
| threads.each(&:join) | |
| nc.drain |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment