Blogum Artık Yazılarını Veritabanından Okuyor — ve Hiçbir Sayfa Değişmedi

5. Günün sonunda şöyle demiştim: “Sıradaki adım, Astro’nun artık .md dosyaları yerine açık mutfaktaki gerçek veriyi okumasını sağlamak.” Bugün bunu yaptım. İşin ilginç tarafı şu: iş bittiğinde sitede gözle görülür hiçbir şey değişmemişti. Doğru yapılmış bir altyapı değişikliği zaten böyle görünüyormuş.

Önce şunu netleştirelim: “okumak” ve “yazmak” ne demek?

Bu yazı boyunca bu iki kelime çok geçecek, o yüzden en başta oturtalım.

Okumak, veritabanına “elinde ne var, bana ver” demek. Bir kütüphaneden kitap almak gibi — raftaki şey değişmiyor, sen sadece bakıyorsun.

Yazmak, veritabanına “şunu da sakla” demek. Kütüphaneye yeni bir kitap bırakmak gibi — artık rafta yeni bir şey var.

Bugüne kadar yaptığım her şey okuma yönündeydi. Bugün bir istisna var: yazılarımı dosyalardan alıp veritabanına koyarken bir kez yazma yaptım, ama bunu kullanıcı değil, ben kendi bilgisayarımdan yaptım. Sitenin ziyaretçisinin bir şey yazabilmesi (mesela yorum bırakması) hâlâ mümkün değil. O, bir sonraki adım.

Önce veri, sonra okuma

Hevesle “hadi siteyi veritabanından beslemeye geçirelim” diye başlayacaktım ki bir şey fark ettim: Neon’daki tabloda sadece bir tane deneme kaydı vardı. Gerçek yazılarımın altısı da hâlâ bilgisayarımdaki dosyalarda duruyordu.

Eğer sırayı şaşırıp önce siteyi değiştirseydim, site anında boşalırdı: altı yazının yerinde tek bir deneme kaydı görünürdü. Yani sıra şuydu: önce yazıları veritabanına taşı, sonra sitenin onları oradan almasını sağla. Basit ama atlanması da kolay.

Yazıları taşımak: ne yaptım, hangi parçalardan oluşuyor

Altı dosyayı elle veritabanına girmek mümkündü ama hem sıkıcı hem hataya açıktı. Onun yerine küçük bir program yazdırdım. Bu program şunu yapıyor: klasördeki her yazı dosyasını açıyor, içindekileri parçalarına ayırıyor, ve her parçayı veritabanındaki doğru sütuna yerleştiriyor.

Burada iki kelimeyi açmam lazım, çünkü sonra tekrar geçecekler.

Her yazı dosyasının en üstünde bir künye var. Dosyayı açtığında, asıl yazı başlamadan önce birkaç satır bilgi görüyorsun: başlık ne, kısa açıklaması ne, hangi tarihte yayınlandı. Bu bilgiler iki çizgi arasında duruyor ve asıl metinden ayrı tutuluyor. Bir dosyanın üstündeki etiket gibi düşün: klasörün içine bakmadan, dışındaki etiketten ne olduğunu anlıyorsun. Program önce bu etiketi okuyup başlığı, açıklamayı ve tarihi alıyor; sonra etiketin altındaki asıl yazı metnini alıyor.

Bir de her yazının “adres adı” var. idrishanlabs.com/blog/3-gun-ilk-api/ adresindeki 3-gun-ilk-api kısmı bu. Bu, yazının internetteki adresinde görünen kısa adı. Benim dosyalarımın adları zaten bu şekilde olduğu için, program dosya adından bu kısa adı çıkarıp aynen kullanıyor. Bu önemliydi: adres adları değişmeseydi, eski bağlantılar kırılmayacaktı — nitekim kırılmadı.

Programa bir de şunu koyduk: veritabanında aynı adres adı zaten varsa, o yazıyı atla. Böylece programı iki kere çalıştırmak hiçbir şeyi bozmuyor, aynı yazıyı iki kez eklemiyor. Altı yazının altısı da sorunsuz taşındı.

