AWS S3, SNS, EventBridge, DynamoDB ile Kategori Servisi

 

Category servisimizi oluşturduk. Şimdi ilk olarak serverless.yml dosyamızın içeriğini göstereceğim.

 

 

Gerekli ayarlarımı bu şekilde yaptım. Kategori görselimi yükleyeceğim için s3 yapılandırmasını, category bilgilerini dynamodb de tutacağım için de dynamodb yapılandırmamı yaptım. Detaylarına girmiyorum zaten önceki konularda söyledim. getUploadUrl dosyamda getUploadUrl fonksiyonumda aşağıdaki şekilde.

 

 

 

Kodu biraz açıklayalım. Frontend’den fileName, fileType, categoryName alır. S3’e yükleme yapabilmek için pre-signed URL oluşturur. Upload işlemi gerçekleşmeden önce yani burada upload url oluştuktan sonra dynamodb’e dosya adı, kategori adı, oluşturulma tarihini kaydeder.

Ve bu lambda işlevine s3’e ve dynamodb’e nesne yazma izni vereceğiz.

 

 

Burada resource de yer alan arn değerlerini nereden alacağımızı yine önceki konularda gördük bannerservice konusunda.

Sls deploy komutu ile deployu tamamlayıp teste geçiyorum.

 

 

 

İşlemler başarılı.

 

 

 

 

Şimdi bir tane updateCategoryImage fonksiyonu yazacağım.

 

 

Bu fonksiyonun temel görevi şu S3’e bir dosya upload edildiğinde otomatik tetiklenir ve ilgili DynamoDB kaydını günceller. Yani aslında upload edilen görselin public URL'sini al ve o görselin bağlı olduğu kaydı DynamoDB’de güncelle.

S3 event’i şu formatta gelir
{

"Records": [

{

"s3": {

"bucket": { "name": "my-bucket-name" },

"object": { "key": "example.png" }

}

}

]

}

single upload olduğundan ilk kaydı alırız. Daha sonrasında public bir url oluşturuyoruz. updateItemCommand kısmı ise kritik kısım.

Key: { fileName: { S: fileName } }

DynamoDB'deki her item'ın bir primary key (partition key)’i var. Bizim tablomuzda bu fileName.

Bu fonksiyon o item'ı bulup güncellemek için bu key’i kullanır.

UpdateExpression: "SET imageUrl = :imageUrl"

DynamoDB’nin SQL benzeri update syntax’ıdır. imageUrl kolonunun değerini değiştirir. Kolon yoksa da oluşturur.

ExpressionAttributeValues: {

":imageUrl": { S: imageUrl },

},

UpdateExpression içindeki placeholder’ların değerlerini burada veriyoruz. :imageUrl yerine gerçek string değeri geçer.

Yani kısaca tablodaki ilgili kaydın imageUrl değerini yeni yüklenen dosyanın linki ile günceller. Dosya upload edildikten sonra kayıt otomatik tamamlansın diye bu fonksiyonu yazıyoruz.

 

 

Unutmadan ilgili iznimizi de verelim

 

 

Şimdi detaylıca buradaki olayları açıklayalım. serverless.yml dosyama updateCategoryImage fonksiyonunu s3 eventi olacak şekilde yazıyorum. handlers/updateCategoryImage.js içindeki updateCategoryImage fonksiyonunu tetikler. S3'e yeni bir dosya yüklendiğinde otomatik çalışır.

Burada şu an 2 fonksiyonumuz var. getUploadUrl, updateCategoryImage. getUploadUrl, upload işlemi için ilk hazırlığı yapıyor. S3 için pre-signed URL üretiyor. Bu url’e put isteği atıp 1 saat içerisinde dosya yükleyebiliriz. Bu url’in 1 saatlik geçerliliği mevcut. Aynı zamanda DynamoDB’ye ön kayıt açıyor. Henüz imageUrl mevcut değil çünkü dosya daha upload edilmemiş oluyor. Hazırlanan url’e put isteği gönderilip upload edilmesi gerekiyor. Bu yükleme işlemi gerçekleştiği anda yani örneğin React uygulaması pre-signed uploadUrl ile dosyayı S3’e 

yüklediği zaman S3 upload’ı alır ve “ObjectCreated:Put” event’i üretir. serverless.yml’deki tanım sayesinde bu event updateCategoryImage Lambda’sını tetikler.

Yani özetle: React > getUploadUrl > pre-signed URL > S3 PUT > S3 event > updateCategoryImage

updateCategoryImage kaydı tamamlayan fonksiyon oluyor. S3 event’ten bilgi çekiyor, Dosyanın public URL’ini oluşturuyor, DynamoDB’de ilgili kaydı güncelliyor. Hani dynamodb’e getUploadUrl fonksiyonunda bir kayıt oluşturduk ya henüz upload gerçekleşmemiş olmasına rağmen işte onu güncelliyor event tetiklendiği anda. S3’ten gelen event sonrası bu fonksiyon: { imageUrl: "https://bucketname.s3.amazonaws.com/fileName" } alanını da ekleyip kaydı tamamlıyor.

Yani tamamen serverless, event-driven bir category image management mikroservisi yazmış olduk.

getUploadUrl işlemi sonrası;

 

 

PUT isteği sonrası s3 event’i tetiklendikten sonra;

 

 

imageUrl eklenmiş oldu. Işte bu senaryoya event-driven diyoruz.

Şimdi bir cleaupCategories fonksiyonu yazalım ve detaylarına bakalım.

 

 

 

