
























One of the scariest parts about hitting "send" on an email is the feeling that there's no takesies-backsies. As soon as it starts hitting people's inboxes, you are left without a mechanism to fix any mistakes. A broken link in a blog post is a minor embarrassment; a broken link in an email to ten thousand subscribers is a small catastrophe.
This is why Buttondown checks every link in your email before you send it, and why the machinery behind that check is more involved than you might expect.
Our link checking infrastructure makes the most sense viewed through the lens of its development: just like in so many things, we started naively and grew increasingly robust over time.
---
config:
layout: elk
elk:
mergeEdges: true
nodePlacementStrategy: LINEAR_SEGMENTS
---
flowchart-elk
A["Extract URLs from email body"] --> B{"Malformed?"}
B -- "Yes" --> WARN
B -- "No" --> D{"Cached?"}
D -- "Hit (safe)" --> SAFE
D -- "Hit (warn)" --> WARN
D -- "Hit (block)" --> BLOCK
D -- "Miss" --> F["HEAD https://foo.com"]
F --> G{"2xx?"}
G -- "Yes" --> L
G -- "No (404/405)" --> I["GET https://foo.com"]
I --> J{"2xx?"}
J -- "Yes" --> L
J -- "No / Timeout" --> WARN
L["Check external services (Google Web Risk, SURBL, Spamhaus)"] --> M{"Flagged?"}
M -- "No" --> SAFE
M -- "Yes" --> BLOCK
SAFE["Safe to send"] --> P
WARN["Broken link warning"] --> P
BLOCK["Block send"] --> P
P[("Cache result (client + server)")]
subgraph Client-Side
A
B
D
end
subgraph Server-Side
F
G
I
J
L
M
end
classDef reject fill:#dc2626,stroke:#991b1b,color:#fff
classDef success fill:#16a34a,stroke:#166534,color:#fff
classDef warn fill:#ca8a04,stroke:#854d0e,color:#fff
classDef process fill:#2563eb,stroke:#1e40af,color:#fff
classDef cache fill:#9333ea,stroke:#6b21a8,color:#fff
class BLOCK reject
class SAFE success
class WARN warn
class F,I,L process
class P cache
You might be wondering what actually processes the asynchronous work mentioned above. We used to use RQ exclusively (and still do in a handful of places), but this and other workloads have moved to AsynchronousAction, our home-built Postgres-based task runner. We'll write more about it soon!
此内容由惯性聚合(RSS阅读器)自动聚合整理,仅供阅读参考。 原文来自 — 版权归原作者所有。