Created
February 4, 2019 21:09
-
-
Save benjaminkreen/3467b5061054394d13dc7d9eb77579ad to your computer and use it in GitHub Desktop.
rails implementation transactional emailing with queueing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# app/controllers/events_controller.rb | |
class EventsController < ApplicationController | |
def create | |
Event.create(params.permit(:event_type, :doi, :event_data)) | |
render json: {}, status: :ok | |
end | |
end | |
# app/models/event.rb | |
class Event < ActiveRecord | |
# not sure if this is the best place for this mapping | |
# could beling in DB | |
EVENT_QUEUE_TIME_MAP = { | |
'event_1' => 0, | |
'event_2' => 24 | |
} | |
after_create :perform_email_job, if: :enqueue_job? | |
def perform_email_job | |
EmailEventJob.set(wait: queue_time.hours).perform_later(id, doi, event_type, queue_time.zero?) | |
# do we care to handle unlisted events? | |
end | |
def queue_time | |
EVENT_QUEUE_TIME_MAP[event_type] | |
end | |
def enqueue_job? | |
# there might be some sort of db locking we'd need to implement | |
# to prevent some sort of race condition? | |
queue_time.zero? || Event.where(doi: doi, event_type: event_type).count == 1 | |
end | |
end | |
# app/jobs/email_event_job.rb | |
class EmailEventJob < ActiveJob | |
def perform(event_id, doi, event_type, use_id) | |
where_args = use_id ? { id: event_id } : { doi: doi, event_type: event_type } | |
events = Event.where(where_args) # maybe add some sort of DB lock | |
return if events.empty? # this might happen? Ideally not. | |
recepients = get_author_emails(doi) | |
# only email client specific api call, can be swapped out | |
SendgridClient.send_email(event_type, recepients, events.pluck(:event_data)) # should raise error if fails | |
events.destroy_all # we can soft delete if we want to keep a record | |
end | |
def get_author_emails(doi) | |
# TODO: this needs to get figured out and probably cached | |
end | |
end | |
# lib/sendgrid_client.rb | |
require 'sendgrid-ruby' | |
require 'json' | |
include SendGrid | |
class SendgridClient | |
EVENT_TEMPLATE_MAP = { | |
'event_1' => 'abc123', | |
'event_2' => 'def456' | |
} | |
class << self | |
def send_email(event_type, recepients, event_data) | |
mail = Mail.new | |
mail.template_id = EVENT_TEMPLATE_MAP[event_type] | |
mail.from = Email.new(email: '[email protected]') | |
personalization = Personalization.new | |
recepients.each do |recepient| | |
personalization.add_to(Email.new(email: recepient)) | |
end | |
# we kinda assume the first set of data coming in is pretty much | |
# tailored for emailing, but we could also massage it here too. | |
personalization.add_dynamic_template_data(events: event_data) | |
mail.add_personalization(personalization) | |
sg = SendGrid::API.new(api_key: ENV['SENDGRID_API_KEY'], host: 'https://api.sendgrid.com') | |
sg.client.mail._('send').post(request_body: mail.to_json) | |
end | |
end | |
end |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment