2017-02-02 21 views
8

Tôi có một sự nghi ngờ rằng một số công việc đang hoạt động của chúng tôi đang biến mất nhưng tôi không biết tại sao. Dưới đây là một trong những tôi đã tìm thấy bằng chứng cho sự biến mất của nó, nhưng không phải là lý do tại sao.Điều gì có thể khiến Rails Active Jobs được lên lịch biến mất?

Trang web của chúng tôi sử dụng dịch vụ in trên đám mây bên ngoài. Chúng tôi bắt đầu công việc và sau đó kiểm tra trạng thái của họ. Đã tạo thành công bản in từ xa trên đám mây, chúng tôi tạo một công việc hoạt động để kiểm tra trạng thái ngay lập tức. Nếu nó được hoàn thành (thành công hay cách khác), nó được đánh dấu như vậy. Nếu không thì công việc kiểm tra trạng thái sẽ tạo một công việc khác, với một chút chậm trễ. Sự chậm trễ tăng lên mỗi lần.

Một kiểm tra trạng thái ngày hôm nay, nhật ký cho biết thời gian chờ đạt 128 giây. Nhưng kiểm tra trạng thái tiếp theo không xảy ra, và cũng không có lỗi trong nhật ký.

Chúng tôi sử dụng công việc hoạt động được hỗ trợ bởi công việc bị trì hoãn. Mã cho công việc kiểm tra trạng thái là dưới đây. Nó không thể thấy bất kỳ lỗ hổng nào trong logic mà sẽ không dẫn đến việc kiểm tra trạng thái được thu thập chính xác hoặc một lần thử khác với sự chờ đợi.

class CheckCloudPrintStatusJob < ApplicationJob 
    queue_as :default 

    def perform(cloud_print, count = 0) 
    cloud_print.update_status 

    unless cloud_print.finished? 
     count += 1 
     wait = 2**(count-1) 

     if count > 15 
     cloud_print.mark_as_failed 

     puts "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~" 
     puts "~~~~~~~~~~~~~~~~~~ Cloud printing ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~" 
     puts "Cloud print ##{cloud_print.id} failed" 
     puts "Finally waited #{wait} seconds and then cancelled." 
     puts "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~" 
     else 
     puts "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~" 
     puts "~~~~~~~~~~~~~~~~~~ Cloud printing ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~" 
     puts "Checking status of cloud print ##{cloud_print.id}" 
     puts "Waiting #{wait} seconds and then retrying." 
     puts "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~" 

     CheckCloudPrintStatusJob.set(wait: wait.seconds).perform_later(cloud_print, count) 
     end 
    end 
    end 
end 
+0

những gì xảy ra khi 'update_status' đặt ra một lỗi? bạn cũng có thể chia sẻ mã trong 'update_status'? –

Trả lời

4

Chính xác, không có lỗi trong logic đã nêu sẽ dẫn đến kiểm tra trạng thái được thu thập chính xác hoặc một lần thử khác đang chờ.

tôi đã xác minh rằng mã công việc của bạn cư xử thành công ngoài chờ đợi 128 giây với các thiết lập sau:

  • rails new dự án
  • delayed_job_active_record thêm vào Gemfile (chạy bundle install)
  • rails generate delayed_job:active_recordrake db:migrate để cài đặt đá quý và tạo bảng DB công việc bị trì hoãn
  • config.active_job.queue_adapter = :delayed_job trong config/application.rb
  • một CloudPrint < ApplicationRecord mô hình cơ bản với update_status, finished?mark_as_failed phương pháp trong app/models/cloud_print.rb
  • mã được cung cấp trong app/jobs/check_cloud_print_status_job.rb
  • enqueuing một công việc bằng cách chạy CheckCloudPrintStatusJob.perform_later(CloudPrint.create) qua Rails Bảng điều khiển (bin/rails c)

Kể từ khi chuỗi trên cư xử chính xác mà không có bất kỳ vấn đề nào, bạn cần phải mở rộng tìm kiếm của mình bằng cách cung cấp thêm complete and verifiable example thực sự tái tạo sự cố. Tải lên toàn bộ dự án Rails của bạn vào repo GitHub khi bạn có thể tái tạo vấn đề của mình một cách nhất quán hoặc điều tra các khía cạnh khác về cấu hình dự án và môi trường của bạn.Dưới đây là một số khả năng:

  • Có thể có logic trong lớp mô hình của bạn có thể làm tăng bất kỳ ngoại lệ nào;
  • Daemon xử lý công nhân có thể đã bị hủy bỏ hoặc bị giết;
  • Hàng công việc có thể đã bị xóa (ví dụ: qua rake jobs:clear)
  • Quy trình khác có thể đã sửa đổi và/hoặc xóa đối tượng mô hình đang được xử lý;
  • finished? có thể đã trả lại true sau khi update_status được gọi, khiến kiểm tra trạng thái cuối cùng không được in ngay cả khi quá trình xử lý hoàn tất thành công.

N.B. - Công việc bị trì hoãn hỗ trợ thử lại các công việc thất bại với độ trễ 5 seconds + N ** 4, trong đó N là số lần thử, không cần tự thực hiện lại logic này. Chỉ cần raise một ngoại lệ nếu cloud_print.finished? là sai, và bạn không cần bất kỳ mã chậm trễ tùy chỉnh khác:

class CheckCloudPrintStatusJob < ApplicationJob 
    queue_as :default 

    def perform(cloud_print) 
    raise 'Not ready' unless cloud_print.finished? 
    end 
end 
+0

Cảm ơn bạn đã phản hồi toàn diện. Trong khi câu trả lời của bạn không trực tiếp giải quyết vấn đề cho chúng tôi, thì điều đó giúp chúng tôi suy nghĩ về vấn đề có thể nằm ở đâu khác. Kỳ lạ thay, giải pháp dường như đã được (ngoài việc thêm rất nhiều an toàn hơn) để chuyển từ dj sang sidekiq. Rõ ràng là không nên tạo sự khác biệt, nhưng rõ ràng là vậy. – Simmo

0

Vì nó ngụ ý từ mã công việc, đối số cloud_print là một thể hiện của một số lớp Ruby (có vẻ như ActiveRecord :: Base). Đó không phải là một ý tưởng hay nói chung để có các đối tượng phức tạp làm đối số cho công việc nền vì các đối số này phải được tuần tự hóa thành chuỗi, json hoặc yaml. DelayedJob sử dụng các đối tượng được tuần tự hóa YAML và đôi khi có thể không khôi phục được một cá thể mô hình. Ví dụ: nếu công việc bị trì hoãn chạy dưới dạng gọi lại before_create - đối tượng mô hình chưa được lưu và không thể khôi phục được. Bạn có thể tìm thêm thông tin tại đây https://github.com/collectiveidea/delayed_job/wiki/Common-problems#jobs-are-silently-removed-from-the-database

+3

Kể từ Rails 5 (ít nhất), ActiveJob sử dụng GlobalId khi đi qua ActiveModel như mô tả ở đây http://guides.rubyonrails.org/active_job_basics.html#globalid Điều đó có nghĩa rằng chúng ta có thể vượt qua một đối tượng ActiceRecord, và nó sẽ lưu trữ Class + Id và không được tuần tự hoá các thuộc tính của đối tượng. Chúng tôi vẫn phải xử lý vấn đề sau với các giao dịch – tal

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