add new tag alias correction helper

This commit is contained in:
albert
2013-03-05 22:08:48 -05:00
parent e10f15d2db
commit d9a17d2378
11 changed files with 185 additions and 16 deletions

View File

@@ -0,0 +1,21 @@
class TagAliasCorrectionsController < ApplicationController
before_filter :moderator_only
def new
@correction = TagAliasCorrection.new(params[:tag_alias_id])
end
def create
@correction = TagAliasCorrection.new(params[:tag_alias_id])
if params[:commit] == "Fix"
@correction.fix!
end
redirect_to tag_alias_correction_path(:id => params[:tag_alias_id])
end
def show
@correction = TagAliasCorrection.new(params[:tag_alias_id])
end
end

View File

@@ -143,7 +143,7 @@ protected
when "moderator/dashboards"
/^\/moderator/
when "tag_aliases"
when "tag_aliases", "tag_alias_corrections"
/^\/tag_aliases/
when "tag_implications"

View File

@@ -40,7 +40,7 @@ class Cache
start_time = Time.now
value = MEMCACHE.get key.slice(0, 200)
elapsed = Time.now - start_time
ActiveRecord::Base.logger.debug('MemCache Get (%0.6f) %s' % [elapsed, key])
ActiveRecord::Base.logger.debug('MemCache Get (%0.6f) %s -> %s' % [elapsed, key, value])
if value.nil? and block_given? then
value = yield
MEMCACHE.set key, value, expiry
@@ -64,7 +64,7 @@ class Cache
start_time = Time.now
MEMCACHE.set key, value, expiry
elapsed = Time.now - start_time
ActiveRecord::Base.logger.debug('MemCache Set (%0.6f) %s' % [elapsed, key])
ActiveRecord::Base.logger.debug('MemCache Set (%0.6f) %s -> %s' % [elapsed, key, value])
value
rescue MemCache::MemCacheError => err
ActiveRecord::Base.logger.debug "MemCache Error: #{err.message}"

View File

@@ -0,0 +1,60 @@
class TagAliasCorrection
attr_reader :tag_alias_id, :tag_alias, :hostname
delegate :antecedent_name, :consequent_name, :to => :tag_alias
def initialize(tag_alias_id, hostname = Socket.gethostname)
@tag_alias_id = tag_alias_id
@tag_alias = TagAlias.find(tag_alias_id)
@hostname = hostname
end
def to_json(options = {})
statistics_hash.to_json
end
def statistics_hash
@statistics_hash ||= {
"antecedent_cache" => Cache.get("ta:" + Cache.sanitize(tag_alias.antecedent_name)),
"consequent_cache" => Cache.get("ta:" + Cache.sanitize(tag_alias.consequent_name)),
"antecedent_count" => Tag.find_by_name(tag_alias.antecedent_name).try(:post_count),
"consequent_count" => Tag.find_by_name(tag_alias.consequent_name).try(:post_count)
}
end
def fill_hash!
Net::HTTP.start(hostname, 80) do |http|
http.request_get("/tag_aliases/#{tag_alias_id}/correction.json") do |res|
if res === Net::HTTPSuccess
json = JSON.parse(res.body)
statistics_hash["antecedent_cache"] = json["antecdent_cache"]
statistics_hash["consequent_cache"] = json["consequent_cache"]
end
end
end
end
def each_server
Danbooru.config.all_server_hosts.each do |host|
other = TagAliasCorrection.new(tag_alias_id, host)
if host != Socket.gethostname
other.fill_hash!
end
yield other
end
end
def clear_cache
tag_alias.clear_cache
end
def fix!
clear_cache
Post.raw_tag_match(tag_alias.antecedent_name).each do |post|
post.save
end
tag_alias.antecedent_tag.fix_post_count if tag_alias.antecedent_tag
tag_alias.consequent_tag.fix_post_count if tag_alias.consequent_tag
end
end

View File

@@ -34,12 +34,14 @@ class Tag < ActiveRecord::Base
end
module CountMethods
def counts_for(tag_names)
select_all_sql("SELECT name, post_count FROM tags WHERE name IN (?)", tag_names)
module ClassMethods
def counts_for(tag_names)
select_all_sql("SELECT name, post_count FROM tags WHERE name IN (?)", tag_names)
end
end
def fix_post_count
update_column(:post_count, Post.tag_match("#{name} status:any").count)
update_column(:post_count, Post.raw_tag_match(name).count)
end
end
@@ -462,7 +464,7 @@ class Tag < ActiveRecord::Base
end
include ApiMethods
extend CountMethods
include CountMethods
extend ViewCountMethods
include CategoryMethods
extend StatisticsMethods

View File

