Ewolucja Dropboxa. Migracja z Pythona 2 na Pythona 3

W przeciągu ostatnich 12 lat, Dropbox urósł do miana jednej z najbardziej popularnych aplikacji desktopowych na świecie (liczy już ponad 500 milionów użytkowników i zatrudnia około 1,8 tys. osób), która zapewnia wirtualną przestrzeń dyskową pozwalającą na wysyłanie i pobieranie danych. Składa się ona z ponad miliona linii kodu, dziennie przetwarza około 12 miliardów plików, wspiera 20 języków programowania, a także jest kompatybilna z takimi platformami, jak Windows, macOS oraz niektóre dystrybucje Linux.

Pomysł na Dropboxa narodził się w 2006 roku, kiedy to 24-letni Drew Houston, chcąc popracować nad jednym ze swoich planów na biznes podczas 6-godzinnej jazdy autobusem, zdał sobie sprawę, że zapomniał USB ze wszystkimi potrzebnymi plikami w domu. Tym sposobem, wpadł na pomysł utworzenia zdalnej przestrzeni dyskowej, z której użytkownicy mogliby korzystać z każdego miejsca na świecie. W przeciągu zaledwie dwóch tygodni, Houston miał już zbudowany prototyp oraz wybraną nazwę dla projektu. Dwa miesiące później, Y Combinator, znany sponsor nowych startupów, wyraził zainteresowanie pomysłem Houstona.

Mimo, iż w momencie, w którym Houston zaczął pracę nad Dropboxem na rynku istniało już wiele innych firm oferujących podobną usługę, Dropboxowi udało się wybić ponad nie wszystkie i zdobyć 70 tysięcy użytkowników w przeciągu zaledwie kilku dni. Jego sekretem była presja na marketing, niezwykła prostota interfejsu, a także zastosowanie tak zwanych growth hacks – niemalże bezkosztowych sposobów na pozyskanie klientów, jak na przykład możliwość polecania aplikacji znajomym. 

Po co migracja na Pythona 3?

Aplikacja Dropboxa początkowo działała w większości na Pythonie. Gdy z czasem do użytku zostały włączone także TypeScript/HTML, Rust oraz Objective-C i C++, setup.py stał się niezwykle obszerny, poplątany i ciężki w utrzymaniu. 