Bu fonksiyonun amacı 1 saatten eski olup henüz S3’te resmi tamamlanmamış (yani imageUrl alanı olmayan) geçici / yarım kalmış kategori kayıtlarını DynamoDB’den silmek.

Kullanıcı upload başlatmış, getUploadUrl çağrılmış, DynamoDB’ye bir satır eklenmiş, Ama dosya S3’e hiç yüklenmemiş veya yükleme yarıda kalmış olabilir. Yani PUT isteği aşaması bir şekilde gerçekleşmemiş. Bu durumda tabloda çöp kayıtlar oluşuyor. cleanupCategories fonksiyonu bu çöpleri düzenli aralıklarla temizliyor.

Şimdi bu fonksiyonu EventBridge schedule (cron) ile periyodik tetiklenen bir Lambda olarak kullanacağız.

Şimdi serverless.yml dosyasına geçelim ve ilk önce silme iznini ayarlayalım.

 

 

 

Functions kısmına cleanupCategories tanımını yaptım. Yani yaptığım şey cleanupCategories isimli Lambda fonksiyonunu her 2 dakikada bir otomatik çalıştır. Bu yapıya EventBridge deniyor.

Yani her 2 dakikada bir 1 saatten eski ve tamamlanmamış kayıt var mı? diye bakıp gerekli temizlikler yapılacak. Şimdi deploy alalım ve Amazon EventBridge hizmetini kontrol edelim.

 

 

 

 

2dk olarak görebiliyoruz.

Şimdi uygulamamıza Amazon SNS’i entegre edeceğiz.

Amazon SNS Nedir?

AWS SNS (Simple Notification Service) AWS’in tamamen yönetilen pub/sub mesajlaşma ve bildirim servisidir. Bir mesajı birden fazla hedefe aynı anda ileten, yüksek ölçekli bir bildirim & mesaj dağıtım servisidir. Genel olarak 2 ana kullanım senaryosu vardır.

1- Pub/Sub (Publish–Subscribe) Mesajlaşma: Burada bir topic oluşturulur. Bir sistem topic’e mesaj yayınlar yani publish eder. Birden fazla sistem bu topic’e abone olur yani subscribe olur. Sonuç olarak bir mesaj birden fazla hedefe aynı anda gider.

2- Bildirim gönderme: Email, sms, mobil push, chatbot, http webhooks

Bizim senaryomuzda ise şu durumda kullanacağız güncel olmayan kategorilerden sonra yöneticiye bilgilendirme yapacağız. Yani bildirim göndereceğiz.

Şimdi ilk olarak serverless.yml dosyamızda SNS kaynağımızı tanımlayacağız.

 

 

Burada CategoryCleanupTopic adında bir SNS topic kaynağı oluşturdum.

Daha sonrasında ‘sls deploy’ komutunu vererek deployu tamamladım.

Şimdi ‘sns’ şeklinde aws de arayıp sns topicslere bakıyorum.

 

 

Oluşturmuş olduğum topic burada. Şimdi bu topic’e abone olalım.

 

 

‘Create subscription’ butonuna tıklıyoruz.

 

 

Protokol, bildirimleri nasıl almayı planladığımızdır. Şimdi bu tanımlamaları serverless.yml dosyamızda yapacağız. Buradaki arn bilgisini kullanacağız.

 

 

Resources altına yeni bir kaynak ekledim. CategoryCleanupTopic kaynağından sonraya ekledim. Bu kaynak ile CategoryCleanupTopic topicine email aboneliği ekliyoruz. Bu topic’e bir mesaj publish edildiğinde AWS SNS otomatik olarak bu email adresine bir bildirim gönderir. Burada abonelik türümüz email, endpoint ise hangi email’e göndereceğimizi belirtiyor. Bu ayarları yaptıktan sonra sls deploy komutu ile deploy alıp subscrition alanını kontrol ediyorum.

 

 

Aws’den bildirim maili alabilmek için izin vermemiz gerekiyor.

 

 

Bize bir mail gönderiyorlar benim spam kutuma düşmüş buradan confirm subscription diyerek kabul ediyorum.

 

 

Artık onaylı. Şimdi son olarak kategori temizleme fonksiyonumuzu SNS’i tetikleyecek şekilde yapılandıralım.

 

 

 

 

Fonksiyonda yaptığım eklemeler bu şekilde.

 

 

Serverless.yml dosyasında environment olarak sns_tpoic_arn değişkenini ekledim. Kısaca fonksiyonda DynamoDB için nasıl DynamoDBClient kullanıyorsam SNS’e mesaj publish etmek için SNSClient kullandım. snsClient.send ile SNS Topic’e gönderiliyor ve topic’e email aboneliği olan herkes’e mail gidiyor.

Yani fonksiyonun son hali şu adımlarla çalışıyor.

1- DynamoDB table içinden eski kategorileri bulur.

2- Eskileri tek tek siler

3- Kaç adet sildiğini hesaplar

4- SNS Topic'e bir mesaj gönderir

5- SNS Topic de bu mesajı email olarak iletir

Önemli olan SNS publish işleminin çalışması için Lambda fonksiyonuna yetki vermemiz lazım. IAM yetkisi eklemeliyiz.

 

 

Bu şekilde en son olarak SNS için gerekli yetkilendirmeyi tanımladım ve sls deploy komutunu çalıştırıp deploy aldım. Bu işlev artık örneğin görseli olmayan bir kategori oluşturup 1 saat içerisinde yükleme yapmadığımız taktirde o kategoriyi silip bu bilgilendirme mailini atacaktır.