Araya giren küçük engel

Veritabanındaki eski deneme kaydını silmek istedim. Bunun için daha önce kullandığım görsel aracı açtım ama tarayıcı bir türlü bağlanamadı — Chrome’un yeni sürümleri, bilgisayarın kendi içinde çalışan programlara erişimi varsayılan olarak engelliyormuş.

Tek bir satır silmek için bununla boğuşmanın anlamı yoktu. Neon’un kendi internet sitesinde zaten bir komut penceresi var; oraya girip tek satırlık bir silme komutu yazdım, iş bitti.

Küçük ama işe yarar bir ders: bir araç, beş saniyelik bir iş için seninle güreşmeye başlıyorsa, o işi yapmanın daha doğrudan bir yolu var mı diye bak.

Bir karar: blogun veritabanı şifresi olmayacak

Burada bir seçim vardı ve bence günün en önemli kararıydı.

Site, yazıları çekerken iki yoldan birini kullanabilirdi:

Birinci yol: Site doğrudan veritabanına bağlanır, yazıları kendisi çeker. Kısa yol gibi görünüyor.

İkinci yol: Site, kendi API’mize sorar; API veritabanına gidip veriyi getirir ve siteye verir. Araya bir durak daha giriyor.

Birinci yolun bir bedeli var: veritabanının şifresini bir de blog projesinin içine koymam gerekirdi. 4. Günde o şifreyi yanlışlıkla internete sızdırdığımı hatırlayınca cevap netleşti. Bir sır, kaç yerde duruyorsa o kadar kolay sızar. Şifre tek bir yerde — API’de — kalsın; blog tarafı onu hiç görmesin. Blog sadece “bana yazıları ver” demeyi bilsin, veritabanıyla nasıl konuşulduğu onu hiç ilgilendirmesin.

Fırın benzetmesiyle: fırıncı artık malzemeyi kendi dolabından almıyor, açık mutfağın tezgahından istiyor. Deponun anahtarı hâlâ sadece mutfakta duruyor.

“Sitenin yazıları nereden aldığını değiştirmek” tam olarak ne demek?

Buraya kadar hep “okuma şeklini değiştireceğiz” dedim. Somutlaştırayım.

Sitemde, yazıları gösteren üç ayrı yer var: yazıların listelendiği sayfa, tek bir yazının açıldığı sayfa, ve birazdan anlatacağım RSS denen şey. Bu üçü de yazıları bir yerden alıp ekrana diziyor.

Ben bu işi şöyle yapacağımı sanıyordum: bu üç dosyayı tek tek açacağım, her birinin içindeki “klasördeki dosyaları oku” kısmını bulacağım, ve onu “API’ye git, oradan al” ile değiştireceğim. Yani üç yeri birden elle değiştirmek.

Ama projeyi incelediğimizde ortaya şu çıktı: bu üç sayfa aslında yazıları doğrudan dosyalardan okumuyor. Arada tek bir tanım dosyası var ve orada şöyle bir cümle yazıyor: “Yazılar şu klasörde duruyor, şu şekilde okunacak.” Üç sayfa da yazıları bu tanıma sorarak alıyor.

Yani değiştirilecek tek bir yer varmış. O cümleyi “yazılar şu internet adresinden alınacak” diye değiştirdiğimizde, üç sayfa da olanlardan habersiz çalışmaya devam etti. Çünkü onlara gelen verinin şekli aynı kaldı: yine bir başlık, bir açıklama, bir tarih, bir metin. Suyun nereden geldiği değişti, ama musluktan akan şey aynı kaldı.

Buradan çıkan kural, bence bugünün en kıymetli şeyi: verinin kaynağını değiştirmek, o veriyi kullanan her yeri tek tek değiştirmekten iyidir. Araya düzgün bir “şekil” koyduğunda, altını komple değiştirsen bile üstündekiler bunu fark etmiyor.

