Add priority queue to notifications

Significant delays are happening in high priority messages being
delivered to clients due to lack of delivery prioritization. Implement
simple delivery prioritization with "high priority" queue to prevent
password resets and other high priority messages from being delayed.

Test plan:
* Deploy to canary or beta environment
* Create user with @instructure.com email address
* Take user through password reset process and confirm that email is
  received

refs SAS-1442

Change-Id: I0b4f98ac03c5a5ee24e903a913614c005a12ead8
Reviewed-on: https://gerrit.instructure.com/c/canvas-lms/+/231036
Tested-by: Service Cloud Jenkins <svc.cloudjenkins@instructure.com>
Reviewed-by: Rob Orton <rob@instructure.com>
Reviewed-by: Cody Cutrer <cody@instructure.com>
Product-Review: Cody Cutrer <cody@instructure.com>
QA-Review: Jonathan Featherstone <jfeatherstone@instructure.com>
This commit is contained in:
Jonathan Featherstone 2020-03-23 12:11:51 -06:00
parent e7492e33fe
commit 8be6311db0
3 changed files with 31 additions and 13 deletions

View File

@ -640,7 +640,8 @@ class Message < ActiveRecord::Base
notification_service_id,
notification_message,
path_type,
target
target,
self.notification.priority?
)
end
complete_dispatch

View File

@ -1,5 +1,5 @@
#
# Copyright (C) 2016 - present Instructure, Inc.
# Copyright (C) 2020 - present Instructure, Inc.
#
# This file is part of Canvas.
#
@ -20,34 +20,50 @@ require 'aws-sdk-sqs'
module Services
class NotificationService
def self.process(global_id, body, type, to)
return unless notification_queue.present?
def self.process(global_id, body, type, to, priority=false)
queue_url = choose_queue_url(priority)
return unless queue_url.present?
notification_queue.send_message(message_body: {
notification_sqs.send_message(message_body: {
global_id: global_id,
type: type,
message: body,
target: to,
request_id: RequestContextGenerator.request_id
}.to_json,
queue_url: @queue_url)
queue_url: queue_url)
end
class << self
private
def notification_queue
QUEUE_NAME_KEYS = {
priority: 'notification_service_priority_queue_name',
default: 'notification_service_queue_name'
}.freeze
def notification_sqs
return nil if config.blank?
@notification_queue ||= begin
@notification_sqs ||= begin
conf = Canvas::AWS.validate_v2_config(config, 'notification_service.yml')
queue_name = conf['notification_service_queue_name']
sqs = Aws::SQS::Client.new(conf.except('notification_service_queue_name'))
@queue_url = sqs.get_queue_url(queue_name: queue_name).queue_url
sqs = Aws::SQS::Client.new(conf.except(*QUEUE_NAME_KEYS.values))
@queue_urls = {}
QUEUE_NAME_KEYS.each do |key, queue_name_key|
queue_name = conf[queue_name_key]
next unless queue_name.present?
@queue_urls[key] = sqs.get_queue_url(queue_name: queue_name).queue_url
end
sqs
end
end
def choose_queue_url(priority)
return nil unless notification_sqs.present?
url = @queue_urls[:priority] if priority
url || @queue_urls[:default]
end
def config
ConfigFile.load('notification_service') || {}
end

View File

@ -36,7 +36,8 @@ module Services
before(:each) do
@queue = double('notification queue')
allow(NotificationService).to receive(:notification_queue).and_return(@queue)
allow(NotificationService).to receive(:notification_sqs).and_return(@queue)
allow(NotificationService).to receive(:choose_queue_url).and_return('default')
end
it "processes email message type" do
@ -150,7 +151,7 @@ module Services
}.with_indifferent_access
spy = SendMessageSpy.new
allow(NotificationService).to receive(:notification_queue).and_return(spy)
allow(NotificationService).to receive(:notification_sqs).and_return(spy)
NotificationService.process(1, 'hello', 'email', 'alice@example.com')
expect(expected).to eq spy.sent_hash