AsyncMagic

AsyncMagic is a lightweight Ruby gem that makes it effortless to add asynchronous method execution to your Ruby classes. With a simple async declaration, your methods will execute in a managed thread pool, providing non-blocking operations while maintaining clean, readable code.
Inspired by Rails async methods.
Features
- ✨ Simple
async declaration for asynchronous methods
- đź§µ Managed thread pool with configurable options
- đźš‚ Rails integration with ActiveRecord support
- 🎯 Support for both instance and class methods
- 📝 Built-in error logging
- ⚡ Non-blocking execution with Future objects
Installation
Add this line to your application's Gemfile:
gem 'async_magic'
$ bundle install
Usage
By default, AsyncMagic will include the methods in all Objects. But you can configure it to include in specific objects (ActiveRecord models, etc.) or manually include it in your classes.
See the Configuration for more details.
class UserHeavyLogic
async
def send_welcome_email(user)
end
async
def self.batch_process(users)
end
end
class UsersController < ApplicationController
def index
log_user_activity
end
private
async
def log_user_activity
end
end
More examples
- check if completed
- get the result
mailer = UserMailer.new
future = mailer.send_welcome_email(user)
future.completed?
result = future.value
- initializer to configure the thread pool
AsyncMagic.configure do |config|
config.include_in = :active_record
end
- configure the thread pool
AsyncMagic.configure do |config|
config.executor_options = {
min_threads: 10,
max_threads: 50,
auto_terminate: true,
idletime: 60,
max_queue: 0,
fallback_policy: :caller_runs
}
end
class MyService
include AsyncMagic
async
def risky_operation
raise "Something went wrong!"
end
end
The error will be logged and the future will contain the error
future = MyService.new.risky_operation
future.rejected?
future.reason
- manually include AsyncMagic
class DataProcessor
include AsyncMagic
async
def process_data(data)
end
end
processor = DataProcessor.new
future = processor.process_data(large_dataset)
if future.wait(5)
result = future.value
else
puts "Processing is taking too long!"
end
AsyncMagic.shutdown
Code style
Just use:
$ bundle exec standardrb
$ bundle exec standardrb --fix
Contributing
You are welcome to contribute to this gem.
License
This gem is available as open source under the terms of the MIT License.
Credits
Thanks AI to help me write this gem faster :)