docbrown/app/services/edge_cache/bust_article.rb
Daniel Uber c1a93ad3c3
Cleanup articles cache busting (#13467)
* Extract repeated calls to cache_bust.call to iteration over list

This mirrors what the EdgeCache::BustUser service looks like.

It might make sense to have cached_article_paths be a method accepting
a block and yielding paths, and including the collections cache paths
as well.

* Move article path information into a separate method

BustArticle.call now only knows to bust cache for each path associated
with the article, the information about which paths to clear is moved
to a separate `paths_for` method.

I may have gone overboard on this.

* Remove extra blank line
2021-04-23 09:35:40 -05:00

113 lines
3.2 KiB
Ruby

module EdgeCache
class BustArticle
TIMEFRAMES = [
[-> { 1.week.ago }, "week"],
[-> { 1.month.ago }, "month"],
[-> { 1.year.ago }, "year"],
[-> { 5.years.ago }, "infinity"],
].freeze
def self.call(article)
return unless article
article.purge
cache_bust = EdgeCache::Bust.new
paths_for(article) do |path|
cache_bust.call(path)
end
bust_home_pages(cache_bust, article)
bust_tag_pages(cache_bust, article)
end
def self.paths_for(article)
paths = [
article.path,
"/#{article.user.username}",
"#{article.path}/",
"#{article.path}?i=i",
"#{article.path}/?i=i",
"#{article.path}/comments",
"#{article.path}?preview=#{article.password}",
"#{article.path}?preview=#{article.password}&i=i",
"/api/articles/#{article.id}",
]
paths.each do |path|
yield path
end
yield "/#{article.organization.slug}" if article.organization.present?
return unless article.collection_id
article.collection.articles.find_each do |collection_article|
yield collection_article.path
end
end
def self.bust_home_pages(cache_bust, article)
if article.featured_number.to_i > Time.current.to_i
cache_bust.call("/")
cache_bust.call("?i=i")
end
if article.video.present? && article.featured_number.to_i > 10.days.ago.to_i
cache_bust.call("/videos")
cache_bust.call("/videos?i=i")
end
TIMEFRAMES.each do |timestamp, interval|
next unless Article.published.where("published_at > ?", timestamp.call)
.order(public_reactions_count: :desc).limit(3).ids.include?(article.id)
cache_bust.call("/top/#{interval}")
cache_bust.call("/top/#{interval}?i=i")
cache_bust.call("/top/#{interval}/?i=i")
end
if article.published && article.published_at > 1.hour.ago
cache_bust.call("/latest")
cache_bust.call("/latest?i=i")
end
cache_bust.call("/") if Article.published.order(hotness_score: :desc).limit(4).ids.include?(article.id)
end
private_class_method :bust_home_pages
def self.bust_tag_pages(cache_bust, article)
return unless article.published
article.tag_list.each do |tag|
if article.published_at.to_i > 2.minutes.ago.to_i
cache_bust.call("/t/#{tag}/latest")
cache_bust.call("/t/#{tag}/latest?i=i")
end
TIMEFRAMES.each do |timestamp, interval|
next unless Article.published.where("published_at > ?", timestamp.call).tagged_with(tag)
.order(public_reactions_count: :desc).limit(3).ids.include?(article.id)
cache_bust.call("/top/#{interval}")
cache_bust.call("/top/#{interval}?i=i")
cache_bust.call("/top/#{interval}/?i=i")
12.times do |i|
cache_bust.call("/api/articles?tag=#{tag}&top=#{i}")
end
end
next unless rand(2) == 1 &&
Article.published.tagged_with(tag)
.order(hotness_score: :desc).limit(2).ids.include?(article.id)
cache_bust.call("/t/#{tag}")
cache_bust.call("/t/#{tag}?i=i")
end
end
private_class_method :bust_tag_pages
end
end