2015-02-17 12 views
5

Tôi đang sử dụng Rails 4.2 và delay_job 4.0.6 làm phụ trợ ActiveJob của tôi.Trong Rails 4.2 kiểm tra xem một công việc đã được enqueued

Tôi có một công việc mà tôi muốn chỉ cho phép trong hàng đợi một lần. Công việc được đề cập mất hơn một phút để chạy. Nó được enqueued bởi một cuộc gọi lại trên một mô hình. Cuộc gọi lại sẽ kích hoạt thường xuyên hơn nhiều so với công việc có thể được hoàn thành. Công việc không cần phải xếp hàng nhiều lần trong tương lai.

Dưới đây là một số mã giả cho những gì tôi đang cố gắng hoàn thành.

# app/jobs/refresh_account_cache_job.rb 
class RefreshAccountCacheJob < ActiveJob::Base 
    def before_enqueue 
    skip if job_already_enqueued 
    end 

    def perform 
    Account.write_to_cache 
    end 

    def job_already_enqueued 
    # ? 
    end 
end 

Nếu một ví dụ của công việc đang chạy khi được gọi lại, nó vẫn phải được đặt trong tương lai. Tôi đang tìm một cách để có được công việc enqueued cho một hoạt động trong tương lai tối đa là 1 lần.

Tôi giả định rằng câu trả lời sẽ phải cụ thể đối với delay_job, nhưng nếu nó có thể được khái quát hóa thành ActiveJob thì sẽ tốt hơn.

+0

Bạn có thể sử dụng redis không? Như trong, bạn có nó được cài đặt trên ngăn xếp của bạn? –

+0

Tôi cần gắn bó với Postgres về dự án này. –

+0

Không yêu cầu bạn thay thế nó, nhưng nếu bạn có thể sử dụng redis cùng với Postgres, có thể có một giải pháp đơn giản. –

Trả lời

2

này có thể không phù hợp chính xác, nhưng nó sẽ giúp bạn chỉ đi đúng hướng:

def self.up 
    create_table :delayed_jobs, :force => true do |table| 
    table.integer :priority, :default => 0, :null => false 
    table.integer :attempts, :default => 0, :null => false 
    table.text  :handler,     :null => false 
    table.text  :last_error 
    table.datetime :run_at 
    table.datetime :locked_at 
    table.datetime :failed_at 
    table.string :locked_by 
    table.string :queue 
    table.timestamps 
end 

Vì vậy, bạn có thể thêm một cột trạng thái để bảng đó, sau đó chạy một truy vấn như thế này để lấy công việc và kiểm tra tình trạng của nó trước khi làm bất cứ điều gì khác.

Delayed::Job.where(queue: '<YOUR QUEUE>').where(id: params[:id]).status

Làm thế nào bạn sẽ thiết lập trạng thái, bạn yêu cầu? Vâng, sử dụng móc thành công trong các công việc bị trì hoãn. Nó trông giống như thế này:

def success(job) 
    update_status('success') 
end 

private 

def update_status(status) 
    job = Job.find job_id 
    job.status = status 
    job.save! 
end 

Hy vọng điều này sẽ hữu ích!

+0

Tôi đang cho rằng một thử. –

1

Tôi đang đăng những gì tôi đã kết thúc làm như một câu trả lời để nhận phản hồi về nó. Đây chỉ là một giải pháp có thể tôi đang thử nghiệm.

Trong công việc tôi đang kiểm tra danh sách công việc bị trì hoãn :: công việc để xem trình xử lý hiện tại có hiện diện hay không. Nếu tôi bỏ qua công việc.

# queue_job.rb 
class EnqueueJob < ActiveJob::Base 
    queue_as :default 

    def already_enqueued? 
    Delayed::Job.all.any? do |job| 
     job.handler.include?("EnqueueJobHandler") 
    end 
    end 

    def perform 
    unless already_enqueued? 
     # do stuff 
    end 
    end 
end 

Cho đến nay, việc này vẫn giữ cho công việc vượt quá hàng đợi. Nhược điểm là tôi không biết rằng tôi đang giữ bộ nhớ cache như là up-to-date như tôi muốn.

0

Điều này có thể quá đơn giản, nhưng tại sao không chỉ thêm biến lớp học, hãy nói @@running, đặt số true vào before_enqueue và xóa nó khi kết thúc công việc?

Sau đó, bạn có thể chỉ cần kiểm tra biến đó và bỏ qua enqueue nếu nó được đặt.

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