İş verisini doğrulama
Deserialization ile iş kurallarını ayırın ve kalıcı/geçici hatayı açıkça sınıflandırın.
Json<T> mesajın JSON yapısını Rust tipine dönüştürür. Sipariş tutarının pozitif olması, kimliğin boş olmaması veya hesabın işleme açık olması gibi kurallar ayrıca yazılır. Doğru error sınıfı, düzeltilemeyecek bir mesajın gereksiz retry döngüsüne girmesini önler.
Decode ile business validation farkı#
| Durum | Kontrol sahibi | Tipik sonuç |
|---|---|---|
| Geçersiz envelope/version/content | Framework contract seçimi | Handler öncesi permanent ret |
| Bozuk JSON veya yanlış alan türü | Json<T> ve Serde |
Permanent decode hatası |
| Boş kimlik veya geçersiz tutar | Uygulama doğrulaması | Açık permanent hata |
| Geçici veritabanı/service arızası | Uygulama hata dönüşümü | Uygun durumda retryable hata |
| İşleme yetkisi olmayan aktör | Uygulama guard/policy'si | Politikanın açık ret kararı |
Framework hata mesajının içeriğine bakıp business retry kararı tahmin etmez. Deserialize yalnız bildirilen veri biçimini doğrular. Consumer handler'ına HTTP'ye ait validation extractor'ını veya tanımlanmamış bir #[validate] marker'ını taşımayın; ortak validator'ınızı normal Rust fonksiyonu/servisi olarak çağırın.
Saf bir doğrulama fonksiyonu yazın#
use lilyrs::queue::QueueHandlerError;
use serde::Deserialize;
#[derive(Deserialize)]
struct OrderInput {
order_id: String,
amount_minor: i64,
}
fn validate_order(input: &OrderInput) -> Result<(), QueueHandlerError> {
if input.order_id.trim().is_empty() {
return Err(QueueHandlerError::permanent("ORDER_ID_REQUIRED"));
}
if input.amount_minor <= 0 {
return Err(QueueHandlerError::permanent("ORDER_AMOUNT_INVALID"));
}
Ok(())
}Fonksiyon I/O yapmaz; bu yüzden broker kurmadan birim test edilebilir. Hata code'ları sınırlı ve sabittir; raw payload, credential veya hassas iş verisini code'a gömmeyin. Aynı validator başka bir transport tarafından da çağrılabilir.
Handler içinde kullanın#
İlk worker'ın method'unu aşağıdakiyle değiştirin ve yukarıdaki OrderInput ile validate_order tanımlarını aynı modüle ekleyin. queue, Json ve QueueHandlerError import'ları ilk uygulamadaki gibidir:
#[queue("orders.created", version = 1, content = "json")]
async fn created(&self, Json(event): Json<OrderInput>) -> Result<(), QueueHandlerError> {
validate_order(&event)?;
println!("{}:{}", event.order_id, event.amount_minor);
Ok(())
}Bu örnek payload'a amount_minor alanı ekler. Publisher'ın serde_json::json! çağrısında aşağıdaki gövdeyi gönderin; ilk publisher'ın yalnız order_id içeren gövdesi bu Rust tipi için yeterli değildir:
{"order_id":"order-42","amount_minor":1250}Kalıcı ret, broker'daki mesajı uygulamanın elle ACK etmesi anlamına gelmez. Lily hata sınıfını retry/dead-letter ve settlement politikasına taşır. İlk business effect'ten önce gerekli doğrulamaları bitirmek kısmi yan etki riskini azaltır.
Dış servis kontrollerini açık yönetin#
Hesabın aktifliğini DB'den okumak gibi I/O gerektiren kontrolleri Scoped servis içinde tutabilirsiniz. Geçici bağlantı hatasını retryable_with_source ile çevirmek uygundur; “hesap kapalı” gibi doğrulanmış bir business sonucunun sınıfını iş politikanız belirler. Bütün DB hatalarını körlemesine permanent yapmak veri kaybına, hepsini retryable yapmak kalıcı hataların tekrarlanmasına yol açabilir.
Payload doğrulamak authentication sağlamaz. Mesaj içindeki bir user_id veya header değeri tek başına doğrulanmış aktör değildir. Kimlik doğrulama sonucunu typed local state ile taşımak ve yetkiyi handler öncesinde denetlemek için guard ve delivery-local state bölümlerine geçin.
Bu sayfanın kaynakları v0.1.0
Anlatım, incelenen framework commit’ine dayanır.