RSS nedir, neden önemliydi?

Yukarıda “üçüncü yer” dediğim şey RSS. Şöyle anlatayım.

Bir blogu takip etmek isteyen biri, her gün siteye girip “yeni yazı var mı” diye bakmak zorunda kalmasın diye, siteler kendi içeriklerinin bir listesini makinelerin okuyabileceği düz bir biçimde yayınlar. Takip uygulamaları bu listeyi düzenli olarak kontrol eder ve yeni bir şey varsa kullanıcıya haber verir. Bu listeye RSS deniyor. Bir derginin arka kapağındaki içindekiler sayfası gibi, ama insan için değil, program için.

Benim sitemde de böyle bir liste otomatik üretiliyormuş ve ben bunu unutmuştum. Planı yaparken aklıma hiç gelmedi. Eğer üç sayfayı elle değiştirme yolunu seçseydim, büyük ihtimalle bunu atlayacaktım — ve blogu takip edenlerin listesi sessizce bozulacaktı. Sessizce, çünkü ben siteye bakınca her şeyi normal görecektim.

Tek bir yeri değiştirmenin ikinci faydası buymuş: unuttuğun köşeler de kendiliğinden doğru yerden beslenmeye devam ediyor.

Nasıl kontrol ettim: önce fotoğrafını çek, sonra karşılaştır

Bu tür bir değişiklikte “bence çalışıyor” yetmez. Çünkü bozulduğunda gürültü çıkarmaz: bir sayfa eksilir, bir tarih kayar, sen de haftalar sonra fark edersin.

Yöntem şuydu. Site, yayına çıkmadan önce bir klasörde bütün sayfalarını hazır hale getiriyor. Ben değişikliği yapmadan önce bu klasörü bir kere oluşturup kenara kopyaladım. Bu, “değişiklikten önceki hali”nin fotoğrafı oldu.

Sonra değişikliği yaptım ve klasörü yeniden oluşturdum. Elimde iki klasör vardı: öncesi ve sonrası. Bunları karşılaştıran bir komut çalıştırdım — bu komut iki klasördeki bütün dosyaları tek tek açıp harf harf karşılaştırıyor.

Sonuç: tek bir harf bile farklı değildi. Altı sayfa, aynı adresler, aynı içerik, aynı RSS listesi.

Onbirinci hata: olmayan bir testi geçtiğimi sanmak

Burada güzel bir hata yaptım. Her şey hazırdı, değişiklik kaydedilmişti, ama henüz GitHub’a göndermemiştim. Yine de canlı siteyi açtım, yazıları gördüm ve “tamam, çalışıyor” dedim.

Oysa o an baktığım şey, günler önce yayınlanmış olan eski siteydi. Yeni kod Cloudflare’e hiç gitmemişti. Yani hiçbir şeyi test etmemiştim; sadece eskisinin hâlâ ayakta olduğunu görmüştüm.

Komik olan şu: bu tam olarak bir gün önce, 5. Günde anlattığım şeyin kendisi. Canlı site, senin bilgisayarındaki klasörün değil, en son yayınlanan halin fotoğrafıdır. Kavramı yazıya dökmüş olmam, ertesi gün aynı tuzağa düşmemi engellemedi. Bir şeyi anlatabiliyor olmak, onu refleks haline getirmiş olmak değilmiş.

En kafa karıştırıcı kısım: aslında kim kime istek atıyor?

Bu bölümü ayrı yazıyorum, çünkü kafam en çok burada karıştı. Sebebi de şu: “Cloudflare” tek bir şey değil. Benim için üç ayrı iş yapıyor ve ben bunların üçüne birden aynı ismi verdiğim için her şey birbirine giriyordu.

