From 14ea16df624cfbb4a1f536c99236b3d72f25ece6 Mon Sep 17 00:00:00 2001 From: Gabina Luz Bianchi Date: Thu, 16 Jan 2025 22:58:38 -0300 Subject: [PATCH] [Data rearchitecture] Implement ContinuedCourseActivityAlert without revisions (#6132) * Reimplement criteria for ContinuedCourseActivityAlert. Instead of using raw revisions from data table, now we hit the API to get recent revisions. --- ...continued_course_activity_alert_manager.rb | 34 ++++++++++++++----- ...nued_course_activity_alert_manager_spec.rb | 32 ++++++++--------- 2 files changed, 40 insertions(+), 26 deletions(-) diff --git a/lib/alerts/continued_course_activity_alert_manager.rb b/lib/alerts/continued_course_activity_alert_manager.rb index df868b4480..6a159727ac 100644 --- a/lib/alerts/continued_course_activity_alert_manager.rb +++ b/lib/alerts/continued_course_activity_alert_manager.rb @@ -22,15 +22,31 @@ def create_alerts private - MINIMUM_CHARACTERS_ADDED_AFTER_COURSE_END = 200 + MINIMUM_REVISIONS_AFTER_COURSE_END = 20 def significant_activity_after_course_end?(course) - user_ids = course.students.pluck(:id) - post_course_characters = Revision - .where(user_id: user_ids) - .where('date > ?', course.end.end_of_day) - .joins(:article) - .where(articles: { namespace: Article::Namespaces::MAINSPACE }) - .sum(:characters) - post_course_characters > MINIMUM_CHARACTERS_ADDED_AFTER_COURSE_END + total_revisions = course.wikis.sum do |wiki| + puts wiki.id + count_revisions_for_wiki(course, wiki) + end + total_revisions > MINIMUM_REVISIONS_AFTER_COURSE_END + end + + def count_revisions_for_wiki(course, wiki) + # 50 is the max users for query + course.students.pluck(:username).in_groups_of(40, false).sum do |usernames| + response = WikiApi.new(wiki).query(query(course, usernames)) + puts response.data['usercontribs'].count + response.data['usercontribs'].count + end + end + + def query(course, users) + { + list: 'usercontribs', + ucuser: users, + ucnamespace: Article::Namespaces::MAINSPACE, + ucend: course.end.end_of_day.strftime('%Y%m%d%H%M%S'), + uclimit: MINIMUM_REVISIONS_AFTER_COURSE_END + 1 + } end end diff --git a/spec/lib/alerts/continued_course_activity_alert_manager_spec.rb b/spec/lib/alerts/continued_course_activity_alert_manager_spec.rb index 9f8a073a75..06bd5531d5 100644 --- a/spec/lib/alerts/continued_course_activity_alert_manager_spec.rb +++ b/spec/lib/alerts/continued_course_activity_alert_manager_spec.rb @@ -8,16 +8,17 @@ def mock_mailer end describe ContinuedCourseActivityAlertManager do - let(:course) { create(:course, start: 1.month.ago, end: 5.days.ago) } + let(:course) { create(:course) } let(:user) { create(:user) } - let(:article) { create(:article, namespace: Article::Namespaces::MAINSPACE) } - let(:revision) do - create(:revision, characters: character_count, date: revision_date, - article_id: article.id, user_id: user.id) - end let(:subject) { described_class.new([course]) } # Only Wikipedia Expert, indicated by greeter: true, should get emails. let(:admin) { create(:admin, email: 'staff@wikiedu.org', greeter: true) } + let(:contribution) do + { 'userid' => 4543197, 'user' => 'Ragesock', 'pageid' => 38467785, 'revid' => 882417897, + 'parentid' => 866599474, 'ns' => 0, 'title' => 'Jazz Workshop', + 'timestamp' => '2019-02-08T22:58:37Z', 'comment' => 'Fixed grammar', 'size' => 1920 } + end + let(:response) { instance_double(MediawikiApi::Response, data: content) } before do create(:courses_user, user_id: user.id, course_id: course.id, @@ -26,44 +27,42 @@ def mock_mailer course_id: course.id, user_id: admin.id, role: CoursesUsers::Roles::WIKI_ED_STAFF_ROLE) + allow_any_instance_of(WikiApi).to receive(:query).and_return response end context 'when there are no revisions after the course ends' do - let(:character_count) { 5000 } - let(:revision_date) { course.end - 2.days } + let(:content) { { 'usercontribs' => [] } } it 'does not create an alert' do - revision subject.create_alerts expect(Alert.count).to eq(0) end end context 'when there is only a small contribution after the course ends' do - let(:character_count) { 5 } - let(:revision_date) { course.end + 2.days } + let(:content) do + { 'usercontribs' => [contribution] } + end it 'does not create an alert' do - revision subject.create_alerts expect(Alert.count).to eq(0) end end context 'when there is significant after the course ends' do - let(:character_count) { 5000 } - let(:revision_date) { course.end + 2.days } + let(:content) do + { 'usercontribs' => Array.new(21) { |_| contribution } } + end it 'creates an alert' do expect_any_instance_of(AlertMailer).to receive(:alert).and_return(mock_mailer) - revision subject.create_alerts expect(Alert.count).to eq(1) end it 'does not create alert for the second time' do expect_any_instance_of(AlertMailer).to receive(:alert).and_return(mock_mailer) - revision subject.create_alerts # Attempt to create for the second time @@ -73,7 +72,6 @@ def mock_mailer end it 'creates another alert if the first alert is resolved' do - revision subject.create_alerts Alert.first.update(resolved: true)