2012-11-12 28 views
12

Tôi có một ứng dụng ruby ​​trên đường ray trong đó tôi đang cố gắng tìm cách chạy mã một vài giây một lần.nhiệm vụ định kỳ đường ray

Tôi đã tìm thấy rất nhiều thông tin và ý tưởng bằng cách sử dụng cron, hoặc triển khai cron, nhưng chúng chỉ chính xác đến từng phút và/hoặc yêu cầu các công cụ bên ngoài. Tôi muốn khởi động tác vụ sau mỗi 15 giây hoặc lâu hơn và tôi muốn nó hoàn toàn nằm trong ứng dụng (nếu ứng dụng dừng lại, các tác vụ dừng lại và không có thiết lập bên ngoài).

Điều này đang được sử dụng để tạo nền dữ liệu bộ nhớ cache. Cứ sau vài giây, nhiệm vụ sẽ tập hợp một số dữ liệu, và sau đó lưu trữ nó trong một bộ nhớ cache được sử dụng bởi tất cả các yêu cầu của máy khách. Nhiệm vụ khá chậm, vì vậy nó cần chạy trong nền và không chặn các yêu cầu của máy khách.

Tôi khá mới với ruby, nhưng có nền perl mạnh, và cách tôi giải quyết điều này sẽ tạo ra một bộ đếm thời gian & xử lý mà dĩa, chạy mã và sau đó thoát khi hoàn tất.
Nó thậm chí còn đẹp hơn để chỉ mô phỏng một yêu cầu của khách hàng và có bản thân bộ điều khiển đường ray. Bằng cách này tôi có thể khởi động nhiệm vụ bằng cách nhấn URI cho nó (mặc dù vì nhiệm vụ sẽ chạy mỗi vài giây, tôi nghi ngờ tôi sẽ cần đến, nhưng có thể có sử dụng trong tương lai). Mặc dù nó sẽ là tầm thường để chỉ có bộ điều khiển gọi bất cứ phương thức nào được gọi bởi trình lập lịch biểu nhiệm vụ định kỳ (một khi tôi có một).

Trả lời

2

Nói chung, không có cách nào được xây dựng theo cách mà tôi biết để tạo một tác vụ định kỳ trong ứng dụng. Rails được xây dựng trên Rack và nó hy vọng sẽ nhận được yêu cầu http, làm điều gì đó, và sau đó trở lại. Vì vậy, bạn chỉ phải quản lý công việc định kỳ bên ngoài mình.

Tôi nghĩ rằng với tần suất bạn cần để chạy tác vụ, một giải pháp tốt có thể chỉ là viết cho bạn một tác vụ cào đơn giản lặp lại mãi mãi và khởi động cùng lúc bạn khởi động ứng dụng của mình một cái gì đó như Foreman. Quản đốc thường được sử dụng như thế này để quản lý việc khởi động/tắt công nhân nền cùng với các ứng dụng của họ. Về sản xuất, bạn có thể muốn sử dụng một cái gì đó khác để quản lý các quy trình, như Monit.

+0

Tôi đã kết thúc chỉ việc tạo một công cụ đơn giản mà dĩa khi ứng dụng đường ray bắt đầu và định kỳ chạy một danh sách các nhiệm vụ. Mỗi vòng lặp thông qua nó sẽ kiểm tra xem cha mẹ vẫn còn sống và bỏ đi nếu không. – Patrick

0

Sử dụng thứ gì đó như công việc bị trì hoãn và thường xuyên truy cập lại mọi thứ?

+0

Anh ấy nói anh ấy muốn nó như một phần của ứng dụng và chỉ tồn tại khi ứng dụng của anh ấy đang chạy. Có vẻ như quá mức cần thiết? – Altonymous

+0

Đá là nó sẽ cần phải chạy trong một quy trình mới, do đó, quá trình web có thể tiếp tục phục vụ các yêu cầu web. Vì vậy, bạn có thể xây dựng máy chủ forking của riêng bạn ... hoặc chỉ sử dụng lại các thư viện hiện có. – DGM

10

tôi muốn đề nghị bất cứ khi nào đá quý https://github.com/javan/whenever

Nó cho phép bạn chỉ định một lịch trình như:

every 15.minutes do 
    MyClass.do_stuff 
end 

Không có công việc cron lịch hoặc monkeying với các dịch vụ bên ngoài.

+1

Bạn phải cẩn thận với Bất cứ khi nào, vì nó phải bắt đầu lên dụ Rail mỗi lần cho một nhiệm vụ. Có sự chậm trễ giữa thời điểm tác vụ được lên lịch bắt đầu và khi Rail kết thúc khởi tạo. – mguymon

+2

Tôi nghĩ rằng bất cứ khi nào đơn vị thời gian nhỏ nhất là phút, bạn không thể sử dụng 'giâys' với nó. – t00ny

2

Bạn có thể có thể viết bạn sở hữu phương pháp, một cái gì đó giống như

class MyWorker 
    def self.work 
    #do you work 
    sleep 15 
    end 
end 

chạy nó với rails runner MyWorker.work Sẽ có một quá trình riêng biệt chạy ở chế độ nền

Hoặc bạn có thể sử dụng một cái gì đó như Resque, nhưng đó là một cách tiếp cận khác. Nó hoạt động như thế: một cái gì đó thêm một nhiệm vụ vào hàng đợi, trong khi đó một nhân viên đang tìm nạp bất kỳ công việc nào trong hàng đợi và cố gắng hoàn thành nó.

Vì vậy, điều đó tùy thuộc vào nhu cầu của riêng bạn.

0

Sử dụng máy chủ mỏng hoặc khác sử dụng eventmachine, sau đó chỉ sử dụng bộ tính giờ là một phần của sự kiện. Ví dụ: trong config/application.rb

EM.add_periodic_timer(2) do 
    do_this_every_2_sec 
end 
Các vấn đề liên quan