Cloudflare’in benim için yaptığı üç iş:

  1. Sayfaları hazırlayan geçici bilgisayar. GitHub’a yeni bir şey gönderdiğimde, Cloudflare kendi tarafında geçici bir bilgisayar açıyor ve sitemi orada hazırlıyor. İş bitince o bilgisayar kapanıyor, gidiyor.
  2. Hazır sayfaların durduğu raflar. Hazırlanan sayfalar, dünyanın dört bir yanındaki Cloudflare makinelerine dağıtılıyor ve ziyaretçilere oradan veriliyor.
  3. API’min çalıştığı yer. Benim API’m de Cloudflare üzerinde duruyor, ama bu tamamen ayrı bir şey — kendi adresi olan, ayrı bir program.

Üçü de “Cloudflare” ama birbirinden bağımsız. Şimdi akışı bu ayrımla, sırasıyla yazayım.

Ben GitHub’a gönderdiğim anda:

  1. Cloudflare yeni bir şey geldiğini fark ediyor ve geçici bir bilgisayar açıyor.
  2. O bilgisayarda sitemin hazırlanması başlıyor. Yani fırıncı işbaşı yapıyor.
  3. Fırıncının yazılara ihtiyacı var ama artık onları dosyalardan almıyor. Deponun anahtarı da onda yok. O yüzden internet üzerinden benim API’me bir istek atıyor — tıpkı sıradan bir ziyaretçi gibi: “bana yayınlanmış yazıları ver.”
  4. İsteği alan API (Cloudflare’in başka bir yerinde çalışan ayrı program) Neon’daki veritabanına gidiyor, altı yazıyı alıyor, ve geçici bilgisayara geri gönderiyor.
  5. Geçici bilgisayar eline geçen yazılarla bütün sayfaları hazırlıyor.
  6. Hazırlanan sayfalar raflara dağıtılıyor.
  7. Geçici bilgisayarın işi bitiyor ve kapanıyor.

Bundan sonra bir ziyaretçi geldiğinde:

  1. Ziyaretçi en yakın raftan hazır sayfayı alıyor. API’ye kimse istek atmıyor. Neon’a kimse gitmiyor. Hepsi çoktan olup bitti.

Yani senin sorduğun şeyin cevabı: evet, Cloudflare’in o geçici bilgisayarı benim API’me istek atıyor; API Neon’dan veriyi getirip ona veriyor; o da bu veriyle sayfaları hazırlayıp raflara koyuyor. Ama bu, ziyaretçi geldiğinde değil, ben yazı gönderdiğimde oluyor.

Fırın benzetmesiyle: sabah fırına geçici bir yardımcı giriyor, deponun anahtarı onda olmadığı için açık mutfağın tezgahından malzemeyi istiyor, mutfaktaki aşçı depoya gidip malzemeyi getiriyor, yardımcı bütün ekmekleri pişirip tezgahlara diziyor ve evine gidiyor. Gün içinde gelen müşteriler, tezgahtaki hazır ekmeği alıyor — kimse mutfağa gidip “bana taze bir şey yap” demiyor.

Fazla temiz bir sonuçtan şüphelenmek

GitHub’a gönderdikten sonra asıl test başladı. Çünkü bu sefer sayfaların hazırlanması benim bilgisayarımda değil, Cloudflare’in o geçici bilgisayarında olacaktı — ve oradan benim API’me ulaşabilmesi gerekiyordu. Yerelde çalışması bunu garanti etmiyordu.

İşlem başarıyla bitti, iki klasör birebir aynıydı. Ama tam burada durmadım, çünkü sonucun bu kadar temiz çıkması rahatsız ediciydi. Birebir aynı çıktı iki farklı şey anlamına gelebilirdi:

  • Ya geçiş kusursuz olmuştu,
  • Ya da geçiş hiç gerçekleşmemişti ve sayfalar hâlâ eski yoldan, dosyalardan üretiliyordu.

İkisi de dışarıdan tamamen aynı görünürdü. Bu yüzden Cloudflare’in işlem kayıtlarına girip şu satırı aradım:

6 yazı blog-api'den yüklendi.

