همه پست‌ها

انتقال ThisThat از Firebase در حین اجرای کمپین‌ها

مهاجرت زنده SaaS از Python Firebase Functions به Node.js و PostgreSQL — آزمون‌های برابری، برش ماژول به ماژول، و چرا big-bang نکردیم.

  • Node.js
  • migration
  • PostgreSQL
  • multi-tenant
  • SaaS
تصویرسازی مهاجرت زنده از Serverless به Node.js

ThisThat کمپین‌های برندها را اجرا می‌کند جایی که کاربران بین تصاویر جفت‌شده در دوره‌های تورنAMENT رأی می‌دهند. وقتی به صورت دورکاری پیوستم، بک‌اند Python روی Firebase Functions بود. ترافیک را مدیریت می‌کرد. همچنین هر بار که بازاریابی شکل کمپین جدیدی می‌خواست گسترش آن سخت‌تر می‌شد و cold startها تأخیر را غیرقابل پیش‌بینی می‌کرد.

برنامه Node.js، PostgreSQL، Sequelize و کدبیسی بود که تیم کوچک واقعاً بتواند به اشتراک بگذارد. نکته: کمپین‌ها زنده بودند. برندها در وسط رقابت بودند. «در تولید درستش می‌کنیم» روی میز نبود.

تطابق خروجی Firebase، تابع به تابع

همه چیز را یکجا بازنویسی نکردیم. همه Firebase Functions را لیست کردیم، هر کدام را به یک مسیر NestJS و مدل Sequelize نگاشتیم و payloadهای واقعی تولیدی را ضبط کردیم. آزمون‌های برابری خروجی‌های قدیم و جدید را برای انتخاب جفت، ثبت رأی، پیشرفت دوره و محاسبه برنده مقایسه کردند.

معیار رفتار دقیق بود، نه «تقریباً کافی». یک تفاوت گرد کردن در شمارش رأی‌ها جزئیات بازسازی نیست وقتی یک برند کمپین پولی اجرا می‌کند. ایزولاسیون multi-tenant هم باید سخت‌تر می‌شد — تورنAMENTها، دارایی‌ها و نتایج هر برند در زیرساخت مشترک پارتیشن‌بندی شده بدون نشت بین‌برند وقتی ترافیک را منتقل کردیم.

برش به صورت ماژول به ماژول اتفاق افتاد. مقایسه خروجی‌ها، مهاجرت ردیف‌ها به صورت دسته‌ای، تماشای نرخ خطاها، اصلاح رو به جلو وقتی چیزی منحرف شد. هیچ تغییر پرچم آخر هفته‌ای.

راه‌اندازی کمپین نیمی از مهاجرت بود

درد زیادی API رأی‌گیری نبود. قبل از مهاجرت، راه‌اندازی کمپین اغلب شامل توسعه‌دهندگان بود: آپلود تصاویر جفت، پیکربندی دوره‌ها، تنظیم قوانین اختصاصی برند، کپی پیکربندی بین محیط‌ها. ابزارهای مدیریت در کنسول‌های Firebase و اسکریپت‌های یکبار مصرف پراکنده بود.

پیکربندی کمپین را به یک پنل منتقل کردیم — تصاویر جفت، ساختار دوره، تنظیمات برند، پنجره‌های انتشار. بازاریابی می‌توانست تورنAMENT را بدون ارسال تیکت توسعه‌دهنده برای هر راه‌اندازی بالا ببرد. این کار راه‌اندازی دستی را حدود سی درصد کاهش داد. برای محصولی که هفتگی کمپین جدید تحویل می‌داد، این به اندازه حذف cold startها اهمیت داشت.

چه چیزی پس از برش بهبود یافت

به برابری عملکردی بدون شکستن کمپین‌های زنده رسیدیم. تأخیر متوسط API حدود بیست درصد کاهش یافت وقتی تغییرپذیری cold-start از بین رفت و مسیرهای کوئری تنگ‌تر شدند. یک کدبیس Node به تیم اجازه داد تغییرات مدیریت و رأی‌گیری را در همان pull request تحویل دهد به جای هماهنگی توابع Python و ابزارهای جداگانه.

Serverless هنوز برای handlerهای نوک‌تیز و ایزوله مناسب است. وضعیت تورنAMENT با محدودیت‌های رابطه‌ای، CRUD مدیریت، و ویرایش‌های کمپین زنده سرویس در حال اجرای طولانی و PostgreSQL را می‌طلبید. همان playbook اگر دوباره انجام دهم: آزمون‌های برابری اول، برش ماژول دوم، هیچ قهرمانی در شب جمعه.