LiveBook-inspired code styling, remove line-number highlighting
Torey Heinz
committed Feb 22, 2026
commit d1f3c647acd80ac9eed3552a3119f220eafb027c
Showing 3
changed files with
44 additions
and 134 deletions
scratch.md
+3
-1
| @@ | @@ -145,7 +145,9 @@ During my intro I want make sure to give a shout out to my employer Vianet Manag |
| **3.1 Email Marketing System** (6-8 min) | |
| - The challenge: 500k+ personalized emails | |
| - The challenge: Send 500k+ personalized emails through AWS, and if you exceed your rate limit AWS doesn't let you know, they just drop it. | |
| - | |
| + | - Each email sent generates 3-4 requests |
| + | - We don't want to take all day to send, it needs to be fast. |
| + | - we don't want to double send |
| **3.3 Internal Admin App** | |
| - one of the values here is that instead of building admin tools into the main app, you can keep the main app focused on delivering business value. | |
slides/03-real-world.html
+28
-130
| @@ | @@ -59,7 +59,7 @@ |
| <h2>The Challenge</h2> | |
| <p>Send <strong>500,000+ personalized marketing emails</strong> through AWS SES.</p> | |
| <div class="callout fragment"> | |
| - | <p><strong>The catch:</strong> If you exceed your rate limit, AWS doesn't tell you — they <strong>silently drop your emails</strong>. No error, no bounce, no notification.</p> |
| + | <p><strong>The catch:</strong> If you exceed your rate limit, AWS doesn't tell you — they <strong>silently drop your emails</strong>.</p> |
| </div> | |
| <ul> | |
| <li class="fragment">Rate limiter that <strong>never</strong> exceeds the AWS SES sending rate</li> | |
| @@ | @@ -75,29 +75,10 @@ |
| <section> | |
| <h2>The Architecture</h2> | |
| - | <div class="arch-diagram"> |
| - | Application Supervisor |
| - | ┌──────────┬──────────────┬───────────┐ |
| - | │ Phoenix │ EmailRate │ Oban │ |
| - | │ Endpoint │ Limiter │ (Job Queue│) |
| - | │ │ (GenServer) │ │ |
| - | └──────────┘──────────────┘───────────┘ |
| - | ▲ │ |
| - | │ ┌────┴────┐ |
| - | │ │Scheduler│ |
| - | │ │ Worker │ |
| - | │ └────┬────┘ |
| - | │ │ |
| - | │ ┌─────────┴────────┐ |
| - | │ │ 2,000 at a time │ |
| - | │ └─────────┬────────┘ |
| - | │ │ |
| - | │ ┌─────────┴────────┐ |
| - | └─────│ Mailer Workers │ |
| - | │ (one per email) │ |
| - | └──────────────────┘</div> |
| + | |
| <ol style="font-size: 0.65em; margin-top: 15px;"> | |
| - | <li class="fragment"><strong>Scheduler Worker</strong> queries DB, creates email jobs — 2,000 at a time</li> |
| + | <li class="fragment"><strong>Scheduler Worker</strong> queries DB, creates email jobs — in batches of 2,000</li> |
| + | <li class="fragment"><strong>Oban</strong> picks up each job and triggers a <strong>Mailer Worker</strong></li> |
| <li class="fragment"><strong>Mailer Worker</strong> handles one email: validate, personalize, rate-check, send</li> | |
| <li class="fragment"><strong>Rate Limiter</strong> (GenServer) ensures we never exceed the AWS SES limit</li> | |
| </ol> | |
| @@ | @@ -111,28 +92,18 @@ |
| <h2>The Supervision Tree</h2> | |
| <p class="muted small">The actual <code>application.ex</code> — entry point that starts every process</p> | |
| - | <pre class="small-code"><code class="language-elixir" data-trim data-line-numbers="4-14|8|11|12"> |
| - | defmodule Marketing.Application do |
| - | use Application |
| - | |
| - | def start(_type, _args) do |
| - | children = [ |
| - | MarketingWeb.Telemetry, |
| - | Marketing.Repo, # Database connection pool |
| - | Marketing.PuppiesRepo, # Multi-database support |
| - | Marketing.ReputableRoomsRepo, |
| - | Marketing.RoommatesRepo, |
| - | Marketing.NuzzleRepo, |
| - | {Phoenix.PubSub, name: Marketing.PubSub}, |
| - | {Finch, name: Marketing.Finch}, # HTTP client |
| - | MarketingWeb.Endpoint, # Web server |
| - | Marketing.EmailRateLimiter, # ← Our rate limiter process |
| - | {Oban, Application.fetch_env!(:marketing, Oban)} # Job queue |
| - | ] |
| - | |
| - | opts = [strategy: :one_for_one, name: Marketing.Supervisor] |
| - | Supervisor.start_link(children, opts) |
| - | end |
| + | <pre class="small-code"><code class="language-elixir" data-trim> |
| + | def start(_type, _args) do |
| + | children = [ |
| + | Marketing.Repo, # Database |
| + | MarketingWeb.Endpoint, # Web server |
| + | {Phoenix.PubSub, ...}, # PubSub |
| + | {Finch, ...}, # HTTP client |
| + | Marketing.EmailRateLimiter, # ← Rate limiter process |
| + | {Oban, ...} # ← Job queue |
| + | ] |
| + | |
| + | Supervisor.start_link(children, strategy: :one_for_one) |
| end | |
| </code></pre> | |
| @@ | @@ -150,12 +121,12 @@ end |
| <h2>The Rate Limiter</h2> | |
| <p class="muted small">A GenServer using a token bucket algorithm</p> | |
| - | <pre class="small-code"><code class="language-elixir" data-trim data-line-numbers="1-5|8|11-13|15-27"> |
| + | <pre class="small-code"><code class="language-elixir" data-trim> |
| defmodule Marketing.EmailRateLimiter do | |
| use GenServer | |
| defstruct tokens: 0.0, capacity: 50.0, rate: 25.0, | |
| - | daily_remaining: 500_000, last_refill_ms: nil |
| + | daily_remaining: 750_000, last_refill_ms: nil |
| # Public API — other code just calls this | |
| def ready?, do: GenServer.call(__MODULE__, :acquire) | |
| @@ | @@ -227,7 +198,7 @@ end |
| <h2>The Mailer Worker</h2> | |
| <p class="muted small">Pattern matching handles every possible failure</p> | |
| - | <pre class="small-code"><code class="language-elixir" data-trim data-line-numbers="3-11|12-19"> |
| + | <pre class="small-code"><code class="language-elixir" data-trim> |
| def perform(%Oban.Job{args: args} = job) do | |
| campaign_id = Map.get(args, "campaign_id") | |
| member_id = Map.get(args, "member_id") | |
| @@ | @@ -256,46 +227,11 @@ end |
| </aside> | |
| </section> | |
| - | <section> |
| - | <h2>Reading the <code>else</code> Block</h2> |
| - | <ul class="kv-list"> |
| - | <li class="fragment"> |
| - | <span class="kv-key">Rate exceeded?</span> |
| - | <span class="kv-val">→ Snooze 1 second, try again</span> |
| - | </li> |
| - | <li class="fragment"> |
| - | <span class="kv-key">Daily limit hit?</span> |
| - | <span class="kv-val">→ Snooze with exponential backoff, up to 1 hour</span> |
| - | </li> |
| - | <li class="fragment"> |
| - | <span class="kv-key">Already sent?</span> |
| - | <span class="kv-val">→ Discard (don't double-send)</span> |
| - | </li> |
| - | <li class="fragment"> |
| - | <span class="kv-key">Invalid email?</span> |
| - | <span class="kv-val">→ Discard (don't retry what won't work)</span> |
| - | </li> |
| - | <li class="fragment"> |
| - | <span class="kv-key">AWS rejected?</span> |
| - | <span class="kv-val">→ Discard</span> |
| - | </li> |
| - | <li class="fragment"> |
| - | <span class="kv-key">Any other error?</span> |
| - | <span class="kv-val">→ Retry (Oban handles retry logic)</span> |
| - | </li> |
| - | </ul> |
| - | <p class="fragment" style="font-size: 0.8em; margin-top: 0.5em;">Every possible outcome handled. <strong>No silent failures. No lost emails.</strong></p> |
| - | |
| - | <aside class="notes"> |
| - | Let's read that else block like a specification. Rate exceeded — snooze 1 second. Daily limit — backoff up to an hour. Already sent — discard, don't double-send. Invalid email — discard, don't retry what won't work. AWS rejected parameters — discard. Anything else — retry with Oban's built-in retry logic. Every outcome is covered. |
| - | </aside> |
| - | </section> |
| - | |
| <section> | |
| <h2>Scheduling 500k Jobs</h2> | |
| <p class="muted small">Stream records in chunks — constant memory usage</p> | |
| - | <pre><code class="language-elixir" data-trim data-line-numbers="5-8|11-15"> |
| + | <pre><code class="language-elixir" data-trim> |
| defmodule Marketing.CampaignSchedulerWorker do | |
| use Oban.Worker, queue: :default, max_attempts: 1 | |
| @chunk_size 2_000 | |
| @@ | @@ -361,7 +297,7 @@ end |
| <h2>The Connection</h2> | |
| <p class="muted small"><code>with</code> chains — same pattern as the email worker</p> | |
| - | <pre><code class="language-elixir" data-trim data-line-numbers="3-6|8-11"> |
| + | <pre><code class="language-elixir" data-trim> |
| def connect(host, port, username, password, opts \\ []) do | |
| with {:ok, socket_info} <- establish_ssl_connection(host, port, opts, timeout), | |
| {:ok, greeting} <- read_greeting(socket_info, timeout), | |
| @@ | @@ -393,7 +329,7 @@ end |
| <h2>Binary Pattern Matching</h2> | |
| <p class="muted small">Something you <strong>can't easily do</strong> in most languages</p> | |
| - | <pre><code class="language-elixir" data-trim data-line-numbers="3-5|7-8"> |
| + | <pre><code class="language-elixir" data-trim> |
| # Sending: 4-byte length header (big-endian) + XML payload | |
| def send_frame(socket_info, xml_data) do | |
| xml_bytes = :unicode.characters_to_binary(xml_data, :unicode, :utf8) | |
| @@ | @@ -427,7 +363,7 @@ end |
| <h2>Connection Pool</h2> | |
| <p class="muted small">Long-lived TCP sessions managed as supervised processes</p> | |
| - | <pre class="small-code"><code class="language-elixir" data-trim data-line-numbers="4-6|8-22"> |
| + | <pre class="small-code"><code class="language-elixir" data-trim> |
| defmodule OrbitFour.Epp.ConnectionPool do | |
| use GenServer | |
| @@ | @@ -470,7 +406,7 @@ end |
| <h2>Health Checks</h2> | |
| <p class="muted small">Pattern matching handles every possible socket state</p> | |
| - | <pre><code class="language-elixir" data-trim data-line-numbers="1-2|4-5|7-12|14-19|21-22"> |
| + | <pre><code class="language-elixir" data-trim> |
| # No socket — unhealthy | |
| defp connection_healthy?(%Connection{socket: nil}), do: false | |
| @@ | @@ -506,44 +442,6 @@ defp connection_healthy?(_conn), do: false |
| </aside> | |
| </section> | |
| - | <section> |
| - | <h2>OrbitFour Supervision Tree</h2> |
| - | <p class="muted small">One supervisor managing everything</p> |
| - | |
| - | <pre class="small-code"><code class="language-elixir" data-trim data-line-numbers="5-14"> |
| - | defmodule OrbitFour.Application do |
| - | use Application |
| - | |
| - | def start(_type, _args) do |
| - | children = [ |
| - | OrbitFourWeb.Telemetry, |
| - | OrbitFour.Repo, # Database |
| - | {Phoenix.PubSub, name: OrbitFour.PubSub}, |
| - | {Finch, name: OrbitFour.Finch}, # HTTP client |
| - | {Oban, ...}, # Job queue |
| - | OrbitFour.Epp.ConnectionPool, # ← TCP connection pool |
| - | OrbitFour.Epp.HealthCache, # ← Periodic health checks |
| - | OrbitFour.Billing.ExchangeRates, # ← Currency rates cache |
| - | OrbitFour.Rdap.Cache, # ← WHOIS data cache |
| - | OrbitFourWeb.Endpoint # Web server |
| - | ] |
| - | |
| - | opts = [strategy: :one_for_one, name: OrbitFour.Supervisor] |
| - | Supervisor.start_link(children, opts) |
| - | end |
| - | end |
| - | </code></pre> |
| - | |
| - | <p class="fragment" style="font-size: 0.7em; color: #555;"> |
| - | DB, web server, TCP pool, health monitors, caches, job queue —<br/> |
| - | all supervised. If the connection pool crashes, the supervisor restarts it.<br/> |
| - | <strong>No pager alerts. No manual restarts.</strong> |
| - | </p> |
| - | |
| - | <aside class="notes"> |
| - | Here's OrbitFour's full supervision tree. Database, web server, TCP connection pool, health monitors, exchange rate caches, WHOIS caches, job queue — all in one tree. If the connection pool crashes from a bad TCP state or network blip, the supervisor restarts it. New connections are established automatically. No pager alerts, no manual intervention. |
| - | </aside> |
| - | </section> |
| <!-- ============================================= | |
| SECTION 3.3: Internal Admin | |
| @@ | @@ -577,7 +475,7 @@ end |
| <h2>Multi-Database Architecture</h2> | |
| <p class="muted small">Connects to <strong>five databases</strong> simultaneously</p> | |
| - | <pre class="small-code"><code class="language-elixir" data-trim data-line-numbers="5-16"> |
| + | <pre class="small-code"><code class="language-elixir" data-trim> |
| defmodule VianetAdmin.Application do | |
| use Application | |
| @@ | @@ -618,7 +516,7 @@ end |
| <h2>LiveView: Real-Time Admin Forms</h2> | |
| <p class="muted small">Loading data from three databases asynchronously</p> | |
| - | <pre class="small-code"><code class="language-elixir" data-trim data-line-numbers="4-7|8-16"> |
| + | <pre class="small-code"><code class="language-elixir" data-trim> |
| def mount(params, _session, socket) do | |
| {form, action} = | |
| if Map.has_key?(params, "id") do | |
| @@ | @@ -659,7 +557,7 @@ end |
| <h2>LiveView: Real-Time Presence</h2> | |
| <p class="muted small">Multiple admins viewing the same record can see each other</p> | |
| - | <pre><code class="language-elixir" data-trim data-line-numbers="1-5|8-13|15-18"> |
| + | <pre><code class="language-elixir" data-trim> |
| # Track this admin's presence | |
| Presence.track(self(), "admin:presence", admin.id, %{ | |
| initials: Utilities.initials(admin), | |
| @@ | @@ -697,7 +595,7 @@ end |
| <h2>LiveView: Async Charts</h2> | |
| <p class="muted small">Data loads asynchronously, pushes chart updates to the browser</p> | |
| - | <pre class="small-code"><code class="language-elixir" data-trim data-line-numbers="5-7|10-17|20-24"> |
| + | <pre class="small-code"><code class="language-elixir" data-trim> |
| def mount(_params, _session, socket) do | |
| socket = | |
| socket | |
slides/shared.css
+13
-3
| @@ | @@ -46,19 +46,29 @@ |
| border-radius: 4px; | |
| } | |
| - | /* ----- Code ----- */ |
| + | /* ----- Code (LiveBook-inspired dark theme) ----- */ |
| .reveal pre { | |
| width: 90%; | |
| font-size: 0.55em; | |
| - | box-shadow: 0 4px 12px rgba(0,0,0,0.1); |
| - | border-radius: 8px; |
| + | background: #1e1e2e; |
| + | border-radius: 14px; |
| + | box-shadow: 0 4px 20px rgba(0,0,0,0.25); |
| + | padding: 0; |
| + | } |
| + | |
| + | .reveal pre code { |
| + | font-family: "JetBrains Mono", "Fira Code", "Cascadia Code", monospace; |
| + | background: #1e1e2e; |
| + | border-radius: 14px; |
| + | padding: 1em; |
| } | |
| .reveal code { | |
| font-family: "JetBrains Mono", "Fira Code", "Cascadia Code", monospace; | |
| } | |
| + | |
| /* ----- Section Dividers ----- */ | |
| .reveal .section-divider { | |