Isn’t defining a job class for each async execution unit too much boilerplate?

Let’s try to implement seamless async execution in Ruby, using ActiveJob and proxy objects!

https://kzone.winosx.com/posts/asynchronous-method-calls-using-rails-s-activejob

#Ruby #Rails #ActiveJob

Asynchronous method calls using Rails’s ActiveJob

ActiveJob is great – but every time you need to perform some kind of delayed execution, you need to create a new job class for it. Something like: class DestroyAccountJob < ActiveJob def perform(account) account.destroy! end end # In the code, this will be used like: DestroyAccountJob.perform_later(account) And ideally, the job #perform method should fit on a single line: no complex code in the job itself, to make it easier to test. But many other programming languages allow performing any method call in the background, without needing to declare a specific class. Could we cut the boilerplate also in Ruby? Turns out we can. Introducing AsyncExecutor This is a small toy snippet, to call any method in a background job. No need to define custom job classes! The simplest usage looks like this: include AsyncExecutor # Call `self.destroy!` in a background job perform_later(:destroy!) It will create and enqueue a AsyncExecutorJob, that will perform the given method. And we also get more advanced usages, using a Proxy object: balance = AccountBalance.create!(account: account) start_date = 3.months.ago end_date = Time.now # 1. With a method name balance.perform_later(:compute_balance, start_date:, end_date:) # 2. With a proxy object balance.perform_later.compute_balance(start_date:, end_date:) # 3. With a block balance.perform_later do compute_balance(start_date:, end_date:) end The code Only two files: # app/lib/active_job/async_executor.rb # Perform any action later (by enqueuing an ad-hoc job), without needing to define a new ActiveJob subclass. module ActiveJob::AsyncExecutor # Internal class. Converts each method called on `target` into an asynchronous job. class Proxy # @param target [StandardObject] def initialize(target) @target = target end def method_missing(method, *args, &block) AsyncExecutorJob.perform_later(@target, method, *args) end end # Call the given method later, in an ad-hoc job. # # @overload perform_later(method) # Invoke the given method on `self` later. # @param method [String, Symbol, nil] the name of the method to call # @return [Proxy] # @example # perform_later(:compute_balance, start_date:, end_date:) # # @overload perform_later() # Return a proxy to `self`, that will execute methods called on it later. # @return [Proxy] # @example # balance.perform_later.compute_balance(start_date:, end_date:) # # @overload perform_later{} # Evaluate the block in the receiver's context, and execute methods called on it later. # @yield [] a block evaluated in the receiver's context (optional) # @return [Proxy] # @example # balance.perform_later { compute_balance(start_date:, end_date:) } def perform_later(method = nil, *args, &block) proxy = Proxy.new(self) if block_given? proxy.instance_eval(&block) elsif method proxy.public_send(method, *args) else proxy end end end # app/jobs/async_executor_job.rb # See ActiveJob::AsyncExecutor class AsyncExecutorJob < ApplicationJob def perform(target, method, *args) target.public_send(method, *args) end end How does it work? The AsyncExecutor::Proxy object convert method calls into a job invocation. The receiver and its arguments are serialized using ActiveJob usual mechanisms – which means for instance that ActiveRecord objects get serialized into a neat and compact globalID. Should I use this in production? A nice property of class-based jobs is that is makes queuing and debugging easier: you can enqueue some jobs in specific queues, and get a neat dashboard with a description of all your jobs. Using AsyncExecutor#perform_later means that all invocations will be mixed in the same queue, and harder to debug. But for small systems, I’m curious of how it can reduce the boilerplate. It is small, monkey-patch-free, and works with any ActiveJob backend. Fell free to experiment with it. Prior art Sidekiq’s delay: a similar idea, but removed in 2022, to avoid monkey-patching and serialization of large objects. AsyncExecutor doesn’t monkey-patch, and uses ActiveJob’s lightweight serialization. perform-later: a nice gem, independent from ActiveJob (which means it can invoke on any Ruby object). However you have to handle serialization yourself, and it is tied to Sidekiq.

Kzone

SolidQueue, the default ActiveJob's adapter in Rails, is very cool. But there is a catch - it needs 1Gb RAM to make all things out of the box working fine. That means it's not good for Heroku default Dynos. Surprise - https://github.com/rails/solid_queue/issues/330#issuecomment-3387827039

#rails #solidqueue #activejob #heroku

Need advice on Solid Queue's memory usage · Issue #330 · rails/solid_queue