@@ -94,22 +94,17 @@ class TagAlias < ActiveRecord::Base
def clear_cache(host = Socket.gethostname)
Cache.delete("ta:#{Cache.sanitize(antecedent_name)}")
Cache.delete("ta:#{Cache.sanitize(consequent_name)}")
end
def update_cache
Cache.put("ta:#{Cache.sanitize(antecedent_name)}", consequent_name)
Cache.delete("ta:#{Cache.sanitize(consequent_name)}")
end
def update_posts
Post.tag_match("#{antecedent_name} status:any").find_each do |post|
escaped_antecedent_name = Regexp.escape(antecedent_name)
fixed_tags = post.tag_string.sub(/(?:\A| )#{escaped_antecedent_name}(?:\Z| )/, " #{consequent_name} ").strip
CurrentUser.scoped(creator, creator_ip_addr) do
post.update_attributes(
:tag_string => fixed_tags
)
end
Post.raw_tag_match(antecedent_name).each do |post|
post.save
end
end
end

View File

@@ -0,0 +1,25 @@
<h1>Tag Alias Correction: <%= @correction.antecedent_name %> -&gt; <%= @correction.consequent_name %></h1>
<p>Because tag aliases are cached in memory, they may go out of sync. This action will clear out the cache and fix and lingering posts.</p>
<% @correction.each_server do |correction| %>
<div style="margin-bottom: 1em;">
<h2>Server: <%= Socket.gethostname %></h2>
<ul>
<li><strong><%= @correction.antecedent_name %></strong> aliased to <strong><%= @correction.statistics_hash["antecedent_cache"] %></strong> in cache</li>
<li><strong><%= @correction.consequent_name %></strong> aliased to <strong><%= @correction.statistics_hash["consequent_cache"] %></strong> in cache</li>
<li><strong><%= @correction.antecedent_name %></strong> count is <%= @correction.statistics_hash["antecedent_count"] %></li>
<li><strong><%= @correction.consequent_name %></strong> count is <%= @correction.statistics_hash["consequent_count"] %></li>
</ul>
</div>
<% end %>
<p>You can try to fix this alias. This will clear the cache and re-save all posts associated with <strong><%= @correction.antecedent_name %></strong>.</p>
<%= form_tag(tag_alias_correction_path) do %>
<%= hidden_field "tag_alias_id", params[:tag_alias_id] %>
<%= submit_tag "Fix" %>
<%= submit_tag "Cancel" %>
<% end %>
<%= render "tag_aliases/secondary_links" %>

View File

@@ -0,0 +1 @@
<%= raw @correction.to_json %>

View File

@@ -38,6 +38,10 @@
<% if tag_alias.is_pending? %>
| <%= link_to "Approve", approve_tag_alias_path(tag_alias), :remote => true, :method => :post %>
<% end %>
<% if CurrentUser.is_moderator? %>
| <%= link_to "Fix", tag_alias_correction_path(:tag_alias_id => tag_alias.id) %>
<% end %>
<% end %>
</td>
</tr>

View File

@@ -157,6 +157,7 @@ Danbooru::Application.routes.draw do
end
end
resources :tag_aliases do
resource :correction, :only => [:new, :create, :show], :controller => "TagAliasCorrections"
member do
delete :cache
post :approve
@@ -165,6 +166,7 @@ Danbooru::Application.routes.draw do
get :general_search
end
end
resource :tag_alias_correction, :only => [:new, :create, :show]
resources :tag_implications do
member do
post :approve

View File

@@ -0,0 +1,59 @@
require 'test_helper'
class TagAliasTest < ActiveSupport::TestCase
context "A tag alias" do
setup do
@mod = FactoryGirl.create(:moderator_user)
CurrentUser.user = @mod
CurrentUser.ip_addr = "127.0.0.1"
MEMCACHE.flush_all
Delayed::Worker.delay_jobs = false
@post = FactoryGirl.create(:post, :tag_string => "aaa")
@tag_alias = FactoryGirl.create(:tag_alias, :antecedent_name => "aaa", :consequent_name => "bbb")
end
teardown do
CurrentUser.user = nil
CurrentUser.ip_addr = nil
end
context "with a bad cache and post counts" do
setup do
Cache.put("ta:aaa", "zzz")
Tag.update_all("post_count = -3", "name = 'aaa'")
@correction = TagAliasCorrection.new(@tag_alias.id)
end
should "have the correct statistics hash" do
assert_equal("zzz", @correction.statistics_hash["antecedent_cache"])
assert_nil(@correction.statistics_hash["consequent_cache"])
assert_equal(-3, @correction.statistics_hash["antecedent_count"])
assert_nil(@correction.statistics_hash["consequent_count"])
end
should "render to json" do
assert_nothing_raised do
@correction.to_json
end
assert_nothing_raised do
JSON.parse(@correction.to_json)
end
end
context "that is fixed" do
setup do
@correction.fix!
end
should "now have the correct cache" do
assert_equal("bbb", Cache.get("ta:aaa"))
end
should "now have the correct count" do
assert_equal(0, Tag.find_by_name("aaa").post_count)
end
end
end
end
end