Kullanıcı gönder butonuna art arda bastığında, bot aynı cevabı iki veya üç kez vermeye başladı. Bu mükerrerlik, yalnızca yapay zeka düşünmeye başlamadan önce birkaç mesajı gönderecek kadar hızlı yazan kişilerde görülüyordu ve desen nadir görüldüğü için üretim ortamında uzun süre fark edilmedi. Vaktinden önce serbest bırakılan bir veritabanı kilidi —alındıktan sadece birkaç milisaniye sonra serbest kalıyordu— konuşmayı korumasız bırakarak birden fazla işlemin aynı isteme yanıt vermesine olanak tanıyordu.

Kilidin neden başarısız olduğu

Kod, tek bir veritabanı çağrısıyla bir kilit alıyor, ardından kontrolü hemen istek işleyiciye (request handler) geri veriyordu. Kilidin ömrü milisaniyelerle ölçülüyordu ve bu süre, yapay zeka modelinin bir yanıt oluşturması için gereken süreden çok daha kısaydı. Model çalışmaya başladığında kilit çoktan yok olmuş oluyordu; bu nedenle ikinci bir isteğin aynı konuşma kaydını alıp başka bir yanıt oluşturmasını engelleyecek hiçbir şey kalmıyordu.

İki belirti ortaya çıktı:

  • Birbirinin ardına özdeş yanıtlar gönderildi.
  • Her işlem kendi istemini aynı kullanıcı girişinden oluşturduğu için, aynı soruya hafifçe yeniden ifade edilmiş yanıtlar geldi.

Çoğu kullanıcı mesajlar arasında duraksadığı için hata radarın altında kaldı. Yalnızca çok hızlı yazanlar yarış durumunu (race condition) tetikliyordu ve bu vakalar nadirdi.

Yetersiz kalan ilk çözüm

İlk tepki, hızlı girdileri "debounce" etmek (gecikme ekleyerek dengelemek) umuduyla bir mesaj geldikten sonra kısa bir gecikme eklemek oldu. Bu, iki mesaj hızlı bir şekilde peş peşe geldiğinde işe yarıyordu; ancak yapay zeka hala metin oluştururken üçüncü bir mesaj gelirse sistem çökmeye başlıyordu.

Zamanlayıcılar ve konuşma verileri aynı depolama alanında (storage bucket) bulunduğu için ikinci bir sorun daha ortaya çıktı. Bot bir isteği işleyip bitirdiğinde, zamanlayıcı kaydının üzerine yazıyor ve böylece kendi geri sayımını silmiş oluyordu. Sistem hangi mesajların halihazırda yanıtlandığını takip edemez hale gelerek daha fazla mükerrerliğe kapı araladı.

Güvenilir bir koruma inşa etmek: versiyon sayaçları, izole zamanlayıcılar ve bir lease

Ekip, iş akışını üç temel sütun üzerine yeniden tasarladı:

  • Versiyon sayacı – Gelen her mesaj, konuşma ile birlikte saklanan bir sayacı artırır. Sayaç, sisteme son yanıttan bu yana kaç mesajın geldiğini söyler; böylece bir yanıt oluşturulurken yeni girdileri tespit etmek kolaylaşır.
  • Özel debounce penceresi – Zamanlayıcılar artık konuşma verilerinden izole edilmiş, ayrı bir depolama alanında tutuluyor. Debounce süresine getirilen katı bir üst sınır, bir kullanıcının botu süresiz olarak bekletmesini engeller.
  • Oturum lease'i (kiralama süresi) – Orijinal kilit, açık bir son kullanma zaman damgasına sahip bir "lease" ile değiştirildi. Lease, bir compare-and-swap (CAS) işlemi kullanılarak alınır: işlem mevcut lease değerini okur, yalnızca eski değer eşleşiyorsa yenisini yazar ve böylece konuşma üzerinde özel haklar kazanır. Eğer işlem çökerse, lease otomatik olarak sona erer ve konuşmayı bir sonraki işleyici için serbest bırakır.

Yeni iş akışı nasıl çalışıyor

  1. Mesajın gelmesi – Sistem versiyon sayacını artırır ve debounce zamanlayıcısını (yeniden) ayarlar. Yapay zekayı başlatmadan hemen istemciye geri döner.
  2. Zamanlayıcının sona ermesi – Zamanlayıcı işleyicisi lease almaya çalışır. Eğer CAS başarılı olursa işleyici devam eder; aksi takdirde, başka bir işlemin zaten konuşmaya sahip olduğunu bilerek geri çekilir.
  3. Yeni girdi kontrolü – İşleyici, mevcut versiyon sayacını zamanlayıcı başladığında kaydettiği değerle karşılaştırır. Eğer sayaç ilerlemişse, bekleyen mesajları tek bir istemde birleştirir.
  4. Yanıt oluşturma – Yapay zeka modeli bir kez çalışarak tüm son kullanıcı girdilerini kapsayan tek bir yanıt üretir.
  5. Son mantık kontrolü – Yanıt gönderilmeden hemen önce, işleyici versiyon sayacını tekrar okur. Eğer oluşturma sırasında daha yeni bir mesaj geldiyse, yanıt atılır ve işlem zamanlayıcıyı yeniden başlatır; böylece kullanıcıya güncel olmayan bir yanıtın ulaşması engellenir.

Bu yaklaşım mükerrer yanıtları ortadan kaldırır, bir konuşmanın ne kadar süre bekletilebileceğine bir sınır getirir ve lease kendi kendine sona erdiği için işlem çökmelerinden otomatik olarak kurtulur.

Çıkarılacak ders

Kritik bölüm başlamadan önce yok olan bir kilit, hiçbir koruma sağlamaz. Geçici bir veritabanı kilidini, açık ve süresi dolan bir lease ile değiştirerek ve zamanlayıcıları konuşma verilerinden izole ederek, bot artık kullanıcılar ışık hızında yazsa bile tek ve güncel bir yanıt vereceğini garanti ediyor. Bu olay zamansız bir dersi vurguluyor: Eşzamanlılık korumaları, korudukları işten daha uzun süreli olmalıdır; aksi takdirde hataların sızmasına izin veren görünmez engellere dönüşürler.