Funkcjonalność Dropboxa mogła jednak zostać ulepszona za pomocą Pythona 3, który niósł ze sobą wiele gwałtownych innowacji. Wprowadził on między innymi:

  • adnotacje typów — pozwalające korzystać z zaawansowanych narzędzi do statycznej analizy kodu jak np. MyPy,
  • asyncio — bibliotekę pozwalającą pisać asynchroniczny, współbieżny kod przy użyciu składni ‘async/await`,

Początek wielkiej wędrówki

Migracja na Pythona 3 zaczęła się już w 2015 roku, gdy podczas corocznego Hack Week zespół Dropboxersów podjął się wyzwania mającego na celu zdeterminowanie jak trudna byłaby migracja na Pythona 3. Zespołowi udało się wykonać proof-of-concept, w którym logowanie oraz synchronizacja plików odbywały się za pomocą kodu napisanego w Python 3. Niestety, wiele funkcji przestało działać, co doprowadziło do porzucenia projektu aż do następnego roku, kiedy to podczas Hack Week 2016 kolejny zespół podjął kroki ku przeprowadzeniu migracji. 

Stworzyli oni m.in. zautomatyzowane testy mające na celu zapobiegać regresowi wywołanego z migracją do Pythona 3, w przypadku gdyby ich projekt miał zostać w przyszłości kontynuowany.

W 2017 roku stało się już jasne, że zaadoptowanie nowszej wersji Pythona stanowiło istotny krok na drodze ku aktualizacji wielu narzędzi programistycznych. Rozpoczęto zatem wielomiesięczne przedsięwzięcie, jakim była migracja z Pythona 2 na Pythona 3. 

Aby wdrożyć Pythona 3, zespół Dropboxa zdecydował się na nową architekturę. Zamiast powierzać ten proces w ręce Freezer Skrypt mieli oni w planach zbudowanie punktów wejściowych za pomocą narzędzi specyficznych dla każdej platformy (n.p. Visual Studio dla Windows), dzięki czemu poszczególne punkty wejściowe byłyby kompatybilne z każdą platformą.  

Dodatkowo, zespół Dropboxa miałby możliwość wybrania języka programowania oraz narzędzi, co oznaczało, że byliby oni w stanie użytkować IDEs każdej platformy, tym samym wciąż mając możliwość napisania większości aplikacji w Pythonie. Ponadto, dzięki zwiększonej modulacji architektury Dropboxa, Python 2 i Python 3 mogły zostać zastosowane jednocześnie, co stworzyło okazję na stopniowe zastąpienie Pythona 2 Pythonem 3.

Pierwsze kroki

Ze względu na niekompatybilność bbfreeze i pywin32 z Pythonem 3, jednym z pierwszych kroków podjętych przez zespół było całkowite zaprzestanie używania “freezer” skryptów. Najpierw jednak musieli oni użyć ich, aby zapoczątkować wątki Pythona w nowej bibliotece libdropbox_bootstrap.

Zamiast korzystania z dedykowanego formatu kodu dla każdego z “freezer” skryptów, zostały one zastąpione pojedynczym formatem kodu bajtowego. Następnie wdrożono punkty wejściowe dla każdej platformy (Dropbox.exe, Dropbox.app, oraz dropboxd), które zostały zbudowane za pomocą ich “standardowych” toolchainów: Visual Studio, Xcode oraz make. 

Ze względu na rozmiar aplikacji Dropbox oraz skalę jej użytkowania, proces przejścia z Pythona 2 na Pythona 3 musiał odbywać się stopniowo. Aby tego dokonać, Dropbox musiał mieć możliwość budowania aplikacji na dwóch wersjach Pythona równocześnie. Wiązało się to m.in. z jednoczesnym przesyłaniem “pakietów” Pythona 2 i Pythona 3, zawierających bytecode i rozszerzenia, a także wprowadzeniem w życie hybrydy składni obu wersji tego języka.

Dzięki designowi wprowadzonemu w poprzednim kroku, wybranie danej wersji języka mogło być kontrolowane już w punktach wejściowych (np. Dropbox.app), które utworzono do libdropbox_bootstrap. Ponieważ wybór ten należało dokonać przed wczytaniem Pythona, zespół Dropboxa upewnił się, że możliwe byłoby wpływanie na niego za pomocą zarówno argumentów wiersza poleceń jak i ustawień odczytanych z dysku.

Nowa wersja wchodzi na rynek

Gdy tylko mieli już wystarczającą pewność, że Python 3 działa jak należy, zespół Dropboxa zaczął wprowadzać go na rynek. Najpierw w zmiany wdrożono pracowników Dropboxa, co pozwoliło zespołowi na zidentyfikowanie i poprawienie znacznej części problemów leżących u podstaw całego projektu. Następnie udostępniono zmiany niewielkiej części ich populacji Beta i w końcu zwiększono zasięg o kanał Stable. W przeciągu 7 miesięcy od rozpoczęcia procesu wdrażania nowej wersji aplikacji, wszystkie instalacje Dropboxa działały już na Pythonie 3. 

Podsumowując, proces migracji z Pythona 2 na Pythona 3 został rozłożony na kilka etapów. Proces trwał około 3 lat, zaczynając już w 2015 roku jako wyzwanie podjęte przez drużynę Dropboxersów w trakcie corocznego Hack Week. Było to skomplikowane przedsięwzięcie na wielką skalę, wymagające integracji obu wersji języka i mające na celu zwiększenie produktywności developerów, uporządkowanie kodu, wprowadzenie aktualizacji ważnych zależności, a także umożliwienie kompatybilności z nowymi wersjami toolchains. Migracja na Pythona 3 była zatem istotnym krokiem ku utrzymaniu jakości usług Dropboxa na wysokim poziomie. 


Artykuł powstał m.in. na podstawie tego artykułu. Zdjęcie główne artykułu pochodzi z facebook.com/Dropbox. Autorką artykułu jest Zuzanna Filipiuk.

Patronujemy

 
 
Polecamy
Optymalizowanie kodu. Przedwczesna optymalizacja oraz konwencje nazewnicze w Javie