Asenkron ve Generic Veri İşleme Pipeline’ı
Asenkron programlama, yapıların performansı ve request-reply yapılarda yanıt verme süresini kısaltmak için önemli bir yaklaşım. C# dilindeki IAsyncEnumerable akış ile edindiğimiz, stream edilebilen veya asenkron olarak elde ettiğimiz verilerin, veri kaynaklarından gelen verileri anlık, performanslı ve verimli bir şekilde işlemeyi mümkün kılar ve yapıların sistem kaynakları daha etkin kullanılabilir.
IAsyncEnumerable Nedir?
Verileri asenkron olarak edinmemizi sağlayan, veri akışının asenkron bir şekilde sağlanabildiği yapıları temsil eden bir interface.
IEnumerable ile aralarindakı en temel fark, IEnumerable verilerin tümünün belleğe yüklenmesini bekleyip sıralı bir şekilde işleyebilirken, IAsyncEnumerable ile verilerin asenkron olarak akış halde gelmesine izin verilir ve tüm verilerin gelmesini beklemek yerine iterasyon kaynağından her bir veri geldikçe işlenebilir. Burada es geçilmemesi gereken nokta kaynağın verileri asenkron olarak verebiliyor olması.
Neden IAsyncEnumerable Kullanılır?
Temelde asenkron iterasyon ile diğer işlemleri engellemeden uzun süren veri işleme işlemlerini yapabilmek ve veritabanı, dosya okuma/yazma veya network I/O işlemleri için IAsyncEnumerable’ı tercih ediyoruz.
Verileri İşleme Pipeline’ı
Pipeline ile büyük ve karmaşık veri işleme görevlerini daha küçük ve yönetilebilir adımlara bölerek akış tabanlı veri işlemenin etkisini artırabiliriz. Aşağıda verilecek kod örneklerinde görebileceğiniz gibi her bir işlemin(sayıların çarpılması, toplanması, metne dönüştürülmesi) bağımsız ve asenkron olarak çalışarak modülerlik, esneklik ve yeniden kullanılabilirlik sağlar, bu da hem performansı yükseltir hem de bakım sürecini, geliştirici tecrübesini iyileştirir ve geliştirme süreçlerini kolaylaştırır.
Implementasyon
Asenkron olarak işlenecek veriler için bir pipeline oluşturacağız. Pipeline’ımız için veri işleme adımlarına ihtiyacımız var. Bunu bir interface ile tanımladık, somut tanımlamalarımız bu soyutluğu baz alacak.
Pipelinimiz ise işlem adımlarını bu interface tanımı üzerinden nasıl olduğunu bilecek. Metot adları oldukça açık, bir pipeline oluşturmak için Create, Pipeline’a işlem adımı eklemek için AddStep ve Pipeline’ı işletmek için ExecuteAsync metodunu kullanacağız.
AddStep aslında herhangi bir yere ekleme yapmıyor, kendisinden önce gelen veya kendisinden sonra gelecek metot çağrılarının zincirlenmesini sağlıyor.
Veri işleme adımları
Yukarıda vurguladığım gibi bütün veri işleme adımları birbirlerinden bağımsız bir şekilde somut halleri IAsyncPipelineStep’ten türetilerek tanımlandı ve hepsi kendi görevi için asenkron olarak çalışabilecek.
Implementasyonun kullanımı
Aşağıda gördüğünüz kullanım ile iki veri işleme pipeline’ı asenkron olarak başlatılarak ikisinin de işlemlerinin bitmesi beklenen bir yaklaşım ile örneklendirildi.
Bu programı her çalıştırdığımızda verilerin genelde farklı sıralarda ekrana yazıldığını göreceksiniz, hatta text processing sonradan başlatılmasına rağmen number processing çıktılarının arasına giriş yapabilecek. Temeldeki amacımız zaten buydu, uzun veri işlemelerin birbirlerini veya sonrasında yapılacak işlemleri etkilememesini sağlamak ve verimli bir çalışma yapısı ortaya koymak.
IAsyncEnumerable ile modüler hale getirmeye çalıştığım veri işleme yapısı, performans ve verimliliği artırmak için uyguladığım yaklaşımlar. Asenkron programlama ile uzun süren işlemleri diğer işlemleri engellemeden gerçekleştirebilir, pipeline yaklaşımı ile karmaşık veri işleme görevlerini daha yönetilebilir parçalara bölebilirsiniz. Bu yaklaşımlar, sistem kaynaklarının daha etkin kullanılmasını sağlar ve geliştirici deneyimini iyileştirir.