MTmertturkoglu.comTüm yazılar

Cloudflare ·

wrangler deploy --strict neden değişmemiş bir config'i yıkıcı sanıyordu?

Cloudflare workers-sdk #16359: API'nin hiç göndermediği bir alan ile undefined bir alanın farkı, ve düzeltmenin neden ilk planladığım yerde kalmadığı.

wrangler deploy --strict ve wrangler versions upload --strict, yerel config ile Cloudflare'deki config arasında yıkıcı bir fark varsa yüklemeyi durdurur. #16233 numaralı issue'da Holutopson bir şey fark etti: varsayılan jurisdiction'daki bir R2 bucket'ı olan Worker'larda hiçbir şey değişmemişken bile strict mod yüklemeyi durduruyordu.

Kök neden: yok ile undefined aynı şey değil

Varsayılan jurisdiction'da API jurisdiction alanını hiç göndermiyor. Ama uzaktaki bağlamaları eşleyen mapWorkerMetadataBindings(), eşlenen nesnede yine de kendi jurisdiction: undefined özelliğini oluşturuyordu. Yerel config'te ise böyle bir özellik yok. Karşılaştırmayı yapan json-diff, { a, j: undefined } ile { a } nesnelerini farklı sayıyor ve bunu bir değişiklik olarak raporluyor. Strict mod da bu farkı yıkıcı kabul ediyordu.

Düzeltme neden ilk planladığım yerde kalmadı

Issue'ya yazdığım ilk plan basitti: eşleyiciyi düzeltip jurisdiction alanını sadece API gönderdiğinde eklemek. Koda bakınca iki şey bu planı yetersiz bıraktı:

  • Eşleyici aynı kalıbı başka isteğe bağlı alanlarda da kullanıyordu: Durable Object script_name/environment, service environment/entrypoint, workflow script_name, queue delivery_delay. Sadece R2'yi düzeltmek aynı yanlış alarmı başka bağlamalarda bırakırdı.
  • Uyuşmazlık iki yönlüydü. Yerel tarafta undefined bir alan taşıyan bir bağlama, uzakta o alanı hiç taşımayan bir bağlamayla karşılaştırıldığında da fark çıkıyordu. Eşleyiciyi düzeltmek bu yönü kapsamazdı.

Bir sonraki aday, karşılaştırmayı yapan diffJsonObjects() fonksiyonuydu. Ama bu fonksiyon @cloudflare/deploy-helpers paketinden dışarı açılan genel amaçlı bir JSON karşılaştırıcı. "Yok ile undefined aynıdır" bir Worker config kuralı, JSON'ın genel bir kuralı değil. O yüzden bu fonksiyona dokunmadım.

Düzeltme, zaten config'e özgü diğer normalizasyonları yapan getRemoteConfigDiff() içine girdi. Karşılaştırmadan hemen önce iki taraftaki undefined özellikler özyinelemeli olarak temizleniyor:

function omitUndefinedProperties<T extends JsonLike>(value: T): T {
	if (Array.isArray(value)) {
		return value.map(omitUndefinedProperties) as T;
	}
	if (value === null || typeof value !== "object") {
		return value;
	}
	return Object.fromEntries(
		Object.entries(value)
			.filter(([, fieldValue]) => fieldValue !== undefined)
			.map(([key, fieldValue]) => [key, omitUndefinedProperties(fieldValue)])
	) as T;
}

Gerçek değişiklikler hâlâ yakalanıyor. Örneğin uzakta jurisdiction: "eu" varken yerelde hiç yoksa, bu yine yıkıcı fark olarak raporlanıyor. Testler iki yönü ve bu gerçek değişiklik durumunu kapsıyor.

Sonuç

PR'ı Pete Bacon Darwin onaylayıp aynı gün birleştirdi (+94/−2, üç dosya). Benim için asıl ders, düzeltmenin nereye ait olduğuydu. En kısa yol eşleyiciyi yamamaktı; doğru yer ise kuralın ait olduğu katmandı.