AWS S3, SNS, EventBridge, DynamoDB ile Ürün Servisi

productService’imi bu şekilde oluşturarak başlıyorum.
Şimdi projeyi vscode’da açıp ürünleri ve görsellerini depolamak için s3 ve DynamoDB kaynaklarını yazalım.

ProductImagesBucket ve ProductTable kaynaklarımı yazdım zaten bunların detayını category ve banner servislerimizde de görmüştük. Burada tek fark atribiuteName bilgisini id olarak değiştirdim ve bunu KeySchema ile primary key olarak tanımladım.
Şimdi diğer servislerde yaptığımız gibi gerekli fonksiyonları yazmaya başlayalım.

Öncelikle yml da gerekli environmentlarımı tanımladım. Sonrasında getUploadUrl fonksiyonunu yazdım.



Kodun zaten çok büyük bir bölümünü diğer servislerde de yazdık. Genel olarak ürün oluşturma + resim yükleme için presigned URL üretme + ürünü DynamoDB’ye kaydetme işlemlerini yapıyor.
Burada sadece product şeması daha geniş. Şu bilgileri ürün tablosuna ekliyoruz.
-
fileName: S3’e yüklenecek dosyanın adı
-
fileType: MIME type
-
productName: Ürün adı
-
productPrice: Fiyat
-
description: Açıklama
-
quantity: Stok adedi
-
category: Kategori ismi/id’si
-
email: Ürünü ekleyen kullanıcının email’i
Tüm bu alanları da zorunlu olarak tutuyoruz bir if bloğu ile validation’ı sağlıyoruz.
Burada ek olarak ürün datasında isApproved değeri tutuyoruz boolean bir değer ve ürünün onaylı olup olmadığını saklıyor.
Özetlemek gerekirse;
-
Formdan gelen ürün bilgisini validate ediyor
-
S3’e ürün görseli yükleyebilmek için presigned URL üretiyor
-
Ürünü DynamoDB’ye kaydediyor (başlangıçta isApproved = false)
-
Frontend’e sadece uploadUrl dönüyor
S3’e upload tamamlanınca bu ürünün imageUrl alanını güncelleyen S3 event tetikli Lambdayı da birazdan yazacağız.
Ancak ondan önce api gateway routeumuzu tanımlayalım getUploadUrl için.


Şimdi test edelim. Ama öncesinde serverless.yml da DynamoDB’e yazma izni vermeliyiz.

iamRoleStatements da gerekli izni tanımladım. Resource arn değerini dynamodb hizmetinde ilgili tabloya tıklayarak detayından öğrenebiliriz.

Test sonucu başarılı yükleme url’ini elde ettik.

Data da eklenmiş. Şimdi bu yükleme url’ini kullanıp s3 ile dosya yükleyebilmek için yine gerekli izni vermemiz gerekiyor.


Arn bilgisini de s3 bucketlardan product bucketını seçerek elde edebiliriz.


Şimdi sırada upload işlemini tetikleyecek fonksiyonu yazmak var ama öncesinde gerekli izinleri serverless da yazıyorum. UpdateItem ile dynamodb’e kayıt güncelleme izni veriyorum Scan ile de tüm ürünleri tarama izni veriyorum. DeleteItem ile de ürünleri silme izni veriyorum.



Bu fonksiyon ürün resmi S3’e yüklendikten sonra otomatik olarak DynamoDB’ye ekleyen bir Lambda fonksiyonudur. Bu fonksiyon S3 event trigger ile tetiklenir. Yani bir kullanıcı ürün resmini S3’e yüklediğinde Lambda otomatik çalışır. Bunu bir önceki servisimizde de yapmıştık.

Serverless.yml da gerekli event tanımını yaptım. Bu şekilde s3 yükleme işlemi sonrası trigger olarak fonksiyonumuz çalışacak.
Şimdi bir başka lambda fonksiyonu yazacağım ve yapacağı iş her iki dakikada bir herhangi bir ürün eklenip eklenmediğini kontrol etmek olacak. Görsel URL’İ olmadan bir saate kadar süren ürün olup olmadığına bakacak ve o ürünleri ortadan kaldıracak. Ayrıca görsel url’i olmayan bir ürün varsa yöneticiye SNS bildirimi göndereceğiz.
Şimdi ilk olarak bir SNS topic oluşturalım.

productCleanupTopic tanımladım. Şimdi deploy ediyorum.

Şimdi bu konuya abone olmamız gerekiyor. Bunun içinde ilgili subscription kaynağını tanımladım.

Sls deploy diyorum.

Product topic için email adresim onay aşamasında görünüyor. Mail adresime gelen onay bağlantısına tıkladıktan sonra mailim onaylanıyor.

Şimdi temizleme fonksiyonumuzu yazalım.

Öncelikle SNS_TOPIC_ARN environment değişkenimi ekledim fonksiyonda kullanacağım.

Yazdığım fonksiyonu eventbridge olarak 2dk da bir çalışacak şekilde tanımladım. Bunların hepsini detaylıca kategori servisinde görmüştük.


Bu sebeple tekrardan detaylıca aynı şeyleri anlatmıyorum. Unutmadan SNS içinde gerekli yetkilendirmeyi yazalım.

Sns:Publish yetkisini mutlaka vermemiz gerekiyor.
Şimdi şunu yapalım /upload-url rotasını oturum açmış kullanıcılar erişecek şekilde yetkilendirelim.

Yeni bir provider ekliyorum httpApi olarak. Bu sayede API Gateway HTTP API’mize Cognito JWT doğrulaması ekledik. identitySource kısmında belirttiğimiz gibi apiye gelen isteklerde Authorization headerı gönderilmek zorunda. Token’daki aud (client_id) ile buradaki audience uyuşacak. Token’ın iss (issuer) değeri issuerUrl ile uyuşacak.
issuerUrl değerini almak için aws konsol da cognito hizmetine gidip user poolumuzdan alabiliriz.

Buradaki token signing key url kısmı issuerUrl oluyor. Ancak tanımlarken url’in tamamını yazmadım yazdığım formata dikkat.
ClientId bilgisi ise app clients menüsü altında erişilebilir.

Şimdi uploadUrl rotasını kısıtlayalım.

Şimdi test edelim.

Authorization değerini header’da göndermediğim için authorization fırlattı.
Şimdi yapmamız gereken authService’i kullanarak oturum açmak.

Sls info komutu ile authService üzerinde routeları görüyorum.

Dönen response’da idToken değerini kopyalıyoruz.

Authorization değeri olarak bearer token formatında gönderiyorum ve başarılı yanıt alıyorum.
Şimdi ise yeni bir fonksiyon yazacağım ve yapacağı iş tüm onaylı ürünleri almak olacak.

Kodu açıklarsak basitçe tabloyu tarıyor ve isApproved = true olan ürünleri filtreliyor.

Route’umuzu tanımladık.

Deploy da tamam.


Kaydı true yaptım ve tekrar bakalım.

Artık onaylı ürünlerimizi listeleyebiliyoruz.