tags: automatically fix incorrect tag counts during maintenance.

* Automatically fix all tags with incorrect counts during daily
  maintenance (previously only tags with negative counts were fixed).
* Log fixed tags to NewRelic.
* Remove the ability to manually fix tag counts with the "Fix" button on
  the /tags listing. This is no longer necessary now that tags are
  fixed automatically.
This commit is contained in:
evazion
2019-09-25 17:33:15 -05:00
parent 03d9b3feca
commit bc34fb16a4
12 changed files with 36 additions and 89 deletions

View File

@@ -1,25 +0,0 @@
class TagCorrectionsController < ApplicationController
respond_to :html, :json, :xml
before_action :builder_only, only: [:new, :create]
def new
@correction = TagCorrection.new(params[:tag_id])
respond_with(@correction)
end
def show
@correction = TagCorrection.new(params[:tag_id])
respond_with(@correction)
end
def create
@correction = TagCorrection.new(params[:tag_id])
if params[:commit] == "Fix"
@correction.fix!
redirect_to tags_path(:search => {:name_matches => @correction.tag.name, :hide_empty => "no"}), :notice => "Tag will be fixed in a few seconds"
else
redirect_to tags_path(:search => {:name_matches => @correction.tag.name})
end
end
end

View File

@@ -1,8 +0,0 @@
class FixTagPostCountJob < ApplicationJob
queue_as :default
queue_with_priority 20
def perform(tag)
tag.fix_post_count
end
end

View File

@@ -15,7 +15,7 @@ module DanbooruMaintenance
ForumSubscription.process_all! ForumSubscription.process_all!
TagAlias.update_cached_post_counts_for_all TagAlias.update_cached_post_counts_for_all
PostDisapproval.dmail_messages! PostDisapproval.dmail_messages!
Tag.clean_up_negative_post_counts! regenerate_post_counts!
SuperVoter.init! SuperVoter.init!
TokenBucket.prune! TokenBucket.prune!
TagChangeRequestPruner.warn_all TagChangeRequestPruner.warn_all
@@ -38,6 +38,13 @@ module DanbooruMaintenance
rescue_exception(exception) rescue_exception(exception)
end end
def regenerate_post_counts!
updated_tags = Tag.regenerate_post_counts!
updated_tags.each do |tag|
DanbooruLogger.info("Updated tag count", tag.attributes)
end
end
def rescue_exception(exception) def rescue_exception(exception)
DanbooruLogger.log(exception) DanbooruLogger.log(exception)
raise exception raise exception

View File

@@ -4,14 +4,14 @@ class TagCorrection
include ActiveModel::Serializers::Xml include ActiveModel::Serializers::Xml
attr_reader :tag attr_reader :tag
delegate :category, :post_count, :real_post_count, to: :tag delegate :category, :post_count, to: :tag
def initialize(tag_id) def initialize(tag_id)
@tag = Tag.find(tag_id) @tag = Tag.find(tag_id)
end end
def attributes def attributes
{ post_count: post_count, real_post_count: real_post_count, category: category, category_cache: category_cache, tag: tag } { post_count: post_count, category: category, category_cache: category_cache, tag: tag }
end end
def category_cache def category_cache
@@ -19,7 +19,6 @@ class TagCorrection
end end
def fix! def fix!
FixTagPostCountJob.perform_later(tag)
tag.update_category_cache tag.update_category_cache
end end
end end

View File

@@ -99,24 +99,26 @@ class Tag < ApplicationRecord
Tag.where(:name => tag_names).update_all("post_count = post_count - 1") Tag.where(:name => tag_names).update_all("post_count = post_count - 1")
end end
def clean_up_negative_post_counts! def regenerate_post_counts!
Tag.where("post_count < 0").find_each do |tag| sql = <<~SQL
tag_alias = TagAlias.where("status in ('active', 'processing') and antecedent_name = ?", tag.name).first UPDATE tags
tag.fix_post_count SET post_count = true_count
if tag_alias FROM (
tag_alias.consequent_tag.fix_post_count SELECT tag, COUNT(*) AS true_count
end FROM posts, unnest(string_to_array(tag_string, ' ')) AS tag
end GROUP BY tag
) true_counts, tags AS old_tags
WHERE
tags.name = tag
AND tags.post_count != true_count
AND old_tags.id = tags.id
RETURNING tags.*, old_tags.post_count AS old_post_count
SQL
updated_tags = Tag.find_by_sql(sql)
updated_tags
end end
end end
def real_post_count
@real_post_count ||= Post.raw_tag_match(name).where("true /* Tag#real_post_count */").count
end
def fix_post_count
update_column(:post_count, real_post_count)
end
end end
module CategoryMethods module CategoryMethods

