وقتی ایجنتها بکاند مینویسن: ۹ از ۱۰ اپ داده رو خراب کردن
خلاصهٔ کاملتر
این گزارش رو خود تیم Convex منتشر کرده و طبیعتاً محصول خودشون هم توش برندهست، ولی روش آزمایشش قابلبررسیه و کدش رو هم متنباز کردن. کاری که کردن این بود: از چند مدل — از جمله Opus و Fable از Anthropic و دو مدل از OpenAI — خواستن ده اپ یکسان رو تکشات بسازن، یکبار روی Postgres و یکبار روی Convex. پرامپتها هیچ حرفی از قفل، تراکنش یا شرایط رقابتی نمیزدن؛ فقط میگفتن مثلاً «بذار مردم چیز بخرن».
نتیجهای که گزارش کردن اینه: زیر بار همزمان، ۹ اپ از ۱۰ اپ Postgres یا از کار افتادن یا بیسروصدا داده رو خراب کردن — و همزمان با خوشرویی پاسخ HTTP 200 برگردوندن. نمونههاش دقیقاً همون کابوسهای آشنان: رزرو همزمان دو نفر برای یه بازهٔ زمانی، شمارش اشتباه رأی، فروش بیشتر از موجودی انبار، سبد خریدی که وسط پرداخت جارو میشه، و یه مورد که سرور کلاً قفل کرد. نسخههای Convex همون ده اپ به گزارش تیم هیچکدوم این مشکل رو نداشتن.
توضیحی که برای این شکاف میدن روی پیشفرضها تمرکز داره نه روی هوش مدل. تو Convex هر mutation بهعنوان یه تراکنش سریالپذیر اجرا میشه و وقتی دو نوشتن به هم بخورن، بازنده خودکار روی نتیجهٔ کامیتشده دوباره تلاش میکنه. تو Postgres پیشفرض برعکسه: کد ظاهراً درست، زیر بار بیسروصدا غلط میشه، مگه اینکه یکی بدونه باید برای تکتک عملیات قفل یا قید مناسب رو دستی اضافه کنه. همین کد ساده، دو سرنوشت متفاوت پیدا میکنه:
function sellItem(id) {
const item = db.get(id);
db.set(id, { stock: item.stock - 1 });
}دو خریدار همین آیتم رو میخونن و هر دو برش میگردونن، پس یکی از دو کاهش موجودی بیسروصدا گم میشه. همون منطق داخل یه mutation این شکلیه:
const sellItem = mutation((ctx, id) => {
const item = ctx.db.get(id);
ctx.db.patch(id, { stock: item.stock - 1 });
});نکتهٔ جالب دیگه اینه که مدلها لزوماً از قفل بیخبر نبودن، بلکه ناقص بهکارش بردن. تو یکی از نمونهها مدل تو ۵ مسیر نوشتن از ۶ مسیر، ستون رو قفل کرده بود ولی مسیر حذف کارت رو جا انداخته بود؛ ساخت و حذف همزمان، ترتیب کارتها رو خراب میکرد. تو نمونهٔ دیگه، مدل خود آگهی و موجودیش رو قفل کرده بود ولی سبد خرید رو نه، و یه حذف کلی، آیتمی که وسط پرداخت به سبد اضافه شده بود رو میبرد. تیم Convex ادعای دیگهای هم داره: بلادرنگ بودن. چون هر کوئری یه اشتراک زندهست، هر نوشتن کامیتشده خودش به همهٔ کلاینتهای ناظر میرسه، در حالی که تو اپهای تولیدشدهٔ Postgres عملاً هیچ کانال زندهای وجود نداشت.
نکات کلیدی:
- ده اپ یکسان با چند مدل، یکبار روی Postgres و یکبار روی Convex ساخته شد
- به گزارش Convex، ۹ از ۱۰ اپ Postgres زیر بار همزمان بیسروصدا داده رو خراب کردن
- خرابیها با پاسخ موفق ۲۰۰ همراه بود، پس تو تستهای معمولی دیده نمیشه
- در Convex هر mutation یه تراکنش سریالپذیره و در تعارض خودکار دوباره اجرا میشه
- مدلها اغلب قفل رو میشناختن ولی ناقص و در بخشی از مسیرهای نوشتن بهکار میبردن
- گزارش از سوی خود فروشنده منتشر شده، ولی کد و روش آزمایش متنبازه




