Chuyện Nghề: Đi Đêm Có Ngày Gặp Ma, Direct Push Có Ngày Gặp Quả Báo

Ở một bài viết trước đó, tui có đề cập đến một dự án về ingest crashlytics data. Mẫu chuyện hôm nay tui kể liên quan đến dự án đó.

Giới thiệu ngắn gọn cái ingestion đã được setup. Khi users sử dụng app mà gặp crash hoặc một số lỗi nhất định thì những trường hợp này sẽ được ghi nhận trên hệ thống của Firebase. Đoạn ingestion là làm sao để mà những data này được đổ vào data lake của công ty. Sau đó kỹ sư có thể viết presto queries để truy vấn thông tin hữu ích. Cái ingestion pipeline này được hiện thực hoá bằng Airflow.

Mỗi tech family có những instances riêng chạy Airflow jobs của tech family đó. Cái code setup mấy đống Airflow jobs của tech family tui đều nằm trong một repo được maintained bởi mấy bạn backend. Nói là được maintained bởi các bản nhưng thật ra về code quality, cá nhân mình thấy cũng ở mức trung bình chứ không phải tốt 😄. Repo cũng rất ít được update. Điều này cũng dễ hiểu vì đó cũng không phải là tech stack chính yếu của team đó.

Lúc mới đầu tiếp quản project, code và sửa đổi chỗ này chỗ kia thì tui tạo merge request rồi nhờ bạn backend trong dự án review, nếu ok thì merge giùm (vì tui chỉ có quyền developer và không merge được) (note: approval là optional 😄). Vì cứ sửa lắc nhắc mà có vẻ bạn backend bận rộn nên không phản hồi nhanh chóng, nên sau vài lần như vậy, tui đề xuất với sếp và các bên, xin luôn quyền maintainer cho repo này. Tui thấy điều này hoàn toàn bình thường vì tất cả backend dev trong repo này đều có quyền maintainer mà.

Cái ingestion pipelines được setup xong. Data đã có, backfill cũng xong. Mọi thứ đều suôn sẻ cho đến khi tui thêm vài bước biến đổi (transformations) để truy vấn dễ dàng hơn 😢. Ai dè cái định dạng data ghi xuống nó không tương thích trong 1 số trường hợp đặc biệt. Cái này chắc luôn là lỗi thư viện.

Sau nhiều lần debug và thử nhiều cách khác nhau, cuối cùng tui cũng fix được issue. Tui cảm thấy khá hài lòng với quá trình debug vì đã dùng nhiều thủ thuật để rút gọn công sức bỏ ra. Niềm hân hoan dâng trào… cho đến một vài ngày sau, cái issue nó lại xảy ra ở một trường hợp đặc biệt khác. Cảm xúc lật ngược như ex lật mặt…

Tui tiếp tục debug và thử nhiều cách fix khác nhau, hòng “truy cùng diệt tận” lũ bọ. Bao nhiêu tà khí tích tụ sau vài ba cái merge request, tui bấm bụng nghĩ “ôi, push thẳng lên master cmn luôn đi”. Hẳn là phật tổ nghe thấy điều này nên đã trừng phạt tui bằng cách khiến tui push code với 1 cái lỗi typo 😢. Sau khi phát hiện cái CI pipeline ửng đỏ (tức là bị failed), tui nhanh chóng nhận ra và sửa liền (dĩ nhiên là lại 1 direct push khác 🤫). CI pipeline xanh trở lại chỉ trong tức khắc. Kiểm tra sơ sơ thấy mọi thứ đều xanh, thật mát lòng. Nhưng hỡi ôi, nó xanh nhưng thật ra nó hổng phải xanh đâu. Ủa phật tổ!

Một ngày đẹp trời, tui thấy một bạn backend của tech family tui post lên slack channel #ask-airflow, nhờ các bạn data engineer hỗ trợ giùm issue. Một cái machine learning pipeline của tech family bị hỏng vì thiếu plugins (note: cái pipeline này là Airflow pipeline, không phải CI pipeline). Nhìn thấy thread trao đổi với mấy chục comment hỏi qua lại, tui tò mò bay vô xem. Nào ngờ đâu, ngỡ xa lạ nhưng lại rất quen. Kiểm tra vài thứ, tui chắc chắn luôn chính cái lần CI pipeline ửng đỏ kia gây ra issue này.

Giải thích sơ về cái issue như sau. Bên dưới là cái CI pipeline của quy trình test - deploy. Mấy cái plugins chẳng qua là mấy file python (static, nội dung cố định), được lưu trên S3. Những file này được fetch về ở job fetch plugins, pass qua mấy job trung gian rồi được sync ngược lại lên S3. Tui cũng không hiểu tại sao lại thiết kế hệ thống kiểu hơi kỳ cục này nữa.

--> test (❌) --> fetch plugins (✔️) --> deploy (❌) --> sync plugins (✔️)

Đáng nhẽ ra khi test failed thì mấy jobs phía sau phải skip, không làm gì hết. Đằng này deploy hỏng mà sync plugins vẫn cứ chạy. Vì plugins không pass qua được (do deploy hỏng) nên việc sync plugins tương đương với thao tác xoá plugins trên S3. Cho nên lần chạy sau mà dùng plugins này thì sẽ tạch… Vậy cách giải quyết issue này rất đơn giản. Chỉ cần retry job sync plugins của 1 pipeline mà ở đó deploy thành công, thì mấy plugins sẽ có lại.

Quay trở lại cái slack thread kia. Mình bay vô giải thích issue, đề xuất cách giải quyết như trên. Nhưng bạn backend bơ mình trên cái thread đó luôn, tiếp tục trao đổi với bạn data engineer. Nói chung cả 2 bản đều không rành CI lắm. Nên bạn data engineer thì kiểu “eh cái này chạy cần có plugins kia mà không thấy, mày làm sao cho có plugins đó đi”. Còn bạn backend chắc cũng không rõ tại sao mấy cái plugins lại biến mất một cách mầu nhiệm như vậy…

Tui chờ hoài không thấy finalize actions gì nên tự vô resolve cho mấy cái plugins có lại. Xong ping bạn backend kêu “tao retry job nọ nên mấy cái plugins có rồi đó, mày retry lại machine learning pipeline của mày thử xem”. Xong rồi tạo merge request để thay đổi lại cấu hình CI pipeline cho nó bớt fragile lại :)). Khoảng 2 ngày sau mới thấy bản reply lại bảo nó ok rồi, rồi merge cái thay đổi trên.

Một hai tuần sau, tui tình cờ phát hiện ra quyền maintainer của mình từ hồi nào đã… bay màu 😯.

Quả báo nhãn tiền!