This small library is intended to help creating asynchronous jobs
using Ruby and RabbitMQ via the Sneakers gem.
## Features
- Hooks: `.before(symbol, &block)`
- Serializers: `.serialize(loader:)`
- Helpers for defering method calls: `object.defer.method(*arguments)`
**Extra**
- A `GenericSerializer` handling classes and ActiveRecord objects
## Examples
Those examples are what we wish to achieve.
The name of the queue is the name of the class by default and can be reset
using sneakers' `.from_queue` method of the `YourClass::Worker`'s class.
### Hooks
``` ruby
class MyClass
include GenericWorker
before do
puts "Before processing"
end
work do |message|
puts "Working with #{message}"
ack!
end
end
MyClass.execute("my class")
# => Before processing
# => Working with my class
```
### Serializers
You can provide a Proc for the loader and/or the dumper keywords.
The dumper will be used when calling `MyClass.execute(message)` receiving
the `message` as argument. It should return a string. The loader will be
used when the message is poped from the RabbitMQ queue.
``` ruby
class MyClass
include GenericWorker
serialize loader: ->(message){ JSON.parse(message) },
dumper: ->(message){ JSON.generate(message) }
work do |message|
one, two = message
puts "Message is serialized and deserialized correctly"
puts "one: #{one}, two: #{two}"
ack!
end
end
MyClass.execute([1, "foo"])
# => Message is serialized and deserialized correctly
# => one: 1, two: foo
```
``` ruby
class MyClass
include GenericWorker
serialize GenericSerializer.new
work do |message|
klass, active_record_object = message
puts "Classes can be passed: #{klass.name} - #{klass.class}"
puts "Active record object can be passed too: #{active_record_object}"
ack!
end
end
MyClass.execute([String, User.find(1)])
# => Classes can be passed: String - Class
# => Active record object can be passed too:
```
### Helpers
Any class method can be defered:
``` ruby
class MyClass
include DeferableWorker
def self.my_method(user)
puts "Running my method on #{user}"
end
end
MyClass.defer.my_method(User.find(1))
# => Running my method on
```
An ActiveRecord::Base instance can be the receiver if it has an `id`:
``` ruby
class MyModel < ActiveRecord::Base
include DeferableWorker
def my_method
puts "Running my method on #{self}"
end
end
instance = MyModel.find(1)
instance.defer.my_method
# => Running my method on
```
Handling errors and results for the deferred methods is via `on_error` and
`on_success` keyword. You must return `ack!` or `reject!` here as in a
Sneakers' `work` method.
``` ruby
class MyModel < ActiveRecord::Base
include DeferableWorker
on_error do |exception|
puts "I just saved the day handling a #{exception}"
reject!
end
def my_method
puts "Running my method on #{self}"
raise StandardError
end
end
instance = MyModel.find(1)
instance.defer.my_method
# => Running my method on
# => I just saved the day handling a StandardError
```