Skip to content

Instantly share code, notes, and snippets.

@jtomaszewski
Created February 16, 2014 01:09
Show Gist options
  • Star 4 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save jtomaszewski/9027725 to your computer and use it in GitHub Desktop.
Save jtomaszewski/9027725 to your computer and use it in GitHub Desktop.
Allow instance methods to be delayed to Sidekiq
# Idea from http://krautcomputing.com/blog/2012/10/07/how-to-make-everything-background-processable-through-sidekiq/
#
# Usage:
#
# class Synchronization
# include Asyncable
# end
#
# Then:
# Synchronization.find(12).perform_async(:synchronize, 3, 2)
# will result in:
# Synchronization.find_by_async_id(12).synchronize(3, 2)
#
# NOTE: You can of course replace #async_id and .find_by_async_id methods =)
module Asyncable
extend ActiveSupport::Concern
%i[perform_async perform_in].each do |method_name|
define_method method_name do |*args|
Caller.send method_name, *args, {async_id: async_id, class_name: self.class.name}
end
end
alias_method :perform_at, :perform_in
protected
# Unique ID of this object, which will be used in #find_by_async_id() to get this object in async worker.
def async_id
id
end
module ClassMethods
# When executing the method in an async method, we'll find this object using this method.
def find_by_async_id(async_id)
find(async_id)
end
end
class Caller
include Sidekiq::Worker
def perform(*args)
options = args.pop
options['class_name'].constantize.find_by_async_id( options['async_id'] ).send(*args)
end
end
end
@jtomaszewski
Copy link
Author

Some another example:

class PostPublisher < SimpleDelegator
    attr_reader :post

    def initialize(post)
        @post = post
    end

    def self.find_by_async_id(id)
        new(Post.find(id))
    end

    def async_id
        post.id
    end

    def publish
      # publish on facebook and some other social services
    end
end

# usage in controller:
  def update
    if post.save
      PostPublisher.new(post).perform_async(:publish)
      # what worker will do:
      # PostPublisher.find_by_async_id(post.id).publish
    end
  end

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment