Skip to content

Commit

Permalink
[Data rearchitecture] Implement ContinuedCourseActivityAlert without …
Browse files Browse the repository at this point in the history
…revisions (#6132)

* Reimplement criteria for ContinuedCourseActivityAlert. Instead of using raw revisions from data table, now we hit the API to get recent revisions.
gabina authored Jan 17, 2025
1 parent a519cbe commit 14ea16d
Showing 2 changed files with 40 additions and 26 deletions.
34 changes: 25 additions & 9 deletions lib/alerts/continued_course_activity_alert_manager.rb
Original file line number Diff line number Diff line change
@@ -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
32 changes: 15 additions & 17 deletions spec/lib/alerts/continued_course_activity_alert_manager_spec.rb
Original file line number Diff line number Diff line change
@@ -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: '[email protected]', 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)

0 comments on commit 14ea16d

Please sign in to comment.