Ruby: 3.3.4 Rails: 7.2.1 Solid Queue: 0.7.0, 0.8.2 I run a Rails App on AWS EC2 instance with 1G of memory. I notice the solid queue process takes up 15-20% of the instance's memory, which becomes ...

GitHub

I'm adding background jobs to my new app (Rails7.2 + SolidQueue), and not sure how things should be designed.
I need to run daily job to generate notifications on user-created task due/reminder date.

Should I:

1) create one job that iterates all relevant tasks and generates notifications? (might get slow with more users)

2) have one job that iterates tasks, and creates separate job for every relevant task?

3) something else?

#rubyonrails #activejob #SolidQueue

Sidekiq remains the fastest and most robust job processing system for Ruby on Rails and ActiveJob.

Our latest article explores how to work with scheduled jobs in Sidekiq.

Give it a read!

https://www.honeybadger.io/blog/sidekiq-background-jobs/?utm_source=mastodon&utm_medium=social

@sidekiq @getajobmike

#Ruby #RubyOnRails #Sidekiq #ActiveJob #Programming

The ultimate guide to Sidekiq scheduled jobs

Unlock the power of background processing in Ruby with Sidekiq. Learn how to create, schedule, and manage background jobs with and without ActiveJob

Honeybadger Developer Blog

Picture this: you're six months into a fresh Rails app that processes business-critical jobs with Solid Queue—and you deployed a bug that is wreaking havoc in thousands of jobs. How do you find them?

You'll wish you'd read our latest article from Jeffery Morhous!

https://www.honeybadger.io/blog/solid-queue-lifecycle/?utm_source=mastodon&utm_medium=social

#Ruby #RubyOnRails #SolidQueue #ActiveJob #SQlite

How Solid Queue works under the hood

Wondering how Solid Queue works on the inside? Read this article to follow a Solid Queue job from enqueue to completion.

Honeybadger Developer Blog
Sidekiq + Redis + ActiveJobでLINE定期通知機能を実装してみた - Qiita

はじめに個人開発にて、Sidekiq、Redis、ActiveJobを組み合わせたLINE通知機能を実装しました。備忘録として、実装の流れをまとめていきたいと思います!▼個人開発についてまとめ…

Qiita
🌖 Ruby on Rails 的 LiteStack 簡介 | AppSignal Blog
➤ Ruby on Rails 的 LiteStack 簡介
https://blog.appsignal.com/2023/09/27/an-introduction-to-litestack-for-ruby-on-rails.html
本文介紹 LiteStack,一個一站式解決方案,可在單臺機器上託管和處理所有生產數據。LiteStack 使用 SQLite 提供數據庫、ActiveJob、ActionCable 和 ActiveSupport::Cache 存儲。此外,本文還介紹了 Litestream 和 StableDiffusion,並提供了一個示例 Rails 應用程序。
+ 這篇文章提供了很好的 LiteStack 簡介,並且還有一個有趣的示例應用程序。
+ 很棒的文章,對於 Ruby on Rails
#Ruby on Rails #LiteStack #SQLite #ActiveJob #ActionCable #LiteCache #Litestream
An Introduction to LiteStack for Ruby on Rails | AppSignal Blog

In the first part of this series, we'll set up an example Rails application and introduce the basics of LiteStack.

AppSignal Blog

Is there a document somewhere that explains what a new #rails #ActiveJob queue adapter should implement? An interface specification of sorts?

Seems I'll go read the code, then.

Upgrade from Ruby 2 to Ruby 3 with confidence—and no ArgumentErrors popping up…

🚀 If not, Francois can help you fix them. Read what our Sr. Engineer recommends: https://www.fastruby.io/blog/custom-deprecation-behavior.html?utm_source=Mastodon&utm_medium=Organic&utm_campaign=Blogpromo&utm_term=safeguardingfromdeprecation&utm_content=Gif&utm_id=

#rubyonrails #railsupgrade #activejob #sidekiq

Safeguarding From Deprecation Regressions During an Upgrade - FastRuby.io | Rails Upgrade Service

When doing an upgrade, you can't expect the rest of the team to stop working on the code. How do you ensure they can continue working without re-introducing a deprecation that was fixed?

Safeguarding from Deprecation Regressions During an Upgrade by @arieljuod
Safeguarding From Deprecation Regressions During an Upgrade - FastRuby.io | Rails Upgrade Service

When doing an upgrade, you can't expect the rest of the team to stop working on the code. How do you ensure they can continue working without re-introducing a deprecation that was fixed?

Safeguarding from Deprecation Regressions During an Upgrade by @arieljuod