Richard Nixon & RFC 768

Musings On Matters Elixir, OTP, BEAM, and Phoenix that I couldn't think of a name for that doesn't involve a disgraced president or UDP. Explanation coming soon.

Hi, I'm Bobby

@yburyug

What This Talk Is

 

- Designing a large Elixir/Phoenix application

- Deploying it

- The business case for Elixir

- The developer case for Elixir

- A look at when its the best tool

What This Talk Is Not

- Extremely technical at an OTP/micro level

- A complete solution to all your woes

- A beckoning for us all to use these new tools with no real reason

A Project Proposal

Exploring Options

Veridian Dynamics 

Veridian Dynamics has a problem. They are paying far too much to grab customer data for quoting insurance policies in their new property & casualty division through an API. They have reached an agreement with a data provider to get all the raw data they want, but they need to be able to query it via an API.

The Pieces

  • Grab all the data from a server the provider puts it on
  • Normalize + Preprocess it all in an ETL pipeline
  • Back up all the data given from provider
  • Keep data updated with new files
  • Put everything in a database
  • Expose it via an API

The Gotchas and Whathaveyou's

  • These files are far from an RFC compliant CSV, a custom set of rules must be built up
  • They range in size from a few megabytes to hundreds of gigabytes
  • Update times are random
  • Somehow there is no way other than FTP to get this stuff

Potential Options

Rails! The Good

  • Team has background in it!
  • Lots of best practices for deploying large apps
  • Easy to find more team members
  • Server costs will be expensive with how much data + throughput we will have
  • Complicated builds for workers and processing
  • Monolithic

Rails! The Bad

Go?

 

  • Service oriented, simple small components
  • Much faster
  • No one on the team knows it :(
  • Heavy turn from typical interpreted languages

Elixir, Phoenix, BEAM, and OTP

OTP & BEAM

  • Battle tested for decades
  • Amazing support for concurrency
  • Wtf I get a free super fast distributed database built in? Raunch
  •  Static analysis is built in? Mmmm
  • Distributed communication protocols are built in?
  • We are not in Kansas anymore

Elixir

  • Simple elegant syntax
  • Powerful but minimal standard library
  • Easy to pick up the basics
  • Can easily interface with Erlang, some libraries might already be here and just not be pure Elixir

Phoenix

  • Mind bogglingly fast, consistently
  • Architecture feels familiar
  • Heavily modular
  • Is getting very mature

What is the right answer?

What does this application actually have to do?

  • Read and copy files from a remote server
  • Listen for change on remote server
  • Interface with a service to back up files
  • Process and normalize files
  • Interface with a database
  • Make data available via REST

We have many moving parts, but the processes themselves are simple

Takeaways

When & Why to Use These Tools

When It Works

  • Greenfield projects without obscure requirements
  • Simple APIs
  • Websockets needs
  • Small services
  • Heavy traffic

When It

Wont

  • Super tight deadlines
  • Things that cant allocate time for functions that may just be a gem drop-in with Rails
  • If you cant invest time in ops and research/learning

Developer Wins

Built In Docs Makes Learning Easy

iex(1)> h String.split

                               def split(binary)

Divides a string into substrings at each Unicode whitespace occurrence with
leading and trailing whitespace ignored. Groups of whitespace are treated as a
single occurrence. Divisions do not occur on non-breaking whitespace.

Clean, Modular Code

defmodule App.CronJob do
  use GenServer

  def start_link() do
    GenServer.start_link(__MODULE__, [])
  end

  def init([]) do
    schedule_work()
    {:ok, []}
  end

  def handle_info(:work, state) do
    state = do_work(state)
    schedule_work()
    {:noreply, state}
  end

  defp do_work(state) do
    2 * 2 # or call some other module/function etc
    IO.puts "running"
  end

  defp schedule_work do
    Process.send_after(self(), :work, (60 * 1_000)) # one/minute
  end
end
GenServer.call(App.CronJob, [])

Oh, the concurrency & parallelism

:observer

Community
CommunityCommunity

Business Wins

Servers Are Expensive? Lol Nah.

Portability

From the docs:

A Competitive Edge

Paul Graham, Beating the Averages

Architecting It All

Essential Flow

  • FTP Monitor listens for change
  • FTP Download Worker spawned if change happens
  • S3 worker backs up new files
  • Splitter splits files evenly
  • Preprocessor processes files
  • Database Loader inserts/updates records
  • API lets you query data

Umbrellas

  • Many isolated apps
  • Build tools make it easy
  • Keep everything in one place but easily separable

Simple Modules

File Splitter

  • Take in a path
  • Split some files by the number of lines specified
  • Write it out to a given directory

Database Loader

  • Use PG_COPY to update in bulk after processing
  • Handle regular updates using normal querying when new data is available

OTP Apps

Supervisors & Trees & Workers, oh my!

Periodic S3 + FTP Listeners

  • List the files on FTP server or S3 Bucket, keep track of the state
  • If the state changes, send a message

FTP & S3 Downloads/Uploads

  • When summoned, download or upload the selected file
  • Do this reliably, and do nothing else

File Preprocessor

  • Our files need scrubbing. These folks did us no favors here
  • Use custom rules etc to create something reasonable

Phoenix API

  • A simple search endpoint for first/last name

Our Application

Core Ideas

  • Isolated, simple components
  • Single responsibilities
  • Communicate via messages & leverage OTP

Deployment

For the Hobbyist:

Digital Ocean/Cloud Provider

For the Team Lacking an Ops Person:

Heroku

The Big Kid Solution:

AWS

The "I Have a Robust Ops Team" Option:

Self-Administration & Configuration

Deployment Tools

git push heroku master

Exrm

Edeliver

Woes Along The Way

Also:
 

An Idea for a Community Initiative

Q & A

Richard Nixon & RFC 768

By Bobby Grayson

Richard Nixon & RFC 768

  • 1,840