How we rolled out one of the largest Python 3 migrations ever

Bài tóm tắt Dropbox 2018 4. Điều chỉnh Độ khó: Trung bình

Dropbox · 2018 · 4. Điều chỉnh · Độ khó: Trung bình — bài gốc

Bài đầu của một series về app desktop Dropbox; chỉ kể kiến trúc build và cách rollout.

Bối cảnh

  • App desktop Dropbox (Windows, macOS, Linux) phần lớn viết bằng Python từ dòng code đầu tiên; hơn 1 triệu dòng Python, hàng trăm triệu bản cài, phát hành cho mọi user mỗi hai tuần (2018). Bắt đầu chuyển sang Python 3 từ 2015.
  • Lý do: type annotation (Dropbox dùng mypy nhiều), cú pháp async/await; và toolchain già: Python 2 trên Windows gắn với Visual Studio 2008 (hết hỗ trợ, không dùng được Windows 10 SDK), Qt mới cần compiler mới.
  • Build dựa trên "freezer" (py2exe, py2app, bbfreeze) qua một script build-all.py kiểu setup.py đã phình to. Code giờ trộn TypeScript, Rust, Python, Objective-C, C++; extension của OS (FinderSync trên macOS là một app package riêng do OS khởi chạy, thành phần kernel của Smart Sync) cần toolchain gốc như Xcode mà freezer không hỗ trợ.

Thay đổi chính

  • Chọn bỏ freezer thay vì vá nó cho Python 3: nhúng runtime Python vào app native. Entry point (Dropbox.exe, Dropbox.app, dropboxd) build bằng Visual Studio, Xcode, make; Python nằm sau một thư viện.
  • Bước 1 "Anti-freeze" (từ 2016): thư viện libdropbox_bootstrap lo cấu hình runtime và khởi động thread Python; một định dạng đóng gói chung cho mọi nền tảng (bytecode trong một file ZIP, extension native đặt cạnh entry point); cô lập interpreter khỏi Python khác trên máy (Py_SetPath, được backport vào bản Python 2 tự fork). Chuyển sang Visual Studio 2013, phải sửa nhiều bản fork Python 2 để build được.
  • Bước 2 "Hydra": ship cả gói Python 2 và Python 3 cạnh nhau; entry point chọn runtime trước khi nạp Python (dlopen/LoadLibrary), điều khiển bằng cờ dòng lệnh khi dev và một setting trên đĩa do Stormcrow (feature gate) đặt. Code viết theo cú pháp lai 2/3 trong thời gian chuyển; CI có job riêng chạy test trên Python 3, commit queue chặn thay đổi làm hỏng Python 3.
  • Rollout: nhân viên Dropbox trước (bắt phần lớn lỗi) → một phần nhóm Beta (đa dạng phiên bản OS hơn) → Stable; mọi bug liên quan migration phải điều tra và sửa xong trước khi mở rộng thêm. Trong 7 tháng mọi bản cài chạy Python 3; từ phiên bản 52 Python 2 bị gỡ hẳn.

Vì sao

  • Kiến trúc nhúng tách việc "đổi runtime" thành hai bước: đổi cách build quanh Python 2 trước, rồi dùng chính kiến trúc đó để thay Python 2 bằng Python 3.

Bài học cho SWE

  • Với phần mềm cài trên máy người dùng, không có "flip a switch": cần chạy hai runtime song song và feature gate từ xa để mở dần theo nhóm.
  • Đổi hệ thống build trước khi đổi ngôn ngữ: khi runtime đã nằm sau một thư viện, thêm biến thể thứ hai là việc nhỏ.
  • Cổng CI chặn hồi quy trên runtime mới giữ cho codebase không trượt lại trong suốt nhiều năm chuyển.

Liên quan