View File

@@ -145,9 +145,6 @@ class TagAlias < TagRelationship
post.update(tag_string: fixed_tags) post.update(tag_string: fixed_tags)
end end
end end
antecedent_tag.fix_post_count if antecedent_tag
consequent_tag.fix_post_count if consequent_tag
end end
end end

View File

@@ -1,19 +0,0 @@
<div id="c-tag-corrections">
<div id="a-new">
<h1>Fix Tag: <%= @correction.tag.name %></h1>
<div style="margin-bottom: 1em;">
<ul>
<li><strong>category actual</strong>: <%= @correction.category %></li>
<li><strong>category memcache</strong>: <%= @correction.category_cache || "none" %></li>
<li><strong>post count db cache</strong>: <%= @correction.post_count %></li>
<li><strong>post count actual:</strong> <%= @correction.real_post_count %></li>
</ul>
</div>
<%= form_tag(tag_correction_path(:tag_id => @correction.tag.id)) do %>
<%= submit_tag "Fix" %>
<%= submit_tag "Cancel" %>
<% end %>
</div>
</div>

View File

@@ -9,8 +9,5 @@
<li>|</li> <li>|</li>
<%= subnav_link_to "Posts (#{@tag.post_count})", posts_path(:tags => @tag.name) %> <%= subnav_link_to "Posts (#{@tag.post_count})", posts_path(:tags => @tag.name) %>
<%= subnav_link_to "Edit", edit_tag_path(@tag) %> <%= subnav_link_to "Edit", edit_tag_path(@tag) %>
<% if @tag.post_count < 1_000 %>
<%= subnav_link_to "Fix", new_tag_correction_path(:tag_id => @tag.id) %>
<% end %>
<% end %> <% end %>
<% end %> <% end %>

View File

@@ -21,9 +21,6 @@
<% if tag.editable_by?(CurrentUser.user) %> <% if tag.editable_by?(CurrentUser.user) %>
<%= link_to "edit", edit_tag_path(tag) %> <%= link_to "edit", edit_tag_path(tag) %>
<% end %> <% end %>
<% if CurrentUser.is_builder? %>
| <%= link_to "fix", new_tag_correction_path(:tag_id => tag.id) %>
<% end %>
</td> </td>
</tr> </tr>
<% end %> <% end %>

View File

@@ -260,7 +260,6 @@ Rails.application.routes.draw do
end end
resource :source, :only => [:show] resource :source, :only => [:show]
resources :tags do resources :tags do
resource :correction, :only => [:new, :create, :show], :controller => "tag_corrections"
collection do collection do
get :autocomplete get :autocomplete
end end

View File

@@ -41,7 +41,6 @@ Disallow: /static
Disallow: /tag_alias_corrections Disallow: /tag_alias_corrections
Disallow: /tag_alias_requests Disallow: /tag_alias_requests
Disallow: /tag_aliases Disallow: /tag_aliases
Disallow: /tag_corrections
Disallow: /tag_implication_requests Disallow: /tag_implication_requests
Disallow: /tag_implications Disallow: /tag_implications
Disallow: /tags Disallow: /tags
@@ -51,4 +50,4 @@ Disallow: /users
Disallow: /wiki_page_versions Disallow: /wiki_page_versions
Disallow: /wiki_pages/new Disallow: /wiki_pages/new
Disallow: /wiki_pages/revert Disallow: /wiki_pages/revert
Disallow: /wiki_pages/show_or_new Disallow: /wiki_pages/show_or_new

View File

@@ -274,13 +274,15 @@ class TagTest < ActiveSupport::TestCase
end end
end end
context "A tag with a negative post count" do context "A tag with an incorrect post count" do
should "be fixed" do should "be fixed" do
tag = FactoryBot.create(:tag, name: "touhou", post_count: -10) tag1 = FactoryBot.create(:tag, name: "touhou", post_count: -10)
post = FactoryBot.create(:post, tag_string: "touhou") tag2 = FactoryBot.create(:tag, name: "bkub", post_count: 10)
post = FactoryBot.create(:post, tag_string: "touhou bkub")
Tag.clean_up_negative_post_counts! Tag.regenerate_post_counts!
assert_equal(1, tag.reload.post_count) assert_equal(1, tag1.reload.post_count)
assert_equal(1, tag2.reload.post_count)
end end
end end
end end