No release in over a year
Execute create/update/destroy operations asynchronously in your Rails app
2005
2006
2007
2008
2009
2010
2011
2012
2013
2014
2015
2016
2017
2018
2019
2020
2021
2022
2023
2024
 Dependencies

Development

>= 0

Runtime

 Project Readme

Create/Update/Destroy + Async

RailsJazz Listed on OpenSource-Heroes.com

A simple benchmark to grab your attention. Performance difference is noticeable. Performance

A very simple solution for a very simple but annoying problem. An example of problem that this gem solves.

#
# code that can be improved
#
class EventsAPIController < AppController
  def show
    @event = Event.find(params[:id])

    # scroll down to see how we can improve this line
    EventView.create(user: current_user)

    render json: @event
  end
end

How code above can be improved (and by improved I mean faster)? This API endpoint is responsible to return JSON info about Event.

What in this code can slowdown this API? Probably this: EventView.create(user: current_user)? This is the only one write operation that we have.

Now, imagine that in our app we have background jobs. We can start a new background job to create event in async mode. But what could be even simpler? Correct answer is to use this gem :) With help of this gem you can rewrite your code to this:

#
# improved version, it will work 100% faster
#
class EventsAPIController < AppController
  def show
    @event = Event.find(params[:id])

    EventView.create_async(user: current_user) # <--- here is a change

    render json: @event
  end
end

When we call .create_async, it will start a new background job and create new record in the background.

Usage

You have methods like:

  • .create_async
  • .save_async
  • .update_async
  • .destroy_async

Examples

# create
User.create_async(first_name: "John", last_name: "Smith")

# update
@user.update_async(first_name: "New Name")

# save
@user.first_name = "New Name"
@user.save_async

# destroy
@user.destroy_async

Ideal use case - when you just need to do an atomic action that won't require any logic with object.

Limitations:

  • you need to have some background job service in your app (as far I remember Sidekiq can be started within your app)
  • maybe it won't work with complex associations that are changed in the object (not tested)
  • validations will happen in the background, so you cannot write code like:
      if @user.save_async
        ... # this won't work as expected
      else
        ... # sorry validation happens only in the background
      end
  • you cannot refer variables in your code, because they will be created in the background. Example:
      @user = User.create_async(attrs)
      puts @user.full_name # this code won't work

Installation

Add this line to your application's Gemfile:

gem "create_update_destroy_async"

And then execute:

$ bundle

TODO

  • how to set queue where it will be executed
  • verify if it works on not with more complext objects, like accept nested attributes
  • options for jobs, like discard_on, priority, etc

Benchmark

  • rails s -e production
  • wrk -c100 http://127.0.0.1:3000/home/index1
  • stop server
  • rails s -e production
  • wrk -c100 http://127.0.0.1:3000/home/index2
  • repeat few times to be 100% sure

Development

You can start rails s in dummy app, and open http://localhost:3000/home/index1 and http://localhost:3000/home/index2.

In addition you need to start Sidekiq in the background.

Contributing

You are welcome to contribute.

License

The gem is available as open source under the terms of the MIT License.