Using Thread.new in :after_save on 1.9, why not?

Hello, can You please explain to me why we can’t use Thread.new in
:after_save?

Let’s suppose the following situation: we have a blog and using remote
search engine (in form of http service) to index it. So, after any
change to the blog post we should also make an http call to notify
search service about changes. In the code it will look something like
this:

class Post < ActiveRecord::Base
after_save do |model|
Thread.new do
# making remote HTTP call.
remote_search_engine.update model
end
end
end

class PostController < ActiveController::Base
def upate
post = Post.by_id(params[:id])
post.update_attributes params[:post]
render json: post
end
end

Theoretically it should work. It should update post, immediately return
JSON response,
and finish call to the search engine sometime later
But nobody does this, why?

For a very long time, I thought that nobody using this technique because
this external http call will blocks the whole VM, so it make no sense to
use it.
But a couple days ago I found that this is actually wrong, this http
call will not block the VM (Fibur as a prove
fibur.markdown · GitHub ).

So, now I wondering - what other problems are out there? Why nobody uses
this and use instead tools like delayed_job and resque?

Thanks!

On Thu, Dec 22, 2011 at 11:58 AM, Alexey P.
[email protected]wrote:

after_save do |model|
post.update_attributes params[:post]
this external http call will blocks the whole VM, so it make no sense to
use it.
But a couple days ago I found that this is actually wrong, this http
call will not block the VM (Fibur as a prove
fibur.markdown · GitHub ).

So, now I wondering - what other problems are out there? Why nobody uses
this and use instead tools like delayed_job and resque?

My guess would be because of the overhead in managing threads. If your
rails code is spawning a new thread after every save, that could get
dangerous really quickly. So then you would need some kind of thread
manager to make sure that threads are properly closing, that threads
aren’t
interfering with each other (what if you save a model twice in quick
succession and, for one reason or another, the first thread takes longer
to
complete so effectively the results of this thread win out in the end),
etc?

Yes, this make sense, but this is only one case from a lots of other
possibilities. For example, we can reduce the request time by fetching
user and post in parallel, like this:

user, post = [
Thread.new{User.by_id request.cookies[:user_id]},
Thread.new{Post.by_id params[:id]}
].collect(&:value)

Although in this case, there’s probably maybe some issues with MySQL
driver (more exactly with its C extension).
But in the case of HTTP requests (for CouchDB for example) this should
work.
But for some reasons nobody uses such technics.