Building Relay
Xây dựng một công ty nền tảng chat thời gian thực từ một thư mục trống — bao gồm đặc tả, mã nguồn, triển khai và giám sát.
Phần 0 — Ý tưởng và trang giấy
0.1 · Từ ứng dụng đến hạ tầng — đi tìm sản phẩm đích thực
Bạn sẽ tạo ra: Một bản tuyên ngôn định vị; một danh sách non-goals
0.2 · Bốn người sẽ phán xét chúng ta
Bạn sẽ tạo ra: Một bộ chân dung người dùng, bao gồm cả người dùng cuối vô hình
0.3 · Hành trình — nơi những sản phẩm gục ngã
Bạn sẽ tạo ra: Bản đồ hành trình; những khoảnh khắc ★
0.4 · Những yêu cầu bạn có thể kiểm chứng
Bạn sẽ tạo ra: Một lát cắt SRS với đầy đủ ID, độ ưu tiên và phương pháp kiểm chứng
0.5 · Quyết định trên giấy trắng mực đen — bản SAD và thói quen viết ADR
Bạn sẽ tạo ra: Bảng động lực thiết kế (drivers); hai bản ADR viết từ con số không
Phần 1 — Đặt nền móng
1.1 · Monorepo và bộ công cụ
Bạn sẽ tạo ra: Một pnpm workspace chạy được — TypeScript, lint, và bộ test xanh
1.2 · Một câu lệnh, cả thế giới
Bạn sẽ tạo ra: Hạ tầng local một câu lệnh — bốn store, có healthcheck và đã kiểm chứng
1.3 · Package protocol
Bạn sẽ tạo ra: Bản giao kèo đường truyền dùng chung — kiểu frame, mã lỗi, và schema biết từ chối dữ liệu hỏng
1.4 · Bộ khung biết đi
Bạn sẽ tạo ra: Hai service bộ khung chạy được — có health check, request ID, log JSON có cấu trúc
Phần 2 — Vòng lặp cốt lõi
2.1 · Schema có xương sống
Bạn sẽ tạo ra: Schema đã migrate và tầng repository khóa theo tenant — rò rỉ giữa các tenant thành điều không thể viết ra
2.2 · Quá trình gửi tin nhắn
Bạn sẽ tạo ra: Gửi tin nhắn: channel row lock và sequence assignment (ADR-03)
2.3 · Gửi hai lần
Bạn sẽ tạo ra: Idempotency keys, unique index một phần (DR-03)
2.4 · Lịch sử biết phân trang
Bạn sẽ tạo ra: Cursor pagination trên (channel_id, seq)
2.5 · Socket
Bạn sẽ tạo ra: Gateway: WS termination, JWT verify, connection registry
2.6 · Hai server, một cuộc trò chuyện
Bạn sẽ tạo ra: Redis fan-out (ADR-07); lập luận về fabric có thể mất frame
2.7 · Đường hầm
Bạn sẽ tạo ra: Resume protocol: cursor, backfill, buffer subscribe-trước-backfill
2.8 · Cột mốc: bài kiểm tra Tuan
Bạn sẽ tạo ra: Suite e2e cho journey 4 — tiêu chí thoát Phase 1
Phần 3 — Vươn mình thành nền tảng
3.1 · Tenant từ trên xuống dưới
Bạn sẽ tạo ra: Org, app, environment; signup bằng OAuth; environment dev tạo tự động
3.2 · Key và token — hai loại credential, một lỗi thường gặp
Bạn sẽ tạo ra: API keys (prefix, hash, rotation); user JWTs; endpoint dev-token
3.3 · Lỗi có trang để xem
Bạn sẽ tạo ra: Một registry khai báo mọi error code nền tảng có thể gửi, một chỗ duy nhất dựng docs_url, và một hàm ném lỗi có kiểu để code gõ sai không compile được
3.4 · Cửa ải cô lập tenant
Bạn sẽ tạo ra: Một bộ kiểm thử cross-tenant tự suy ra danh sách mục tiêu từ router đang chạy, ba dạng tấn công so sánh một CẶP phản hồi thay vì một mã trạng thái, một kiểm tra cấu trúc rằng mọi bảng đều có đường về tenant, và tầng socket bị tấn công từ chính frame union của protocol
3.5 · Outbox
Bạn sẽ tạo ra: Transactional outbox + relay (ADR-06); crash-in-the-gap test
3.6 · JetStream và consumer đầu tiên
Bạn sẽ tạo ra: Cấu hình stream; subject grammar dùng chung; durable pull consumer tự dedupe
3.7 · Commit và publish là hai khoảnh khắc
Bạn sẽ tạo ra: Khép lại lỗi trùng lặp khi resume: một high-water mark sống lâu hơn buffer
3.8 · Các endpoint và các thiết bị đo
Bạn sẽ tạo ra: Hai endpoint công khai mà Part 3 cần, tính đẳng xâm do unique index bảo đảm chứ không phải do bộ nhớ, mọi lỗi validation lần đầu gọi tên field của nó, guard thao tác toàn cục canh chín bảng thay vì năm, và độ phủ nhánh của tầng repository được trả lời bằng một con số
3.9 · Kênh mà khách hàng kiểm soát
Bạn sẽ tạo ra: Một loại kênh private thực sự quyết định điều gì đó ở cả bốn cửa vào, xoá thành viên và phân quyền, lưu trữ kênh để từ chối gửi tin mà không tiết lộ kênh có tồn tại, và một gauntlet tấn công chính tenant của bạn
3.10 · Những gì một người dùng thấy
Bạn sẽ tạo ra: Danh sách channel phân trang bằng cursor và xếp theo hoạt động, số tin chưa đọc suy ra từ chính sequence mà đường ghi vẫn duy trì, profile người dùng được tạo ngầm ở lần xác thực đầu tiên, một người dùng đã xoá mà tin nhắn vẫn còn, và một lệnh ban có hiệu lực cả ở cửa vào lẫn trên đường gửi
3.11 · Người gửi mà một tin nhắn chưa từng có
Bạn sẽ tạo ra: Bot user mang theo description mà cơ sở dữ liệu bắt buộc, một người gửi trên mọi tin nhắn do compiler bảo đảm chứ không phải test, một credential nói với danh nghĩa phần mềm, không phải con người, từ chối mà không hé lộ ai tồn tại, và một bot vẫn tính tiền như active user nhưng miễn trần gửi
3.12 · Tin nhắn chưa từng tới
Bạn sẽ tạo ra: Một tin nhắn gửi qua REST tới được socket đang mở, một thứ tự tách theo transport vì response của request handler CHÍNH LÀ acknowledgement của nó, một publisher sống sót qua broker đã chết trong 2 ms, và một điều khoản P1 được đo là chưa thoả rồi ghi lại thay vì bị thu hẹp
3.13 · Presence, và ai được phép nhìn thấy
Bạn sẽ tạo ra: Một frame nằm trong protocol union từ chương 1.3 nay mới có bên phát, một subject grammar thứ hai giữ nguyên từng byte đường đi message, một key mà sự tồn tại chính là trạng thái, SET … NX chính là bầu chọn, một grace period mà bản vá đầu khiến người dùng kẹt online, và không dòng code lọc nào
3.14 · Membership đổi ngay dưới một socket đang sống
Bạn sẽ tạo ra: Một điều khoản chưa thoả từ chương 2.6, nay đóng bằng cách đảo ngược bài test đã bắt nó; một ngữ pháp subject thứ ba gửi tới principal thay vì channel, bởi một lần thêm thành viên không thể đi nhờ subject mà instance chưa subscribe; và một lệnh ban tới như một thay đổi, ra một frame mỗi channel
3.15 · Cái frame không ai được gửi
Bạn sẽ tạo ra: Frame đầu vào thứ hai đầu tiên sau hai mươi chương, đứng sau một tập hợp có tên được test ghim; một ngữ pháp subject thứ tư được nhận chứ không né, sau khi đếm lại con số ADR-19 và thấy bảy điểm định kiểu chứ không phải ba; và một phán quyết thành thật về điều khoản nền tảng không làm được
3.16 · Kết nối thứ sáu, và con số ấy sống ở đâu
Bạn sẽ tạo ra: FR-RTM-09 đóng lại ở cả hai nửa: một trần năm kết nối mà không instance gateway nào tự tính được, giữ thành năm khoá slot giành bằng `SET NX PX`; một mã đóng thứ sáu, lời từ chối duy nhất trong bộ mà xử lý đúng không phải thử lại; và một trần hỏng mở ồn ào, dòng log là bằng chứng duy nhất
3.17 · Những lời ai đó muốn lấy lại
Bạn sẽ tạo ra: FR-MSG-07, FR-MSG-08 và FR-MSG-10 được dựng, và hai kind cuối của FR-RTM-05 lần đầu có bên phát: một ngữ pháp subject thứ năm mang cả hai loại thay đổi với kind nằm trong payload, bởi một bia mộ không phải `Message` còn một lần sửa thì là; và hai mã lỗi thay cho 403 chung chung
3.18 · Tin nhắn không chỉ có chữ
Bạn sẽ tạo ra: Nửa external-URL của FR-MSG-11 được dựng: một tin nhắn mang attachment, giới hạn mười phần tử và 2.048 ký tự, bị từ chối trừ khi scheme là http hoặc https. Nửa media_id được hoãn tới §4.14 và bị từ chối đích danh, bằng một mã lỗi riêng.
3.19 · Webhook sống sót qua phía khách hàng
Bạn sẽ tạo ra: Một dispatcher service: ký HMAC, lịch retry theo thời điểm tới hạn, dead letter
3.20 · Khi nào thì thôi cố
Bạn sẽ tạo ra: Bản ghi lần thử trên stream analytics, và auto-disable từ hai trigger
3.21 · Email chẳng ai gửi
Bạn sẽ tạo ra: Mẫu outbox lần thứ ba, trên một cột mà chương "Khi nào thì thôi cố" đã viết sẵn — và Mailpit, vì chỉ thư đã nhận mới chứng minh được email không mang bí mật nào
3.22 · Những giới hạn bạn thấy trước
Bạn sẽ tạo ra: Bộ đếm request theo từng environment, các header trên mọi response, và hai bộ giới hạn hỏng theo hai hướng ngược nhau
3.23 · Quota và cái giá của nó
Bạn sẽ tạo ra: Quota theo tháng, hạn mức chi tiêu, và cách suy giảm chỉ chặn gửi mà không ảnh hưởng history
3.24 · Đếm một kết nối
Bạn sẽ tạo ra: Connection-minutes được đo từ một service không sở hữu bảng nào, một cú crash tính thiếu trong một giới hạn đã biết thay vì tính thừa mãi mãi, và close code 4008 lần đầu được gửi kể từ khi chương 1.3 khai báo nó
3.25 · Cột mốc: cửa ải cô lập tenant
Bạn sẽ tạo ra: Ba lần cố ý tái tạo lỗi — một lần vẫn xanh và dạy ta giới hạn của bộ kiểm thử
3.26 · Cột mốc: một người ngoài tích hợp
Bạn sẽ tạo ra: Một package tích hợp bị niêm phong về mặt cơ chế nên không thể import code trong workspace, và một phán quyết cho tiêu chí ra khỏi Phase 2 của SRS kèm những gì đã đo và những gì chỉ được giả định
Phần 4 — Mọi ngả đường dữ liệu đã đi
4.1 · Câu hỏi mà những bộ đếm không trả lời đượchiện chỉ có bản tiếng Anh
Bạn sẽ tạo ra: Một corpus một triệu tin nhắn, câu truy vấn phân tích lần đầu được viết cho Postgres, và bốn con số cho thấy index lẽ ra phải sửa được nó lại tốn thêm 49% dung lượng mà đổi lại chỉ là nhiễu
4.2 · Kho dữ liệu chưa từng lắng nghehiện chỉ có bản tiếng Anh
Bạn sẽ tạo ra: Một ClickHouse mà truy vấn chạm tới được, một schema phân tích với sổ ghi của riêng nó, và cùng một câu hỏi được trả lời trong 13,22 ms so với 585,9 ms của Postgres — cùng một ngày trong chín mươi mốt ngày không bao giờ đối soát được
4.3 · Consumer đã được hứa hẹnhiện chỉ có bản tiếng Anh
Bạn sẽ tạo ra: Bộ nạp cho một stream đã đầy dần từ chương 3.20 mà chưa ai đọc — khử trùng lặp bằng chính khóa của bản ghi, bởi vì khuôn mẫu được xây để ngăn đúng vấn đề này lại ghi vào cơ sở dữ liệu mà đường dẫn này không được phép chạm tới
Chặng đường phía trước
- Phần 5Trải nghiệm lập trình viênsắp ra mắt
- Phần 6Ship sản phẩmsắp ra mắt
- Phần 7Vận hànhsắp ra mắt
- Phần 8Nhìn lại chặng đườngsắp ra mắt