Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Batch Aggregation mailer #4352

Merged
merged 6 commits into from
Jul 1, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions app/controllers/api/v1/aggregations_controller.rb
Original file line number Diff line number Diff line change
Expand Up @@ -22,4 +22,10 @@ def create
rescue AggregationClient::ConnectionError
json_api_render(:service_unavailable, 'The aggregation service is unavailable or not responding')
end

def update
super do |agg|
AggregationCompletedMailerWorker.perform_async(agg.id) if update_params[:status]
end
end
end
19 changes: 19 additions & 0 deletions app/mailers/aggregation_completed_mailer.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
# frozen_string_literal: true

class AggregationCompletedMailer < ApplicationMailer
layout false

def aggregation_complete(agg)
@user = User.find(agg.user_id)
@email_to = @user.email
base_url = ENV.fetch('AGGREGATION_STORAGE_BASE_URL', '')
@zip_url = "#{base_url}/#{agg.uuid}/#{agg.uuid}.zip"
@reductions_url = "#{base_url}/#{agg.uuid}/reductions.csv"

@success = agg.completed?
agg_status = @success ? 'was successful!' : 'failed'
subject = "Your workflow aggregation #{agg_status}"

mail(to: @email_to, subject: subject)
end
end
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
Hello,

Your workflow aggregation has finished processing.

<% if @success %>
The workflow was aggregated successfully.

Click here to download a zip file containing the following:
* Workflow classifications export
* Workflow export
* Extracts (one file per task)
* Reductions

<%= @zip_url %>

Click here to download the reductions file by itself:

<%= @reductions_url %>

<% else %>
The workflow failed to aggregate. Please contact us or try again.
<% end %>

If you have questions or if there were any issues with your aggregation, please email [email protected].

Cheers,
The Zooniverse Team

This is an automated email, please do not respond.

To manage your Zooniverse email subscription preferences visit https://zooniverse.org/settings

To unsubscribe to all Zooniverse messages please visit https://zooniverse.org/unsubscribe
Please be aware that the above link will unsubscribe you from ALL Zooniverse emails.
12 changes: 12 additions & 0 deletions app/workers/aggregation_completed_mailer_worker.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
# frozen_string_literal: true

class AggregationCompletedMailerWorker
include Sidekiq::Worker

sidekiq_options queue: :data_high

def perform(agg_id)
aggregation = Aggregation.find(agg_id)
AggregationCompletedMailer.aggregation_complete(aggregation).deliver_now
end
end
1 change: 1 addition & 0 deletions kubernetes/deployment-production.tmpl
Original file line number Diff line number Diff line change
Expand Up @@ -121,6 +121,7 @@ data:
TALK_API_APPLICATION: '1'
USER_SUBJECT_LIMIT: '10000'
AGGREGATION_HOST: http://aggregation-caesar/
AGGREGATION_STORAGE_BASE_URL: https://aggregationdata.blob.core.windows.net
---
apiVersion: apps/v1
kind: Deployment
Expand Down
1 change: 1 addition & 0 deletions kubernetes/deployment-staging.tmpl
Original file line number Diff line number Diff line change
Expand Up @@ -110,6 +110,7 @@ data:
TALK_API_APPLICATION: '1'
USER_SUBJECT_LIMIT: '100'
AGGREGATION_HOST: http://aggregation-staging-app/
AGGREGATION_STORAGE_BASE_URL: https://aggregationdata.blob.core.windows.net
---
apiVersion: apps/v1
kind: Deployment
Expand Down
20 changes: 20 additions & 0 deletions spec/controllers/api/v1/aggregations_controller_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -107,6 +107,26 @@
end

it_behaves_like 'is updatable'

context 'with the mailer worker' do
before do
default_request scopes: scopes, user_id: authorized_user.id
allow(AggregationCompletedMailerWorker).to receive(:perform_async).with(resource.id)
end

let(:params) { update_params.merge(id: resource.id) }

it 'calls the mailer worker' do
put :update, params: params
expect(AggregationCompletedMailerWorker).to have_received(:perform_async).with(resource.id)
end

it 'does not call the mailer if status is not an updated param' do
params[:aggregations].delete(:status)
put :update, params: params
expect(AggregationCompletedMailerWorker).not_to have_received(:perform_async)
end
end
end

describe '#destroy' do
Expand Down
52 changes: 52 additions & 0 deletions spec/mailers/aggregation_completed_mailer_spec.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
# frozen_string_literal: true

require 'spec_helper'

RSpec.describe AggregationCompletedMailer, type: :mailer do
let(:base_url) { 'https://example.com' }

before do
allow(ENV).to receive(:fetch).with('AGGREGATION_STORAGE_BASE_URL', '').and_return(base_url)
end

describe '#aggregation_complete' do
let(:mail) { described_class.aggregation_complete(aggregation) }

context 'with a successful aggregation' do
let(:aggregation) { create(:aggregation, status: 'completed', uuid: 'asdf123asdf') }
let(:uuid) { aggregation.uuid }

it 'mails the user' do
expect(mail.to).to match_array([aggregation.user.email])
end

it 'includes the subject' do
expect(mail.subject).to include('Your workflow aggregation was successful!')
end

it 'includes the zip file link' do
expect(mail.body.encoded).to include("#{base_url}/#{uuid}/#{uuid}.zip")
end

it 'includes the reductions file link' do
expect(mail.body.encoded).to include("#{base_url}/#{uuid}/reductions.csv")
end

it 'comes from [email protected]' do
expect(mail.from).to include('[email protected]')
end

it 'has the success statement' do
expect(mail.body.encoded).to include('The workflow was aggregated successfully.')
end
end

context 'with a failed aggregation' do
let(:aggregation) { create(:aggregation, status: 'failed') }

it 'reports the failures statement' do
expect(mail.body.encoded).to include('The workflow failed to aggregate.')
end
end
end
end
18 changes: 18 additions & 0 deletions spec/workers/aggregation_completed_mailer_worker_spec.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
# frozen_string_literal: true

require 'spec_helper'

RSpec.describe AggregationCompletedMailerWorker do
let(:aggregation) { create(:aggregation) }

it 'delivers the mail' do
expect { described_class.new.perform(aggregation.id) }.to change { ActionMailer::Base.deliveries.count }.by(1)
end

context 'with missing attributes' do
it 'is missing an aggregation and does not send' do
expect { described_class.new.perform(nil) }.to not_change { ActionMailer::Base.deliveries.count }
.and raise_error(ActiveRecord::RecordNotFound)
end
end
end
Loading