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
You can’t perform that action at this time.