Oradaydı. Bu satırı, yazıları çeken kodun içine bilerek koymuştuk. Görmem şu anlama geliyordu: kod gerçekten Cloudflare’in makinesinde çalışmış, internet üzerinden benim API’me gitmiş, altı yazıyı oradan almış. Aynı çıktının sebebi, geçişin düzgün yapılmış olmasıymış.

Ders: bir değişikliğin işe yaradığının kanıtı, sonucun “doğru görünmesi” değildir. O değişikliğin gerçekten çalıştığına dair ayrı bir iz aramak gerekir.

Dürüst olmak gerekirse, işim kısa vadede zorlaştı

Bugünden önce yeni yazı eklemek şuydu: dosyayı yaz, GitHub’a gönder.

Bugünden sonra: dosyayı yaz, taşıma programını çalıştır (yazı veritabanına girsin), sonra GitHub’a gönder. Yani bir adım fazla.

Bunu saklamanın anlamı yok — bu adım bana konfor getirmedi, temel attı. İçeriğim artık bir dosyanın içinde değil, sorgulanabilir bir veritabanında duruyor. Yorum, beğeni, okunma sayısı, ileride yazı yazmak için düzgün bir arayüz: bunların hiçbiri dosyalarla yapılamaz, hepsi bu temeli gerektirir. Bugün ödediğim fatura, yarın açılacak kapıların bedeli.

İki şeyi bilerek yapmadım

Eski dosyaları silmedim. Silmek cazip geliyor, çünkü site artık onları okumuyor. Ama o dosyalar hâlâ yazı yazdığım yer. Silersem yeni yazı yazmanın tek yolu veritabanına elle kayıt girmek olur — yani rahat rahat metin yazmak yerine, veritabanı komutlarıyla uğraşmak. Bu dosyalar ancak yazı yazmak için düzgün bir arayüz yaptığımda gereksizleşir; ondan önce değil.

Site hâlâ “önceden hazırlanmış” çalışıyor. Veritabanına yeni bir yazı eklemek siteyi kendiliğinden güncellemiyor; sayfaların yeniden hazırlanması gerekiyor. Şu an bu benim için sorun değil, çünkü zaten her yazıdan sonra gönderim yapıyorum. Ama ileride çözülmesi gereken bir konu olarak duruyor.

Hata verip durmak, sessizce yanlış çalışmaktan iyidir

Yazıları API’den çeken koda bilerek şöyle bir davranış koyduk: API’ye ulaşılamazsa, sayfa hazırlama işlemi hata verip durur. Yazıları atlayıp devam etmez.

İlk bakışta “hata vermesi” kötü gibi duruyor. Ama alternatifini düşün: API o an erişilemez olsa ve kod bunu görmezden gelip devam etse, bomboş bir site hazırlanır ve sessizce yayına girerdi. Ben de bunu günler sonra, tesadüfen fark ederdim.

Sessizce yanlış çalışan bir sistem, gürültüyle duran bir sistemden her zaman kötüdür. Duran sistem seni uyarır; sessiz olan seni kandırır.

Sırada ne var?

Şimdiye kadar yaptığım her şey tek yönlüydü: veritabanından al, sayfaya koy. Hep alma yönünde.

Sıradaki adım ters yöne gitmek: veritabanına koymak. Yani siteye gelen birinin yazdığı bir şeyi (örneğin bir yorumu) alıp veritabanına kaydetmek.

Bu, göründüğünden daha büyük bir adım. Çünkü okurken en kötü ihtimalle yanlış bir şey gösterirsin; yazarken ise başkasının gönderdiği veriyi kendi veritabanına alıyorsun. Gelen şeyin gerçekten beklediğin şey olup olmadığını kontrol etmek, kötü niyetli birinin gönderdiği bir şeyin zarar vermesini engellemek gerekiyor. Yani yazma tarafı, okuma tarafından daha dikkat ister.

Bir sonraki yazıda bunu kuracağız.

Yorumlar