docbrown/app/workers/articles/update_page_views_worker.rb
Daniel Uber ba590c1750
Load article before creating a page view for an invalid one (#15898)
* Load article before creating a page view for an invalid one

This should resolve a validation error in PageView.create! when the
article does not exist (perhaps it was deleted, or the user suspended,
or it was invalid data sent from the client).

This had been happening dozens of times per day for the last 10
months.

* Use an intention revealing symbol instead of calculated id

Since we only require that find_by not find anything, pass a symbol
that's not going to be the id for any article under any conditions.

As an added benefit, this provides a clear indication of the purpose
of the symbol, without needing to mentally confirm that

```sql
  SELECT * FROM articles
  WHERE id IN (
    SELECT (1 + MAX(id)) FROM articles
  ) LIMIT 1
```

actually never gives any articles back.
2021-12-29 09:48:34 -06:00

33 lines
1.1 KiB
Ruby

module Articles
class UpdatePageViewsWorker
include Sidekiq::Worker
sidekiq_options queue: :medium_priority,
lock: :until_executing,
on_conflict: :replace,
retry: false
def perform(create_params)
article = Article.find_by(id: create_params["article_id"])
return unless article
PageView.create!(create_params)
updated_count = article.page_views.sum(:counts_for_number_of_views)
if updated_count > article.page_views_count
article.update_column(:page_views_count, updated_count)
end
# PageViewsController#create called the method update_organic_page_views
# at the end. The relationship between the two was 12.5% chance (rand(8))
# and 1% chance (rand(100)), or roughly 12x more likely for page view
# updates vs. organic page view updates. We kept a similar relationship
# between the two workers, this one here is schedule after 2 minutes,
# organic page view updates after 25 minutes.
Articles::UpdateOrganicPageViewsWorker.perform_at(
25.minutes.from_now,
article.id,
)
end
end
end