Skip to content

Instantly share code, notes, and snippets.



Created Jun 7, 2018
What would you like to do?
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]

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

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

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