diff --git a/.circleci/config.yml b/.circleci/config.yml index f6963bf8c..ea4f9427a 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -44,7 +44,6 @@ jobs: docker-compose -f config/docker/compose.yml exec archives dockerize -wait tcp://$PGHOST:$PGPORT bash -l -c 'cd /app ; bundle exec rake db:create ; bundle exec rake db:migrate' docker-compose -f config/docker/compose.yml exec web dockerize -wait tcp://$PGHOST:$PGPORT bash -l -c 'cd /app ; bin/rake db:create ; bin/rake db:migrate' - run: - name: Run tests command: | circleci tests glob test/**/*_test.rb | circleci tests split --split-by=timings | xargs -I{} docker-compose -f config/docker/compose.yml exec -T web bash -l -c 'cd /app ; bin/rails test --no-ci-clean {}' diff --git a/app/helpers/posts_helper.rb b/app/helpers/posts_helper.rb index 681c466ce..ac21b899e 100644 --- a/app/helpers/posts_helper.rb +++ b/app/helpers/posts_helper.rb @@ -147,6 +147,10 @@ module PostsHelper return params[:pool_id].to_i == pool.id end + def show_tag_change_notice? + Tag.scan_query(params[:tags]).size == 1 && TagChangeNoticeService.get_forum_topic_id(params[:tags]) + end + private def nav_params_for(page) diff --git a/app/logical/alias_and_implication_importer.rb b/app/logical/alias_and_implication_importer.rb index 7fe6e5382..3ccb0f3b0 100644 --- a/app/logical/alias_and_implication_importer.rb +++ b/app/logical/alias_and_implication_importer.rb @@ -100,6 +100,30 @@ class AliasAndImplicationImporter end end + def affected_tags + tokens = self.class.tokenize(text) + tokens.inject([]) do |all, token| + case token[0] + when :create_alias, :remove_alias, :create_implication, :remove_implication + all << token[1] + all << token[2] + all + + when :mass_update + all += Tag.scan_tags(token[1]) + all += Tag.scan_tags(token[2]) + all + + when :change_category + all << token[1] + all + + else + all + end + end + end + private def parse(tokens, approver) diff --git a/app/logical/tag_change_notice_service.rb b/app/logical/tag_change_notice_service.rb new file mode 100644 index 000000000..cb43b59ee --- /dev/null +++ b/app/logical/tag_change_notice_service.rb @@ -0,0 +1,18 @@ +module TagChangeNoticeService + extend self + + def redis_client + ::Redis.new(url: Danbooru.config.redis_url) + end + + def get_forum_topic_id(tag) + redis_client.get("tcn:#{tag}") + end + + def update_cache(affected_tags, forum_topic_id) + rc = redis_client + affected_tags.each do |tag| + rc.setex("tcn:#{tag}", 1.week, forum_topic_id) + end + end +end diff --git a/app/models/bulk_update_request.rb b/app/models/bulk_update_request.rb index e0c73dc17..fd6abda69 100644 --- a/app/models/bulk_update_request.rb +++ b/app/models/bulk_update_request.rb @@ -16,6 +16,7 @@ class BulkUpdateRequest < ApplicationRecord before_validation :initialize_attributes, :on => :create before_validation :normalize_text after_create :create_forum_topic + after_save :update_notice scope :pending_first, -> { order(Arel.sql("(case status when 'pending' then 0 when 'approved' then 1 else 2 end)")) } scope :pending, -> {where(status: "pending")} @@ -241,4 +242,11 @@ class BulkUpdateRequest < ApplicationRecord def estimate_update_count AliasAndImplicationImporter.new(script, nil).estimate_update_count end + + def update_notice + TagChangeNoticeService.update_cache( + AliasAndImplicationImporter.new(script, nil).affected_tags, + forum_topic_id + ) + end end diff --git a/app/models/tag_relationship.rb b/app/models/tag_relationship.rb index 0a0d1dcb5..537df4504 100644 --- a/app/models/tag_relationship.rb +++ b/app/models/tag_relationship.rb @@ -32,6 +32,7 @@ class TagRelationship < ApplicationRecord validates :approver, presence: { message: "must exist" }, if: -> { approver_id.present? } validates :forum_topic, presence: { message: "must exist" }, if: -> { forum_topic_id.present? } validate :antecedent_and_consequent_are_different + after_save :update_notice def initialize_creator self.creator_id = CurrentUser.user.id @@ -204,6 +205,13 @@ class TagRelationship < ApplicationRecord Post.fast_count(antecedent_name, skip_cache: true) end + def update_notice + TagChangeNoticeService.update_cache( + [antecedent_name, consequent_name], + forum_topic_id + ) + end + extend SearchMethods include MessageMethods end diff --git a/app/views/posts/partials/index/_posts.html.erb b/app/views/posts/partials/index/_posts.html.erb index 53a33e3f9..f45c00a25 100644 --- a/app/views/posts/partials/index/_posts.html.erb +++ b/app/views/posts/partials/index/_posts.html.erb @@ -19,6 +19,12 @@ <% end %> + <% if show_tag_change_notice? %> +
+

This tag is the subject of an ongoing discussion. If you have any relevant information, please join the <%= link_to "discussion", forum_topic_path(TagChangeNoticeService.get_forum_topic_id(params[:tags]) || 1) %>.

