2009-05-22 27 views
28

Khi một tài nguyên mới được tạo ra và nó cần phải làm một số dài chế biến trước tài nguyên đã sẵn sàng, làm thế nào để tôi gửi xử lý mà đi vào nền nơi nó sẽ không giữ lên yêu cầu hiện tại hoặc khác lưu lượng truy cập vào ứng dụng web của tôi?Ruby on Rails: Làm thế nào để chạy mọi thứ trong nền?

trong mô hình của tôi:

class User < ActiveRecord::Base 
after_save :background_check 

protected 
def background_check 
    # check through a list of 10000000000001 mil different 
    # databases that takes approx one hour :) 
    if(check_for_record_in_www(self.username)) 
    # code that is run after the 1 hour process is finished. 
    user.update_attribute(:has_record) 
    end 
end 
end 

Trả lời

39

Bạn nên chắc chắn kiểm tra Railscasts sau:

Họ giải thích làm thế nào để chạy quá trình nền trong Rails trong mỗi thể cách (có hoặc không có aq ueue ...)

+2

Những ngày này, hầu hết được sử dụng/lựa chọn tốt nhất hỗ trợ là [sidekiq] (https://github.com/mperham/sidekiq), [resque ] (https://github.com/defunkt/resque) và [delay_job] (https://github.com/collectiveidea/delayed_job). IMHO, Sidekiq là tốt nhất cho hàng đợi thông lượng cao, và delay_job là hàng tốt nhất cho thông lượng rất thấp. –

+0

Một tùy chọn khác là [IronWorker] (http://www.iron.io) nếu bạn muốn xử lý nền "làm dịch vụ" và không bao giờ phải lo lắng về ý tưởng của máy chủ hoặc xếp hàng. IronMQ/IronWorker cũng cung cấp tính năng thử lại tự động, nhật ký tác vụ, webhook, v.v. Nó tích hợp độc đáo với Rails. Dưới đây là một số video: https://www.youtube.com/user/ironiodevelopers – Chad

7

Bắt đầu một quá trình riêng biệt, mà có lẽ là cách dễ dàng nhất thực hiện với system, thêm vào trước một 'nohup' và phụ thêm một '&' vào cuối của lệnh bạn vượt qua nó. (Hãy chắc chắn rằng các lệnh chỉ là một đối số chuỗi, không phải là một danh sách các đối số.)

Có nhiều lý do bạn muốn làm điều đó theo cách này, chứ không phải là, nói, cố gắng sử dụng chủ đề:

  1. Các chuỗi của Ruby có thể hơi phức tạp khi nói đến việc thực hiện I/O; bạn phải cẩn thận rằng một số điều bạn không làm cho toàn bộ quá trình chặn.

  2. Nếu bạn chạy một chương trình có tên khác, nó có thể dễ dàng nhận dạng trong 'ps', vì vậy bạn không vô tình nghĩ rằng đó là một FastCGI back-end hoang dã hoặc một cái gì đó, và giết nó.

Thực sự, quá trình bạn bắt đầu phải được "deamonized", xem lớp học Daemonize để được trợ giúp.

2

bạn lý tưởng muốn sử dụng máy chủ công việc nền hiện có thay vì viết của riêng bạn. những thông thường này sẽ cho phép bạn gửi một công việc và cung cấp cho nó một khóa duy nhất; sau đó bạn có thể sử dụng khóa để truy vấn định kỳ máy chủ việc làm cho trạng thái công việc của bạn mà không chặn ứng dụng web của bạn. here is a nice roundup của các tùy chọn khác nhau trên mạng.

0

gì về:

def background_check 
    exec("script/runner check_for_record_in_www.rb #{self.username}") if fork == nil 
end 

Chương trình "check_for_record_in_www.rb", sau đó sẽ chạy trong một tiến trình khác và sẽ có quyền truy cập vào ActiveRecord, có thể truy cập vào cơ sở dữ liệu.

1

Tôi thích sử dụng backgroundrb, nó đẹp cho phép bạn giao tiếp với nó trong suốt quá trình dài. Vì vậy, bạn có thể có cập nhật trạng thái trong ứng dụng đường ray của mình

1

Tôi nghĩ rằng spawn là một cách tuyệt vời để chia nhỏ quy trình của bạn, thực hiện xử lý ở chế độ nền và chỉ cho người dùng xác nhận rằng quá trình xử lý này đã được bắt đầu.

6

Tôi vừa thử nghiệm đá quý 'delay_job' vì nó hoạt động với nền tảng lưu trữ Heroku và nó rất dễ cài đặt !!

Thêm đá quý vào Gemfile, bundle install, rails g delayed_job, rake db:migrate Sau đó, bắt đầu xử lý hàng đợi;

RAILS_ENV=production script/delayed_job start 

Trong trường hợp bạn có một phương pháp gọi đó là quá trình lâu dài của bạn tức là

company.send_mail_to_all_users 

bạn thay đổi nó để;

company.delay.send_mail_to_all_users 

Kiểm tra đầy đủ các tài liệu trên github: https://github.com/collectiveidea/delayed_job

Các vấn đề liên quan