FEATURE: Add new EnsureConsistency scheduled job

FEATURE: Add new EnsureConsistency scheduled job

Add a new job that is scheduled twice daily to ensure the consistency of the calendar topic.

In some rare cases, like when a post is moved, the calendar is not properly updated.

Since reacting to a post being moved is hard (we don’t have the information of the previous topics), this job will ensure that the events of each posts in the calendar topic are up to date.

diff --git a/jobs/scheduled/ensure_consistency.rb b/jobs/scheduled/ensure_consistency.rb
new file mode 100644
index 0000000..0d5d684
--- /dev/null
+++ b/jobs/scheduled/ensure_consistency.rb
@@ -0,0 +1,26 @@
+# frozen_string_literal: true
+
+module Jobs
+  class ::DiscourseCalendar::EnsureConsistency < Jobs::Scheduled
+    every 12.hours
+
+    PLUGIN_NAME ||= "calendar"
+
+    def execute(args)
+      return unless SiteSetting.calendar_enabled
+      return unless topic_id = SiteSetting.holiday_calendar_topic_id
+      return unless op = Post.find_by(topic_id: topic_id, post_number: 1)
+      return unless op.calendar_details.present?
+
+      posts = Post
+        .where(topic_id: topic_id, post_number: op.calendar_details.keys)
+        .where("raw NOT LIKE '%[date%'")
+
+      posts.find_each do |post|
+        DistributedMutex.synchronize("#{PLUGIN_NAME}-#{post.id}") do
+          DiscourseCalendar::EventUpdater.update(post)
+        end
+      end
+    end
+  end
+end
diff --git a/plugin.rb b/plugin.rb
index 7782002..f163991 100644
--- a/plugin.rb
+++ b/plugin.rb
@@ -13,8 +13,8 @@ enabled_site_setting :calendar_enabled
 register_asset "stylesheets/vendor/fullcalendar.min.css"
 register_asset "stylesheets/common/discourse-calendar.scss"
 
-PLUGIN_NAME ||= "calendar".freeze
-DATA_PREFIX ||= "data-calendar-".freeze
+PLUGIN_NAME ||= "calendar"
+DATA_PREFIX ||= "data-calendar-"
 
 REGION_TO_EMOJI_FLAG ||= {
   "ar" => "argentina",
@@ -63,6 +63,7 @@ after_initialize do
     "../jobs/scheduled/ensure_expired_event_destruction.rb",
     "../jobs/scheduled/update_holiday_usernames.rb",
     "../jobs/scheduled/check_next_regional_holidays.rb",
+    "../jobs/scheduled/ensure_consistency.rb",
   ].each { |path| load File.expand_path(path, __FILE__) }
 
   register_post_custom_field_type(DiscourseCalendar::CALENDAR_DETAILS_CUSTOM_FIELD, :json)
diff --git a/spec/jobs/ensure_consistency_spec.rb b/spec/jobs/ensure_consistency_spec.rb
new file mode 100644
index 0000000..2112165
--- /dev/null
+++ b/spec/jobs/ensure_consistency_spec.rb
@@ -0,0 +1,33 @@
+# frozen_string_literal: true
+
+require "rails_helper"
+
+describe DiscourseCalendar::EnsureConsistency do
+  before { SiteSetting.calendar_enabled = true }
+
+  it "works" do
+    op = create_post(raw: "[calendar]\n[/calendar]")
+
+    SiteSetting.holiday_calendar_topic_id = op.topic_id
+
+    post = create_post(raw: "Some Event [date=2019-09-10]", topic: op.topic)
+    CookedPostProcessor.new(post).post_process
+
+    op.reload
+    expect(op.calendar_details[post.post_number.to_s]).to be_present
+
+    DiscourseCalendar::EnsureConsistency.new.execute(nil)
+
+    op.reload
+    expect(op.calendar_details[post.post_number.to_s]).to be_present
+
+    PostMover
+      .new(op.topic, Discourse.system_user, [post.id])
+      .to_new_topic("A topic with some dates in it")
+
+    DiscourseCalendar::EnsureConsistency.new.execute(nil)
+
+    op.reload
+    expect(op.calendar_details).to eq({})
+  end
+end
diff --git a/spec/lib/event_updater_spec.rb b/spec/lib/event_updater_spec.rb
index b867faa..c2eee14 100644
--- a/spec/lib/event_updater_spec.rb
+++ b/spec/lib/event_updater_spec.rb
@@ -3,9 +3,7 @@
 require 'rails_helper'
 
 describe DiscourseCalendar::EventUpdater do
-  before do
-    SiteSetting.calendar_enabled = true
-  end
+  before { SiteSetting.calendar_enabled = true }
 
   it "will correctly update the associated first post calendar details" do
     op = create_post(raw: "[calendar]\n[/calendar]")

GitHub sha: d6fd8f03