Skip to content

Instantly share code, notes, and snippets.

@mmmries
Created June 7, 2018 12:36
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save mmmries/424afa5b73ef597d56037b5b2591561e to your computer and use it in GitHub Desktop.
Save mmmries/424afa5b73ef597d56037b5b2591561e to your computer and use it in GitHub Desktop.
A "Plug-ish" approach to flexible shared behavior

The main idea here is compose shared functionality into a pipeline of functions that all implement some shared behaviour.

defmodule Notification.Event do
  # The event (probably a bad name) is where you would put the structified JSON event you got from RabbitMQ
  defstruct [:sent_at, :user, :event]
end

defmodule Notification.Plug do
  @callback init(opts) :: opts
  @callback call(Notification.Event.t) ::
    :skip # halts processing early if we should not send anything
    | Notification.Event.t # continue processing with an updated Notification.Event.t
    | {:send_email, Notifications.Email.t, Notification.Event.t} # deliver an email to the user and continue processing with the new Notifiction.Event.t
    | {:send_sms, Notifications.SMS.t, Notification.Event.t} # deliver an sms to the user and continue processing with the new Notifiction.Event.t
end

defmodule Notifications.MattressShipped do
  plug CheckIfUserUnsubscribed
  plug CheckIfUserOptedIn, default: true
  plug SendMattressShippedEmail
  plug SendMattressShippedSMS
end

This lets us compose a different set of functionality for each type of event and it makes it easy for the team supporting this code to answer questions like, "is this notification opt-in or opt-out? Does it check for unsubscribed users?".

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment