deniz.in

Piyasalar

Hava durumu

Hava durumu yükleniyor

· kaynak dev.to (home feed)

Tek kelimelik bir IMAP hatası, 9.133 Gmail mesajını sessizce okundu olarak işaretledi

Bir geliştiricinin mail botu, 9.143 Gmail mesajından 9.133'ünü okundu olarak işaretledi; çünkü IMAP fetch işlemi tasarım gereği \Seen bayrağını ayarlıyor — ve bu yan etkiyi düzeltmek, ona bağımlı olan poller'ı bozdu.

Tek kelimelik bir IMAP hatası, 9.133 Gmail mesajını sessizce okundu olarak işaretledi

Postayı fazla iyi okuyan bir bot

Kişisel bir otomasyon botu, aylarca sahibinin Gmail gelen kutusundaki neredeyse her mesajı, her biri geldikten birkaç saniye sonra okundu olarak işaretledi; ta ki fark edilene kadar. dev.to'da yayınlanan bir postmortem'e göre sorun, yazarın etkili bir şekilde kendisine açtığı bir şikayet olarak ortaya çıktı: e-posta bozuk görünüyordu ve filtreleme yanlış görünüyordu. Filtreleme gayet iyiydi. Gerçekte yaşanan şey, gelen kutusundaki 9.143 mesajdan 9.133'ünün bir mail botu tarafından okundu olarak işaretlenmesiydi.

Adapter, gelen kutusunu her 15 saniyede bir yokluyor ve her yeni mesajı IMAP'ın RFC822 fetch öğesini kullanarak çekiyordu. Postmortem'de açıklandığı gibi, IMAP spesifikasyonu olan RFC 3501, bu fetch'i bayrak yazımını yan etki olarak yapacak şekilde tanımlıyor. Gövdenin tamamını almak okumak sayılıyor ve sunucu bunu kaydediyor. Hiçbir şey arızalı değildi — protokol tam yazıldığı gibi davranıyordu.

Düzeltmeden önce yazar toplam 9.143 mesaj ölçtü: 9.133'ü seen olarak işaretli, 10'u görülmemiş ve en yeni 30 mesajın 29'u zaten okunmuştu. Onarım tek bir token'dan ibaret: bunun yerine BODY.PEEK[] isteyin; bu, bayrak yazımı olmadan aynı baytları döndürür.

Filtrenin suçu üstlenmesi

Yazar, yanlış yönlendirmeyi bayrağın kendisinden daha ilginç buluyor. Adapter'da çalışan bir gönderici allowlist'i vardı, ayrıca List-Unsubscribe, Precedence: bulk ve Auto-Submitted gibi başlıklara dayalı otomatik posta filtreleri vardı — hepsi doğru çalışıyordu. Ancak filtreleme, fetch'ten sonra, dispatch anında çalışıyordu. Botun hiçbir ilgisi olmasını istemediği bir mesaj için sıra şöyleydi: onu fetch et (bu \Seen ayarlardı); göndericinin izinli olmadığına karar ver; at. Sistemin bilerek görmezden geldiği postalar bile okundu olarak işaretleniyordu.

Neredeyse her şey fetch'ten geçtiği için, daha sıkı filtreleme daha fazla sessiz hasar anlamına geliyordu. Ve görünür belirti — yazarın önem verdiği postaların okunmuş halde gelmesi — filtreleme yapılandırmasına, yani doğru çalışan tek alt sistemi işaret ediyordu. Yazarın çıkardığı genel ders: bir belirti bir bileşeni gösterdiğinde, o bileşenin yan etkileri olan bir şeyin aşağı akışında olup olmadığını kontrol edin. Okuma yolları denetlenmez, çünkü okumanın yazması beklenmez.

İkinci hata düzeltmeyle birlikte geliyor

Tek başına BODY.PEEK[]'e geçmek yeni bir arıza getiriyor. Poller, yeni mesajları UNSEEN arayarak buluyordu — bu düzen yalnızca eski fetch'in dokunduğu her şeye \Seen ayarlaması sayesinde çalışıyordu. Yan etkiyi kaldırınca UNSEEN "henüz işlenmemiş" anlamını yitiriyor ve "insan tarafından okunmamış" anlamaya başlıyor; poller her 15 saniyede bir kalıcı olarak büyüyen bir birikmişi yeniden fetch etmeye devam ediyor.

Yerine geçen çözüm açık bir UID high-water mark: işlenen en yüksek UID'yi izleyin ve UID max+1:* sonrasını arayın. Yazar burada iki ayrıntıda takıldı. Birincisi, UID n:* her zaman en az bir sonuç döndürür — IMAP, daha yeni bir şey olmasa bile posta kutusunun en yüksek UID'sini geri verir — dolayısıyla kodun saklanan maksimumla kendi karşılaştırması gerçek filtredir. İkincisi, işaret, başlangıçta mevcut posta kutusundan tohumlanmalıdır; yoksa bir yeniden başlatma her şeyi yeniden teslim eder; önceki _seen_uids kümesi bu amaçla kullanılamazdı çünkü 2.000 girişle sınırlıydı ve zamanla budanıyordu.

Diff'e göre değil, etkiye göre doğrulayın

Yazar, kod doğru göründüğü için hatayı düzeltilmiş ilan etmedi. Doğrulama prosedürü: posta kutusunu read-only modunda seçin ki watcher ölçtüğü şeyi kirletmesin; ALL ve UNSEEN aramaları için sayıların anlık görüntüsünü alın; mesaj sayısı artana kadar poll edin; ardından yeni UID'nin hâlâ unseen olduğunu iddia edin. Yeni bir mesaj geldi ve okunmamış kaldı. Postmortem, değecek tek kanıtın bu olduğunu savunuyor; çünkü bir yan etkinin yokluğunu, ona neden olan kodu yeniden okuyarak kanıtlayamazsınız.

Neden önemli

Paylaşılan duruma dokunan otomasyonların çoğu, sessizce yazan okumalar içerir ve IMAP'ın \Seen bayrağı ders kitabı örneğidir. Önemsediği bir posta kutusuna bot yönelten herkes, RFC822 mi yoksa BODY.PEEK[] mi fetch ettiğini kontrol etmeli ve fetch'ten önce fetch'ten sonraya değil filtreleme yapmalıdır; çünkü fetch'in aşağı akışındaki her şey yan etkileri önlemek için çok geçtir. Hikâye ayrıca aktarılabilir iki hata ayıklama kuralını örnekliyor: bir yan etkiyi kaldırmak, ona sessizce bağımlı olan ne varsa bozar, o yüzden başka neyin o durumu okuduğunu sorun; ve düzeltmeleri diff'in okunuşuna göre değil, gözlemlenen davranışla kanıtlayın. Benzer şekilde yanlış teşhis edilmiş homelab arızalarını belgeleyen yazar, hata ayıklamanın ilk bölümünü belirtinin adını andığı bileşene — yani baştan sona kusursuz çalışan bileşene — harcadı.

  • #imap
  • #email
  • #debugging
  • #gmail
  • #postmortem

İlgili yazılar