2012-03-12 40 views
5

Đối với tất cả những điều sau đây giả định sau đây:tính toán thuộc tính hệ quả với một hệ thống xếp hàng

  • ray v3.0
  • ruby ​​v1.9
  • resque

Chúng tôi có 3 mô hình:

  • Sản phẩm belongs_to: sku, belongs_to: loại
  • Sku has_many: sản phẩm, belongs_to: loại
  • Thể loại has_many: sản phẩm, has_many: dòng sản phẩm

Khi chúng tôi cập nhật các sản phẩm (giả sử chúng ta vô hiệu hóa nó) chúng ta cần phải có một số điều xảy ra với sku và thể loại có liên quan. Điều này cũng đúng cho khi sku được cập nhật.

thích hợp cách để đạt được điều này là có after_save trên mỗi mô hình kích hoạt sự kiện cập nhật của các mô hình khác.

dụ:

products.each(&:disable!) 
# after_save triggers self.sku.products_updated 
# and self.category.products_updated (self is product) 

Bây giờ nếu chúng ta có 5000 sản phẩm chúng tôi đang ở trong một điều trị. Các thể loại tương tự có thể nhận được cập nhật hàng trăm lần và hog cơ sở dữ liệu trong khi làm như vậy.

Chúng tôi cũng có một hệ thống xếp hàng đẹp, vì vậy cách thức cập nhật sản phẩm thực tế hơn sẽ là products.each(&:queue_disable!) mà chỉ đơn giản là tung 5000 nhiệm vụ mới vào hàng đợi đang hoạt động. Tuy nhiên, vấn đề về cập nhật danh mục 5000 vẫn tồn tại.

Có cách nào để tránh tất cả các cập nhật đó trên db không?

Làm cách nào để có thể nối tất cả danh mục.products_updated cho từng danh mục trong hàng đợi?

+0

Tại sao bạn phải cập nhật danh mục khi sản phẩm bị thay đổi? Nó là một truy cập một mức giá trung bình hoặc những gì? Nếu vậy, hãy bỏ bộ đệm truy cập và tính toán nó khi cần hoặc sử dụng http://redis.io/. –

Trả lời

0

Thực hiện cập nhật phụ thuộc trong các cuộc gọi SQL đơn lẻ. #update_all sẽ cập nhật nhiều bản ghi cùng một lúc. Ví dụ,

Trong một callback after_update, cập nhật tất cả các giá trị cột phụ thuộc:

class Category 
    after_update :update_dependent_products 

    def update_dependent_products 
    products.update_all(disabled: disabled?) if disabled_changed? 
    end 
end 

Nếu đó là quá chậm, di chuyển nó vào một công việc resque:

class Category 
    after_update :queue_update_dependent_products 

    def update_dependent_products 
    products.update_all(disabled: disabled?) if disabled_changed? 
    end  

    def queue_update_dependent_products 
    Resque.enqueue(Jobs::UpdateCategoryDependencies, self.id) if disabled_changed? 
    end 
end 

class Jobs::UpdateCategoryDependencies 
    def self.perform(category_id) 
    category = Category.find_by_id(category_id) 
    category.update_dependent_products if category 
    end 
end 

làm những điều tương tự cho callbacks mô hình khác.

+0

Những gì tôi đang cố gắng thực hiện theo cách khác: tôi cập nhật một loạt sản phẩm và mỗi bản cập nhật phải truyền cho danh mục nhưng sẽ tốt hơn nếu tất cả các bản cập nhật sản phẩm được thực hiện trước và sau đó chỉ là một cập nhật cho từng danh mục bị ảnh hưởng . – Kostas

+0

OK Tôi hiểu lầm những gì bạn đang hỏi. Tôi đã thêm một câu trả lời khác và sẽ để lại câu trả lời này. – tee

2

Bạn có thể đảm bảo cập nhật danh mục duy nhất cho tất cả các sản phẩm bằng cách sử dụng một vài plugin Resque: Resque Unique JobResque Scheduler.

Trì hoãn thực hiện công việc để cập nhật danh mục một chút (tuy nhiên phải mất nhiều thời gian để gọi tất cả các cập nhật sản phẩm) và đảm bảo mỗi công việc là duy nhất bằng cách bao gồm mô-đun công việc duy nhất. Unique Job sử dụng các paramaters của công việc, vì vậy nếu bạn cố gắng xếp hàng 2 công việc với category_id 123, nó bỏ qua thứ hai kể từ khi công việc đã được xếp hàng đợi.

class Product 
    after_save :queue_category_update 

    def queue_category_update 
    Resque.enqueue_at(1.minute.from_now, Jobs::UpdateCategory, category.id) if need_to_update_category? 
    end 
end 

module Jobs 
    module UpdateCategory 
    include Resque::Plugins::UniqueJob 

    def self.perform(category_id) 
     category = Category.find_by_id(category_id) 
     category.update_some_stuff if category 
    end 
    end 
end 
Các vấn đề liên quan