+
+ <% end %> + <% unless post_set.is_random? %> <%= numbered_paginator(post_set.posts) %> <% end %> diff --git a/config/docker/compose.yml b/config/docker/compose.yml index 1ca8228fa..7c9a36414 100644 --- a/config/docker/compose.yml +++ b/config/docker/compose.yml @@ -6,6 +6,10 @@ services: - "5432:5432" environment: - POSTGRES_PASSWORD + redis: + image: redis:latest + ports: + - "6379:6379" memcached: image: memcached:alpine ports: @@ -63,3 +67,4 @@ services: - db - memcached - archives + - redis \ No newline at end of file diff --git a/test/unit/alias_and_implication_importer_test.rb b/test/unit/alias_and_implication_importer_test.rb index 5690e11db..326b580f5 100644 --- a/test/unit/alias_and_implication_importer_test.rb +++ b/test/unit/alias_and_implication_importer_test.rb @@ -26,6 +26,28 @@ class AliasAndImplicationImporterTest < ActiveSupport::TestCase end end + context "#affected_tags" do + setup do + FactoryBot.create(:post, tag_string: "aaa") + FactoryBot.create(:post, tag_string: "bbb") + FactoryBot.create(:post, tag_string: "ccc") + FactoryBot.create(:post, tag_string: "ddd") + FactoryBot.create(:post, tag_string: "eee") + + @script = "create alias aaa -> 000\n" + + "create implication bbb -> 111\n" + + "remove alias ccc -> 222\n" + + "remove implication ddd -> 333\n" + + "mass update eee -> 444\n" + end + + subject { AliasAndImplicationImporter.new(@script, nil) } + + should "return the correct tags" do + assert_equal(%w(aaa 000 bbb 111 ccc 222 ddd 333 eee 444), subject.affected_tags) + end + end + context "#estimate_update_count" do setup do FactoryBot.create(:post, tag_string: "aaa") diff --git a/test/unit/bulk_update_request_test.rb b/test/unit/bulk_update_request_test.rb index 83c226465..aff2ca660 100644 --- a/test/unit/bulk_update_request_test.rb +++ b/test/unit/bulk_update_request_test.rb @@ -35,6 +35,33 @@ class BulkUpdateRequestTest < ActiveSupport::TestCase end end + context "#update_notice" do + setup do + @mock_redis = MockRedis.new + @forum_topic = FactoryBot.create(:forum_topic) + TagChangeNoticeService.stubs(:redis_client).returns(@mock_redis) + end + + should "update redis" do + @script = "create alias aaa -> 000\n" + + "create implication bbb -> 111\n" + + "remove alias ccc -> 222\n" + + "remove implication ddd -> 333\n" + + "mass update eee -> 444\n" + FactoryBot.create(:bulk_update_request, script: @script, forum_topic: @forum_topic) + assert_equal(@forum_topic.id.to_s, @mock_redis.get("tcn:aaa")) + assert_equal(@forum_topic.id.to_s, @mock_redis.get("tcn:000")) + assert_equal(@forum_topic.id.to_s, @mock_redis.get("tcn:bbb")) + assert_equal(@forum_topic.id.to_s, @mock_redis.get("tcn:111")) + assert_equal(@forum_topic.id.to_s, @mock_redis.get("tcn:ccc")) + assert_equal(@forum_topic.id.to_s, @mock_redis.get("tcn:222")) + assert_equal(@forum_topic.id.to_s, @mock_redis.get("tcn:ddd")) + assert_equal(@forum_topic.id.to_s, @mock_redis.get("tcn:333")) + assert_equal(@forum_topic.id.to_s, @mock_redis.get("tcn:eee")) + assert_equal(@forum_topic.id.to_s, @mock_redis.get("tcn:444")) + end + end + context "on approval" do setup do @script = %q( diff --git a/test/unit/tag_alias_test.rb b/test/unit/tag_alias_test.rb index 2df827697..97046dc77 100644 --- a/test/unit/tag_alias_test.rb +++ b/test/unit/tag_alias_test.rb @@ -69,6 +69,19 @@ class TagAliasTest < ActiveSupport::TestCase end end + context "#update_notice" do + setup do + @mock_redis = MockRedis.new + @forum_topic = FactoryBot.create(:forum_topic) + TagChangeNoticeService.stubs(:redis_client).returns(@mock_redis) + end + + should "update redis" do + FactoryBot.create(:tag_alias, antecedent_name: "aaa", consequent_name: "bbb", skip_secondary_validations: true, forum_topic: @forum_topic) + assert_equal(@forum_topic.id.to_s, @mock_redis.get("tcn:aaa")) + end + end + context "on secondary validation" do should "warn about missing wiki pages" do ti = FactoryBot.build(:tag_alias, antecedent_name: "aaa", consequent_name: "bbb", skip_secondary_validations: false) diff --git a/test/unit/tag_implication_test.rb b/test/unit/tag_implication_test.rb index 76e474852..261abc0e3 100644 --- a/test/unit/tag_implication_test.rb +++ b/test/unit/tag_implication_test.rb @@ -65,6 +65,19 @@ class TagImplicationTest < ActiveSupport::TestCase end end + context "#update_notice" do + setup do + @mock_redis = MockRedis.new + @forum_topic = FactoryBot.create(:forum_topic) + TagChangeNoticeService.stubs(:redis_client).returns(@mock_redis) + end + + should "update redis" do + FactoryBot.create(:tag_implication, antecedent_name: "aaa", consequent_name: "bbb", skip_secondary_validations: true, forum_topic: @forum_topic) + assert_equal(@forum_topic.id.to_s, @mock_redis.get("tcn:aaa")) + end + end + context "on secondary validation" do should "warn if either tag is missing a wiki" do ti = FactoryBot.build(:tag_implication, antecedent_name: "aaa", consequent_name: "bbb", skip_secondary_validations: false)