{"id":38848,"date":"2026-02-08T22:40:54","date_gmt":"2026-02-08T19:40:54","guid":{"rendered":"https:\/\/fatihsoysal.com\/blog\/?p=38848"},"modified":"2026-02-08T22:40:54","modified_gmt":"2026-02-08T19:40:54","slug":"12-days-of-digitalocean-day-5-gunluk-tetikleyicilerle-dogum-gunu-hatirlaticilarini-otomatiklestirme","status":"publish","type":"post","link":"https:\/\/fatihsoysal.com\/blog\/12-days-of-digitalocean-day-5-gunluk-tetikleyicilerle-dogum-gunu-hatirlaticilarini-otomatiklestirme\/","title":{"rendered":"12 Days of DigitalOcean (Day 5) &#8211; G\u00fcnl\u00fck Tetikleyicilerle Do\u011fum G\u00fcn\u00fc Hat\u0131rlat\u0131c\u0131lar\u0131n\u0131 Otomatikle\u015ftirme"},"content":{"rendered":"<p><body><\/p>\n<h2>12 Days of DigitalOcean (Day 5) &#8211; G\u00fcnl\u00fck Tetikleyicilerle Do\u011fum G\u00fcn\u00fc Hat\u0131rlat\u0131c\u0131lar\u0131n\u0131 Otomatikle\u015ftirme<\/h2>\n<h2>Giri\u015f: Unutulan Do\u011fum G\u00fcnlerine Son!<\/h2>\n<p>G\u00fcn\u00fcm\u00fcz\u00fcn h\u0131zl\u0131 tempolu d\u00fcnyas\u0131nda, ki\u015fisel ve profesyonel hayatlar\u0131m\u0131zda bir\u00e7ok detay\u0131 ak\u0131lda tutmak zorla\u015fabiliyor. \u00d6zellikle sevdiklerimizin veya i\u015f arkada\u015flar\u0131m\u0131z\u0131n \u00f6zel g\u00fcnlerini, \u00f6rne\u011fin do\u011fum g\u00fcnlerini unutmak, istenmeyen durumlara yol a\u00e7abilir. Bir do\u011fum g\u00fcn\u00fcn\u00fc ka\u00e7\u0131rmak, sadece k\u00fc\u00e7\u00fck bir utan\u00e7 kayna\u011f\u0131 olmakla kalmaz, ayn\u0131 zamanda ili\u015fkilerdeki de\u011feri ve \u00f6zeni de sorgulatabilir. Neyse ki, teknoloji sayesinde bu t\u00fcr unutkanl\u0131klar\u0131n \u00f6n\u00fcne ge\u00e7mek, hatta bu s\u00fcreci tamamen otomatikle\u015ftirmek m\u00fcmk\u00fcn. DigitalOcean&#8217;\u0131n g\u00fc\u00e7l\u00fc ve esnek bulut hizmetleri, bu t\u00fcr otomasyon g\u00f6revleri i\u00e7in m\u00fckemmel bir platform sunar.<\/p>\n<p>&#8220;12 Days of DigitalOcean&#8221; serisinin be\u015finci g\u00fcn\u00fcnde, g\u00fcnl\u00fck tetikleyiciler kullanarak do\u011fum g\u00fcn\u00fc hat\u0131rlat\u0131c\u0131lar\u0131n\u0131 nas\u0131l otomatikle\u015ftirebilece\u011fimizi derinlemesine inceleyece\u011fiz. Bu makalede, DigitalOcean Functions (Sunucusuz Fonksiyonlar), Managed Databases (Y\u00f6netilen Veritabanlar\u0131) gibi hizmetleri kullanarak, her g\u00fcn belirli bir saatte \u00e7al\u0131\u015facak, yakla\u015fan do\u011fum g\u00fcnlerini tespit edecek ve bize otomatik olarak bildirim g\u00f6nderecek bir sistemin nas\u0131l kurulaca\u011f\u0131n\u0131 ad\u0131m ad\u0131m ele alaca\u011f\u0131z. Amac\u0131m\u0131z, hem teknik bilgi birikiminizi art\u0131rmak hem de hayat\u0131n\u0131z\u0131 kolayla\u015ft\u0131racak pratik bir \u00e7\u00f6z\u00fcm sunmakt\u0131r.<\/p>\n<h2>Neden Otomatik Do\u011fum G\u00fcn\u00fc Hat\u0131rlat\u0131c\u0131lar\u0131?<\/h2>\n<p>Otomatik do\u011fum g\u00fcn\u00fc hat\u0131rlat\u0131c\u0131lar\u0131 kurman\u0131n ard\u0131nda yatan nedenler olduk\u00e7a \u00e7e\u015fitlidir ve hem ki\u015fisel hem de profesyonel ya\u015famda \u00f6nemli faydalar sunar:<\/p>\n<p>*   <strong>Ki\u015fisel \u0130li\u015fkileri G\u00fc\u00e7lendirme:<\/strong> Do\u011fum g\u00fcn\u00fcn\u00fc hat\u0131rlamak ve kutlamak, birine de\u011fer verdi\u011finizi g\u00f6stermenin en basit yollar\u0131ndan biridir. Otomatik hat\u0131rlat\u0131c\u0131lar sayesinde, sevdiklerinizin \u00f6zel g\u00fcnlerini asla unutmaz, onlara zaman\u0131nda ve i\u00e7ten bir \u015fekilde kutlama mesaj\u0131 g\u00f6ndererek ili\u015fkilerinizi daha da g\u00fc\u00e7lendirirsiniz.<br \/>\n*   <strong>Stres ve Unutkanl\u0131\u011f\u0131 Azaltma:<\/strong> Do\u011fum g\u00fcnlerini takip etmek i\u00e7in s\u00fcrekli ajanda kontrol etmek veya zihinsel notlar tutmak stresli olabilir. Otomatik bir sistem, bu y\u00fck\u00fc \u00fczerinizden al\u0131r ve \u00f6nemli g\u00fcnleri ka\u00e7\u0131rma endi\u015fesini ortadan kald\u0131r\u0131r.<br \/>\n*   <strong>Zaman Tasarrufu:<\/strong> Manuel olarak do\u011fum g\u00fcn\u00fc listelerini y\u00f6netmek ve kontrol etmek zaman al\u0131c\u0131d\u0131r. Otomatik sistem, bu s\u00fcreci tamamen s\u0131f\u0131ra indirerek size daha \u00f6nemli i\u015flere odaklanma imkan\u0131 tan\u0131r.<br \/>\n*   <strong>Profesyonel Ba\u011flamda Kullan\u0131m:<\/strong> M\u00fc\u015fteri ili\u015fkileri y\u00f6netimi (CRM) sistemlerinde oldu\u011fu gibi, bu t\u00fcr bir otomasyonu i\u015f hayat\u0131na da uyarlayabilirsiniz. \u00d6rne\u011fin, m\u00fc\u015fterilerinizin do\u011fum g\u00fcnlerini kutlayarak onlarla daha ki\u015fisel bir ba\u011f kurabilir, sadakatlerini art\u0131rabilir veya \u00f6zel indirimler sunabilirsiniz.<br \/>\n*   <strong>\u00d6l\u00e7eklenebilirlik ve G\u00fcvenilirlik:<\/strong> DigitalOcean gibi bulut platformlar\u0131 \u00fczerinde kurulan sistemler, y\u00fcksek \u00f6l\u00e7eklenebilirlik ve g\u00fcvenilirlik sunar. \u0130ster 10 ister 1000 ki\u015finin do\u011fum g\u00fcn\u00fcn\u00fc takip ediyor olun, sistem sorunsuz bir \u015fekilde \u00e7al\u0131\u015fmaya devam eder.<\/p>\n<p>Bu faydalar g\u00f6z \u00f6n\u00fcne al\u0131nd\u0131\u011f\u0131nda, otomatik do\u011fum g\u00fcn\u00fc hat\u0131rlat\u0131c\u0131lar\u0131n\u0131n sadece bir &#8220;kolayl\u0131k&#8221; olmaktan \u00f6te, hayat kalitesini art\u0131ran \u00f6nemli bir ara\u00e7 oldu\u011funu s\u00f6yleyebiliriz.<\/p>\n<h2>Temel Bile\u015fenler ve Mimari Yakla\u015f\u0131m<\/h2>\n<p>Otomatik do\u011fum g\u00fcn\u00fc hat\u0131rlat\u0131c\u0131 sistemimizi kurarken, DigitalOcean&#8217;\u0131n sundu\u011fu \u00e7e\u015fitli hizmetleri ve baz\u0131 \u00fc\u00e7\u00fcnc\u00fc taraf entegrasyonlar\u0131n\u0131 kullanaca\u011f\u0131z. \u0130\u015fte sistemin temel bile\u015fenleri ve mimari yakla\u015f\u0131m\u0131m\u0131z:<\/p>\n<h3>Sistem Genel Bak\u0131\u015f\u0131<\/h3>\n<p>Basit\u00e7e ifade etmek gerekirse, sistemimiz \u015fu ad\u0131mlar\u0131 takip edecektir:<br \/>\n1.  <strong>Veri Depolama:<\/strong> T\u00fcm do\u011fum g\u00fcn\u00fc bilgileri g\u00fcvenli bir veritaban\u0131nda saklanacak.<br \/>\n2.  <strong>Zamanlanm\u0131\u015f Tetikleyici:<\/strong> Her g\u00fcn belirli bir saatte bir fonksiyon otomatik olarak \u00e7al\u0131\u015ft\u0131r\u0131lacak.<br \/>\n3.  <strong>\u0130\u015f Mant\u0131\u011f\u0131:<\/strong> \u00c7al\u0131\u015fan fonksiyon, veritaban\u0131n\u0131 sorgulayarak yakla\u015fan do\u011fum g\u00fcnlerini tespit edecek.<br \/>\n4.  <strong>Bildirim:<\/strong> Tespit edilen do\u011fum g\u00fcnleri i\u00e7in \u00f6nceden belirlenmi\u015f bir kanal (e-posta, SMS vb.) arac\u0131l\u0131\u011f\u0131yla bildirim g\u00f6nderilecek.<\/p>\n<h3>DigitalOcean&#8217;\u0131n Sundu\u011fu Hizmetler<\/h3>\n<p>*   <strong>DigitalOcean Functions (Sunucusuz Fonksiyonlar):<\/strong> Bu, sistemimizin kalbini olu\u015fturacak. Sunucusuz fonksiyonlar, belirli bir olaya (\u00f6rne\u011fin, zamanlanm\u0131\u015f bir tetikleyici) yan\u0131t olarak \u00e7al\u0131\u015fan k\u00fc\u00e7\u00fck, ba\u011f\u0131ms\u0131z kod par\u00e7alar\u0131d\u0131r. Sunucu y\u00f6netimiyle u\u011fra\u015fmadan, sadece kodumuzu yazarak h\u0131zl\u0131 ve maliyet etkin bir \u015fekilde uygulamalar geli\u015ftirmemizi sa\u011flarlar. G\u00fcnl\u00fck tetikleyicilerimiz ve do\u011fum g\u00fcn\u00fc kontrol mant\u0131\u011f\u0131m\u0131z burada \u00e7al\u0131\u015facak.<br \/>\n*   <strong>DigitalOcean Managed Databases (Y\u00f6netilen Veritabanlar\u0131):<\/strong> Do\u011fum g\u00fcn\u00fc bilgilerini g\u00fcvenli ve eri\u015filebilir bir \u015fekilde saklamak i\u00e7in y\u00f6netilen bir veritaban\u0131 hizmeti kullanaca\u011f\u0131z. DigitalOcean, PostgreSQL, MySQL, Redis gibi pop\u00fcler veritabanlar\u0131 i\u00e7in y\u00f6netilen \u00e7\u00f6z\u00fcmler sunar. Bu sayede veritaban\u0131 kurulumu, bak\u0131m\u0131, yedeklemesi gibi operasyonel y\u00fcklerden kurtuluruz.<br \/>\n*   <strong>DigitalOcean App Platform (Uygulama Platformu &#8211; \u0130ste\u011fe Ba\u011fl\u0131):<\/strong> E\u011fer sistemimize bir web aray\u00fcz\u00fc eklemek, do\u011fum g\u00fcn\u00fc bilgilerini kolayca y\u00f6netmek veya daha karma\u015f\u0131k bir API sunmak istersek, App Platform m\u00fckemmel bir se\u00e7enektir. Ancak temel hat\u0131rlat\u0131c\u0131 sistemi i\u00e7in zorunlu de\u011fildir.<br \/>\n*   <strong>DigitalOcean Droplets (Sanal Sunucular &#8211; Alternatif):<\/strong> Sunucusuz fonksiyonlar yerine, bir Droplet \u00fczerinde bir cron job kurarak da benzer bir otomasyonu sa\u011flayabiliriz. Ancak Functions, daha az y\u00f6netim y\u00fck\u00fc ve &#8220;kulland\u0131k\u00e7a \u00f6de&#8221; modeli ile bu t\u00fcr g\u00f6revler i\u00e7in genellikle daha uygun maliyetlidir.<\/p>\n<h3>\u00dc\u00e7\u00fcnc\u00fc Taraf Entegrasyonlar<\/h3>\n<p>*   <strong>E-posta Servisleri (SendGrid, Mailgun vb.):<\/strong> Do\u011fum g\u00fcn\u00fc hat\u0131rlat\u0131c\u0131lar\u0131n\u0131 e-posta olarak g\u00f6ndermek i\u00e7in bu servislerin API&#8217;lerini kullanaca\u011f\u0131z. Genellikle \u00fccretsiz katmanlar\u0131 bulunur ve kolay entegrasyon sa\u011flarlar.<br \/>\n*   <strong>SMS Servisleri (Twilio vb.):<\/strong> E\u011fer hat\u0131rlat\u0131c\u0131lar\u0131 SMS olarak almak istersek, Twilio gibi SMS API sa\u011flay\u0131c\u0131lar\u0131 kullan\u0131labilir.<br \/>\n*   <strong>Anl\u0131k Mesajla\u015fma (Slack, Discord Webhooks):<\/strong> Daha \u00e7ok ekip i\u00e7i kullan\u0131m veya ki\u015fisel bildirimler i\u00e7in Slack veya Discord gibi platformlar\u0131n webhook \u00f6zelliklerini kullanarak mesaj g\u00f6nderebiliriz.<\/p>\n<h3>Veri Depolama: Do\u011fum G\u00fcn\u00fc Bilgilerini Nerede Tutaca\u011f\u0131z?<\/h3>\n<p>Do\u011fum g\u00fcn\u00fc hat\u0131rlat\u0131c\u0131 sistemimizin temelini, do\u011fum g\u00fcn\u00fc bilgilerini saklad\u0131\u011f\u0131m\u0131z veritaban\u0131 olu\u015fturur. Bu verilerin g\u00fcvenilir, h\u0131zl\u0131 eri\u015filebilir ve kolay y\u00f6netilebilir olmas\u0131 \u00f6nemlidir. Bu nedenle, DigitalOcean Managed PostgreSQL veya MySQL gibi ili\u015fkisel bir veritaban\u0131 hizmeti tercih etmek en uygunudur.<\/p>\n<p><strong>Gereksinimler:<\/strong><br \/>\n*   <strong>G\u00fcvenilirlik:<\/strong> Veri kayb\u0131n\u0131 \u00f6nlemek i\u00e7in otomatik yedekleme ve y\u00fcksek eri\u015filebilirlik.<br \/>\n*   <strong>Eri\u015fim H\u0131z\u0131:<\/strong> Fonksiyonumuzun veritaban\u0131na h\u0131zl\u0131 bir \u015fekilde ba\u011flan\u0131p sorgu yapabilmesi.<br \/>\n*   <strong>Y\u00f6netim Kolayl\u0131\u011f\u0131:<\/strong> Veritaban\u0131 altyap\u0131s\u0131n\u0131n DigitalOcean taraf\u0131ndan y\u00f6netilmesi, bizim sadece veriye odaklanmam\u0131z\u0131 sa\u011flamal\u0131.<\/p>\n<p><strong>Veritaban\u0131 \u015eemas\u0131 Tasar\u0131m\u0131:<\/strong><br \/>\nA\u015fa\u011f\u0131da, bir PostgreSQL veritaban\u0131nda kullanabilece\u011fimiz basit bir <code>birthdays<\/code> tablosu i\u00e7in \u00f6rnek bir \u015fema bulunmaktad\u0131r:<\/p>\n<pre><code class=\"language-sql\">CREATE TABLE birthdays (\n    id SERIAL PRIMARY KEY,\n    first_name VARCHAR(100) NOT NULL,\n    last_name VARCHAR(100),\n    birth_date DATE NOT NULL,\n    notification_type VARCHAR(50) DEFAULT 'email', -- 'email', 'sms', 'slack'\n    recipient_email VARCHAR(255),\n    recipient_phone VARCHAR(20),\n    slack_webhook_url TEXT,\n    last_notified_year INT, -- Son hangi y\u0131lda bildirim g\u00f6nderildi\u011fi\n    created_at TIMESTAMP WITH TIME ZONE DEFAULT CURRENT_TIMESTAMP,\n    updated_at TIMESTAMP WITH TIME ZONE DEFAULT CURRENT_TIMESTAMP\n);<\/code><\/pre>\n<p><strong>S\u00fctun A\u00e7\u0131klamalar\u0131:<\/strong><br \/>\n*   <code>id<\/code>: Her do\u011fum g\u00fcn\u00fc kayd\u0131 i\u00e7in benzersiz kimlik.<br \/>\n*   <code>first_name<\/code>, <code>last_name<\/code>: Do\u011fum g\u00fcn\u00fc olan ki\u015finin ad\u0131 ve soyad\u0131.<br \/>\n*   <code>birth_date<\/code>: Ki\u015finin do\u011fum tarihi (y\u0131l, ay, g\u00fcn). Y\u0131l bilgisi, ya\u015f hesaplamak veya ge\u00e7mi\u015f y\u0131llara g\u00f6re bildirim g\u00f6ndermemek i\u00e7in \u00f6nemlidir.<br \/>\n*   <code>notification_type<\/code>: Hangi kanaldan bildirim g\u00f6nderilece\u011fini belirler (\u00f6rn: &#8217;email&#8217;, &#8216;sms&#8217;, &#8216;slack&#8217;).<br \/>\n*   <code>recipient_email<\/code>, <code>recipient_phone<\/code>, <code>slack_webhook_url<\/code>: Bildirimin g\u00f6nderilece\u011fi e-posta adresi, telefon numaras\u0131 veya Slack webhook URL&#8217;si.<br \/>\n*   <code>last_notified_year<\/code>: Bu alan, her y\u0131l sadece bir kez bildirim g\u00f6nderilmesini sa\u011flamak i\u00e7in \u00f6nemlidir. Bildirim g\u00f6nderildi\u011finde, bu alan g\u00fcncel y\u0131la ayarlan\u0131r.<br \/>\n*   <code>created_at<\/code>, <code>updated_at<\/code>: Kayd\u0131n olu\u015fturulma ve son g\u00fcncellenme tarihleri.<\/p>\n<h3>Tetikleyici Mekanizmas\u0131: Her G\u00fcn Nas\u0131l \u00c7al\u0131\u015facak?<\/h3>\n<p>Sistemimizin her g\u00fcn otomatik olarak \u00e7al\u0131\u015fmas\u0131n\u0131 sa\u011flayacak mekanizma, DigitalOcean Functions&#8217;\u0131n zamanlanm\u0131\u015f tetikleyicileridir. Bu \u00f6zellik, sunucusuz fonksiyonlar\u0131m\u0131z\u0131 belirli bir cron ifadesine g\u00f6re d\u00fczenli aral\u0131klarla \u00e7al\u0131\u015ft\u0131rmam\u0131z\u0131 sa\u011flar.<\/p>\n<p><strong>DigitalOcean Functions Zamanlanm\u0131\u015f Tetikleyicileri (Cron-like triggers):<\/strong><br \/>\nBu, en ideal ve y\u00f6netimi en kolay y\u00f6ntemdir. DigitalOcean, fonksiyonlar\u0131n\u0131za do\u011frudan cron tab benzeri bir ifade tan\u0131mlayarak otomatik tetikleme imkan\u0131 sunar. \u00d6rne\u011fin, her g\u00fcn sabah 8&#8217;de \u00e7al\u0131\u015facak bir tetikleyici i\u00e7in <code>0 8 <em> <\/em> *<\/code> (UTC saatiyle) \u015feklinde bir cron ifadesi kullanabiliriz. Fonksiyon, tan\u0131mlanan bu zaman diliminde otomatik olarak \u00e7a\u011fr\u0131l\u0131r ve i\u00e7erisindeki kodu \u00e7al\u0131\u015ft\u0131r\u0131r.<\/p>\n<p><strong>Alternatif: Droplet \u00dczerinde Cron Job:<\/strong><br \/>\nE\u011fer sunucusuz mimari yerine daha geleneksel bir yakla\u015f\u0131m tercih ediyorsan\u0131z, DigitalOcean Droplet \u00fczerinde bir sanal sunucu olu\u015fturup, bu sunucu \u00fczerinde bir script (\u00f6rne\u011fin Python veya Node.js) \u00e7al\u0131\u015ft\u0131rabilir ve bu scripti Linux&#8217;un <code>cron<\/code> servisi ile zamanlayabilirsiniz. Ancak bu yakla\u015f\u0131m, sunucu y\u00f6netimi (i\u015fletim sistemi g\u00fcncellemeleri, g\u00fcvenlik yamalar\u0131 vb.) gibi ek sorumluluklar getirir ve Functions&#8217;a g\u00f6re daha az maliyet etkin olabilir.<\/p>\n<h3>\u0130\u015f Mant\u0131\u011f\u0131: Kimin Do\u011fum G\u00fcn\u00fc Var?<\/h3>\n<p>Zamanlanm\u0131\u015f tetikleyici taraf\u0131ndan \u00e7a\u011fr\u0131lan fonksiyonumuzun ana g\u00f6revi, veritaban\u0131ndan yakla\u015fan do\u011fum g\u00fcnlerini tespit etmek ve bunlar i\u00e7in bildirim haz\u0131rlamakt\u0131r.<\/p>\n<p><strong>Fonksiyonun G\u00f6revi:<\/strong><br \/>\n1.  Veritaban\u0131na ba\u011flan.<br \/>\n2.  Bug\u00fcn veya yar\u0131n do\u011fum g\u00fcn\u00fc olan ki\u015fileri sorgula.<br \/>\n3.  Sorgulama yaparken, <code>last_notified_year<\/code> alan\u0131n\u0131 kontrol ederek, bu y\u0131l i\u00e7in zaten bildirim g\u00f6nderilip g\u00f6nderilmedi\u011fini kontrol et. (Y\u0131l d\u00f6n\u00fcm\u00fc ge\u00e7tiyse veya hen\u00fcz gelmediyse.)<br \/>\n4.  Tespit edilen her ki\u015fi i\u00e7in uygun bir hat\u0131rlatma mesaj\u0131 olu\u015ftur.<br \/>\n5.  Bildirim t\u00fcr\u00fcne (e-posta, SMS vb.) g\u00f6re ilgili API&#8217;yi \u00e7a\u011f\u0131rarak bildirimi g\u00f6nder.<br \/>\n6.  Bildirim g\u00f6nderildikten sonra, ilgili kayd\u0131n <code>last_notified_year<\/code> alan\u0131n\u0131 g\u00fcncel y\u0131la ayarla.<\/p>\n<p><strong>Veritaban\u0131 Sorgulama Mant\u0131\u011f\u0131:<\/strong><br \/>\nFonksiyonumuzun ana sorgusu, ge\u00e7erli ay ve g\u00fcne g\u00f6re filtreleme yapacakt\u0131r.<\/p>\n<pre><code class=\"language-sql\">SELECT *\nFROM birthdays\nWHERE EXTRACT(MONTH FROM birth_date) = EXTRACT(MONTH FROM CURRENT_DATE)\n  AND EXTRACT(DAY FROM birth_date) = EXTRACT(DAY FROM CURRENT_DATE)\n  AND (last_notified_year IS NULL OR last_notified_year != EXTRACT(YEAR FROM CURRENT_DATE));<\/code><\/pre>\n<p>Bu sorgu, sadece bug\u00fcn\u00fcn ay ve g\u00fcn\u00fcne uyan ve bu y\u0131l hen\u00fcz bildirim g\u00f6nderilmemi\u015f do\u011fum g\u00fcnlerini getirir. \u0130stenirse, yar\u0131nki do\u011fum g\u00fcnleri i\u00e7in de benzer bir sorgu eklenebilir.<\/p>\n<h3>Bildirim Sistemi: Hat\u0131rlat\u0131c\u0131lar\u0131 Nas\u0131l G\u00f6nderece\u011fiz?<\/h3>\n<p>Do\u011fum g\u00fcn\u00fc olan ki\u015fileri tespit ettikten sonra, bu bilgiyi kullan\u0131c\u0131ya ula\u015ft\u0131rmam\u0131z gerekir. Bunun i\u00e7in \u00e7e\u015fitli bildirim kanallar\u0131 ve \u00fc\u00e7\u00fcnc\u00fc taraf servisler kullanabiliriz.<\/p>\n<p>*   <strong>E-posta (SendGrid, Mailgun):<\/strong> En yayg\u0131n ve esnek bildirim y\u00f6ntemidir. SendGrid veya Mailgun gibi servisler, g\u00fc\u00e7l\u00fc API&#8217;ler sunarak e-posta g\u00f6nderme s\u00fcrecini kolayla\u015ft\u0131r\u0131r. Fonksiyonumuz, bu servislerin API&#8217;lerini kullanarak ki\u015fiselle\u015ftirilmi\u015f e-postalar g\u00f6nderebilir. Genellikle \u00fccretsiz veya \u00e7ok uygun fiyatl\u0131 ba\u015flang\u0131\u00e7 katmanlar\u0131 bulunur.<br \/>\n*   <strong>SMS (Twilio):<\/strong> Acil veya an\u0131nda ula\u015fmas\u0131 gereken bildirimler i\u00e7in SMS idealdir. Twilio, d\u00fcnya genelinde SMS g\u00f6nderme ve alma hizmetleri sunan pop\u00fcler bir platformdur. Fonksiyonumuz, Twilio API&#8217;sini kullanarak hat\u0131rlat\u0131c\u0131lar\u0131 do\u011frudan telefon numaralar\u0131na g\u00f6nderebilir.<br \/>\n*   <strong>Anl\u0131k Mesajla\u015fma (Slack, Discord Webhooks):<\/strong> E\u011fer hat\u0131rlat\u0131c\u0131lar\u0131 bir ekip kanal\u0131na veya ki\u015fisel bir Slack\/Discord hesab\u0131na g\u00f6ndermek istiyorsan\u0131z, bu platformlar\u0131n webhook \u00f6zelliklerini kullanabilirsiniz. Bir webhook URL&#8217;sine basit bir HTTP POST iste\u011fi g\u00f6ndererek mesaj g\u00f6ndermek m\u00fcmk\u00fcnd\u00fcr.<\/p>\n<p>Her bildirim t\u00fcr\u00fc i\u00e7in, fonksiyonumuzun ilgili servis API&#8217;sine istek yapacak kodu i\u00e7ermesi ve gerekli kimlik do\u011frulama bilgilerini (API anahtarlar\u0131) g\u00fcvenli bir \u015fekilde y\u00f6netmesi gerekecektir.<\/p>\n<h2>Ad\u0131m Ad\u0131m Uygulama: DigitalOcean \u00dczerinde Kurulum<\/h2>\n<p>\u015eimdiye kadar teorik altyap\u0131y\u0131 ve mimariyi konu\u015ftuk. Art\u0131k DigitalOcean \u00fczerinde bu sistemi pratik olarak nas\u0131l kuraca\u011f\u0131m\u0131za dair ad\u0131mlar\u0131 inceleyelim.<\/p>\n<h3>Ad\u0131m 1: DigitalOcean Managed Database Kurulumu<\/h3>\n<p>\u00d6ncelikle do\u011fum g\u00fcn\u00fc bilgilerini saklayaca\u011f\u0131m\u0131z veritaban\u0131n\u0131 kurmam\u0131z gerekiyor.<\/p>\n<p>1.  <strong>DigitalOcean Hesab\u0131n\u0131za Giri\u015f Yap\u0131n:<\/strong> DigitalOcean kontrol paneline gidin.<br \/>\n2.  <strong>Veritaban\u0131 Olu\u015fturma:<\/strong> Sol men\u00fcden &#8220;Databases&#8221; se\u00e7ene\u011fine t\u0131klay\u0131n ve &#8220;Create a Database Cluster&#8221; butonuna bas\u0131n.<br \/>\n3.  <strong>Veritaban\u0131 T\u00fcr\u00fc Se\u00e7imi:<\/strong> PostgreSQL veya MySQL&#8217;i se\u00e7in. Bu \u00f6rnekte PostgreSQL kullanaca\u011f\u0131z.<br \/>\n4.  <strong>Plan ve B\u00f6lge Se\u00e7imi:<\/strong> \u0130htiya\u00e7lar\u0131n\u0131za uygun bir plan (\u00f6rne\u011fin, ba\u015flang\u0131\u00e7 seviyesi bir plan) ve size en yak\u0131n veri merkezi b\u00f6lgesini se\u00e7in.<br \/>\n5.  <strong>Veritaban\u0131 Ad\u0131 ve Kimlik Bilgileri:<\/strong> Veritaban\u0131 k\u00fcmenize bir isim verin ve varsay\u0131lan kullan\u0131c\u0131 ad\u0131 ile parolas\u0131n\u0131 not al\u0131n. Bu bilgiler fonksiyonumuzun veritaban\u0131na ba\u011flanmas\u0131 i\u00e7in gerekecek.<br \/>\n6.  <strong>Olu\u015fturma:<\/strong> Veritaban\u0131 k\u00fcmesini olu\u015fturmak i\u00e7in &#8220;Create Database Cluster&#8221; butonuna t\u0131klay\u0131n. Olu\u015fturma i\u015flemi birka\u00e7 dakika s\u00fcrebilir.<br \/>\n7.  <strong>Ba\u011flant\u0131 Bilgilerini Al\u0131n:<\/strong> Veritaban\u0131 k\u00fcmeniz haz\u0131r oldu\u011funda, &#8220;Connection Details&#8221; b\u00f6l\u00fcm\u00fcnden ba\u011flant\u0131 dizesini (connection string) veya ayr\u0131 ayr\u0131 host, port, kullan\u0131c\u0131 ad\u0131, parola, veritaban\u0131 ad\u0131 bilgilerini al\u0131n. Bu bilgiler fonksiyonunuzun ortam de\u011fi\u015fkenlerine eklenecektir.<br \/>\n8.  <strong>Veritaban\u0131 \u015eemas\u0131 Olu\u015fturma:<\/strong> Bir SQL istemcisi (DBeaver, pgAdmin veya <code>psql<\/code> komut sat\u0131r\u0131 arac\u0131) kullanarak veritaban\u0131n\u0131za ba\u011flan\u0131n ve yukar\u0131da bahsetti\u011fimiz <code>birthdays<\/code> tablosunu olu\u015fturmak i\u00e7in SQL komutunu \u00e7al\u0131\u015ft\u0131r\u0131n:<\/p>\n<pre><code class=\"language-sql\">CREATE TABLE birthdays (\n        id SERIAL PRIMARY KEY,\n        first_name VARCHAR(100) NOT NULL,\n        last_name VARCHAR(100),\n        birth_date DATE NOT NULL,\n        notification_type VARCHAR(50) DEFAULT 'email',\n        recipient_email VARCHAR(255),\n        recipient_phone VARCHAR(20),\n        slack_webhook_url TEXT,\n        last_notified_year INT,\n        created_at TIMESTAMP WITH TIME ZONE DEFAULT CURRENT_TIMESTAMP,\n        updated_at TIMESTAMP WITH TIME ZONE DEFAULT CURRENT_TIMESTAMP\n    );<\/code><\/pre>\n<p>9.  <strong>\u00d6rnek Veri Ekleme:<\/strong> Testleriniz i\u00e7in birka\u00e7 \u00f6rnek do\u011fum g\u00fcn\u00fc kayd\u0131 ekleyin. Bir kayd\u0131n <code>birth_date<\/code> alan\u0131n\u0131 bug\u00fcn\u00fcn veya yar\u0131n\u0131n ay ve g\u00fcn\u00fcyle e\u015fle\u015fecek \u015fekilde ayarlayarak test etmeyi unutmay\u0131n.<\/p>\n<pre><code class=\"language-sql\">INSERT INTO birthdays (first_name, last_name, birth_date, notification_type, recipient_email) VALUES\n    ('Ay\u015fe', 'Y\u0131lmaz', '1990-01-20', 'email', 'ayse.yilmaz@example.com'),\n    ('Mehmet', 'Demir', '1985-01-21', 'email', 'mehmet.demir@example.com');\n    -- Not: Bug\u00fcne veya yar\u0131na denk gelen bir tarih se\u00e7in.<\/code><\/pre>\n<h3>Ad\u0131m 2: DigitalOcean Functions Olu\u015fturma<\/h3>\n<p>\u015eimdi s\u0131ra, do\u011fum g\u00fcn\u00fc kontrol\u00fcn\u00fc yapacak sunucusuz fonksiyonumuzu olu\u015fturmaya geldi. Bu \u00f6rnekte Node.js kullanaca\u011f\u0131z, ancak Python veya Go gibi di\u011fer dilleri de tercih edebilirsiniz.<\/p>\n<p>1.  <strong>Functions Projesi Ba\u015flatma:<\/strong><br \/>\n    *   DigitalOcean kontrol panelinde &#8220;Functions&#8221; b\u00f6l\u00fcm\u00fcne gidin ve &#8220;Create Function&#8221; veya &#8220;Create Project&#8221; butonuna t\u0131klay\u0131n.<br \/>\n    *   Yeni bir proje olu\u015fturun ve projenize bir isim verin (\u00f6rn: <code>birthday-reminders<\/code>).<br \/>\n    *   Projenin i\u00e7ine yeni bir fonksiyon (\u00f6rne\u011fin <code>check-birthdays<\/code>) olu\u015fturun. \u00c7al\u0131\u015fma zaman\u0131 olarak &#8220;Node.js&#8221; se\u00e7in.<br \/>\n2.  <strong>Fonksiyon Kodu (Node.js \u00d6rne\u011fi):<\/strong><br \/>\n    A\u015fa\u011f\u0131daki \u00f6rnek kod, PostgreSQL veritaban\u0131na ba\u011flan\u0131r, bug\u00fcn do\u011fum g\u00fcn\u00fc olanlar\u0131 sorgular ve SendGrid arac\u0131l\u0131\u011f\u0131yla e-posta g\u00f6nderir.<\/p>\n<pre><code class=\"language-javascript\">\/\/ index.js (DigitalOcean Function kodu)\n    const { Client } = require('pg'); \/\/ PostgreSQL istemcisi\n    const sgMail = require('@sendgrid\/mail'); \/\/ SendGrid istemcisi\n\n    \/\/ Ortam de\u011fi\u015fkenlerinden SendGrid API anahtar\u0131n\u0131 al\n    sgMail.setApiKey(process.env.SENDGRID_API_KEY);\n\n    exports.main = async (args) => {\n        const client = new Client({\n            connectionString: process.env.DATABASE_URL, \/\/ Veritaban\u0131 ba\u011flant\u0131 dizesi\n            ssl: {\n                rejectUnauthorized: false \/\/ DigitalOcean Managed DB i\u00e7in gerekli olabilir\n            }\n        });\n\n        try {\n            await client.connect(); \/\/ Veritaban\u0131na ba\u011flan\n\n            const today = new Date();\n            const currentMonth = today.getMonth() + 1; \/\/ Ay 0'dan ba\u015flar\n            const currentDay = today.getDate();\n            const currentYear = today.getFullYear();\n\n            \/\/ Bug\u00fcn do\u011fum g\u00fcn\u00fc olan ve bu y\u0131l hen\u00fcz bildirim g\u00f6nderilmemi\u015f ki\u015fileri sorgula\n            const query = <code>\n                SELECT id, first_name, last_name, birth_date, notification_type, recipient_email, recipient_phone, slack_webhook_url\n                FROM birthdays\n                WHERE EXTRACT(MONTH FROM birth_date) = $1\n                  AND EXTRACT(DAY FROM birth_date) = $2\n                  AND (last_notified_year IS NULL OR last_notified_year != $3);\n            <\/code>;\n            const res = await client.query(query, [currentMonth, currentDay, currentYear]);\n            const birthdaysToday = res.rows;\n\n            if (birthdaysToday.length === 0) {\n                console.log('Bug\u00fcn do\u011fum g\u00fcn\u00fc olan kimse bulunamad\u0131 veya zaten bildirim g\u00f6nderildi.');\n                return { statusCode: 200, body: 'No birthdays today.' };\n            }\n\n            console.log(<code>Bug\u00fcn ${birthdaysToday.length} ki\u015finin do\u011fum g\u00fcn\u00fc var.<\/code>);\n\n            for (const person of birthdaysToday) {\n                const fullName = <code>${person.first_name} ${person.last_name || ''}<\/code>.trim();\n                const birthYear = person.birth_date ? new Date(person.birth_date).getFullYear() : null;\n                const age = birthYear ? currentYear - birthYear : 'bilinmiyor';\n\n                let messageBody = '';\n                if (birthYear) {\n                    messageBody = <code>Bug\u00fcn ${fullName} adl\u0131 ki\u015finin ${age}. do\u011fum g\u00fcn\u00fc! Kutlamay\u0131 unutmay\u0131n.<\/code>;\n                } else {\n                    messageBody = <code>Bug\u00fcn ${fullName} adl\u0131 ki\u015finin do\u011fum g\u00fcn\u00fc! Kutlamay\u0131 unutmay\u0131n.<\/code>;\n                }\n\n                \/\/ Bildirim tipine g\u00f6re i\u015flem yap\n                if (person.notification_type === 'email' && person.recipient_email) {\n                    const msg = {\n                        to: person.recipient_email,\n                        from: process.env.SENDER_EMAIL, \/\/ G\u00f6nderen e-posta adresi (SendGrid'de do\u011frulanm\u0131\u015f olmal\u0131)\n                        subject: <code>Do\u011fum G\u00fcn\u00fc Hat\u0131rlat\u0131c\u0131s\u0131: ${fullName}<\/code>,\n                        html: <code><p>${messageBody}<\/p><p>Sevgilerle, Otomatik Hat\u0131rlat\u0131c\u0131 Sisteminiz<\/p><\/code>,\n                    };\n                    await sgMail.send(msg);\n                    console.log(<code>E-posta g\u00f6nderildi: ${person.recipient_email}<\/code>);\n                }\n                \/\/ SMS veya Slack i\u00e7in benzer if bloklar\u0131 eklenebilir\n                \/\/ else if (person.notification_type === 'sms' && person.recipient_phone) {\n                \/\/     \/\/ Twilio API \u00e7a\u011fr\u0131s\u0131\n                \/\/ } else if (person.notification_type === 'slack' && person.slack_webhook_url) {\n                \/\/     \/\/ Slack Webhook \u00e7a\u011fr\u0131s\u0131\n                \/\/ }\n\n                \/\/ last_notified_year alan\u0131n\u0131 g\u00fcncelle\n                await client.query(\n                    <code>UPDATE birthdays SET last_notified_year = $1, updated_at = CURRENT_TIMESTAMP WHERE id = $2;<\/code>,\n                    [currentYear, person.id]\n                );\n                console.log(<code>'last_notified_year' g\u00fcncellendi for ${fullName}<\/code>);\n            }\n\n            return { statusCode: 200, body: 'Do\u011fum g\u00fcn\u00fc hat\u0131rlat\u0131c\u0131lar\u0131 ba\u015far\u0131yla g\u00f6nderildi.' };\n\n        } catch (error) {\n            console.error('Fonksiyon hatas\u0131:', error);\n            return { statusCode: 500, body: <code>Hata: ${error.message}<\/code> };\n        } finally {\n            await client.end(); \/\/ Veritaban\u0131 ba\u011flant\u0131s\u0131n\u0131 kapat\n        }\n    };<\/code><\/pre>\n<p>3.  <strong>Ba\u011f\u0131ml\u0131l\u0131klar\u0131 Ekleme:<\/strong><br \/>\n    Fonksiyonunuzun k\u00f6k dizininde bir <code>package.json<\/code> dosyas\u0131 olu\u015fturun ve gerekli ba\u011f\u0131ml\u0131l\u0131klar\u0131 ekleyin:<\/p>\n<pre><code class=\"language-json\">{\n      \"name\": \"check-birthdays\",\n      \"version\": \"1.0.0\",\n      \"description\": \"DigitalOcean Function to check and send birthday reminders.\",\n      \"main\": \"index.js\",\n      \"dependencies\": {\n        \"pg\": \"^8.x.x\",        \/\/ PostgreSQL istemcisi\n        \"@sendgrid\/mail\": \"^7.x.x\" \/\/ SendGrid istemcisi\n      }\n    }<\/code><\/pre>\n<p>    DigitalOcean Functions, bu <code>package.json<\/code> dosyas\u0131n\u0131 kullanarak ba\u011f\u0131ml\u0131l\u0131klar\u0131 otomatik olarak y\u00fckleyecektir.<\/p>\n<p>4.  <strong>Ortam De\u011fi\u015fkenleri Ayarlama:<\/strong><br \/>\n    Hassas bilgileri (veritaban\u0131 ba\u011flant\u0131 dizesi, API anahtarlar\u0131) do\u011frudan kodda saklamak yerine ortam de\u011fi\u015fkenleri olarak ayarlamak \u00f6nemlidir.<br \/>\n    *   Fonksiyonunuzun ayarlar b\u00f6l\u00fcm\u00fcne gidin.<br \/>\n    *   &#8220;Environment Variables&#8221; k\u0131sm\u0131na a\u015fa\u011f\u0131daki de\u011fi\u015fkenleri ekleyin:<br \/>\n        *   <code>DATABASE_URL<\/code>: DigitalOcean Managed Database&#8217;inizden ald\u0131\u011f\u0131n\u0131z ba\u011flant\u0131 dizesi.<br \/>\n        *   <code>SENDGRID_API_KEY<\/code>: SendGrid&#8217;den alaca\u011f\u0131n\u0131z API anahtar\u0131.<br \/>\n        *   <code>SENDER_EMAIL<\/code>: SendGrid&#8217;de do\u011frulanm\u0131\u015f g\u00f6nderen e-posta adresiniz.<\/p>\n<h3>Ad\u0131m 3: Bildirim Servisi Entegrasyonu (SendGrid \u00d6rne\u011fi)<\/h3>\n<p>E-posta g\u00f6ndermek i\u00e7in SendGrid&#8217;i nas\u0131l entegre edece\u011fimizi detayland\u0131ral\u0131m.<\/p>\n<p>1.  <strong>SendGrid Hesab\u0131 Olu\u015fturma:<\/strong><br \/>\n    *   SendGrid web sitesine gidin ve \u00fccretsiz bir hesap olu\u015fturun. Genellikle belirli bir say\u0131da \u00fccretsiz e-posta g\u00f6ndermenize izin veren bir katman sunarlar.<br \/>\n2.  <strong>API Anahtar\u0131 Alma:<\/strong><br \/>\n    *   SendGrid kontrol panelinize giri\u015f yap\u0131n.<br \/>\n    *   &#8220;Settings&#8221; -> &#8220;API Keys&#8221; b\u00f6l\u00fcm\u00fcne gidin.<br \/>\n    *   &#8220;Create API Key&#8221; butonuna t\u0131klay\u0131n.<br \/>\n    *   API anahtar\u0131n\u0131za bir isim verin ve &#8220;Full Access&#8221; veya sadece &#8220;Mail Send&#8221; izinlerini se\u00e7in.<br \/>\n    *   Olu\u015fturulan API anahtar\u0131n\u0131 kopyalay\u0131n. Bu anahtar\u0131 DigitalOcean Functions&#8217;taki <code>SENDGRID_API_KEY<\/code> ortam de\u011fi\u015fkenine yap\u0131\u015ft\u0131racaks\u0131n\u0131z.<br \/>\n3.  <strong>G\u00f6nderen Kimli\u011fi Do\u011frulama:<\/strong><br \/>\n    *   SendGrid, e-posta g\u00f6nderebilmeniz i\u00e7in g\u00f6nderen e-posta adresinizi veya alan ad\u0131n\u0131z\u0131 do\u011frulaman\u0131z\u0131 ister.<br \/>\n    *   &#8220;Settings&#8221; -> &#8220;Sender Authentication&#8221; b\u00f6l\u00fcm\u00fcne gidin ve e-posta adresinizi veya alan ad\u0131n\u0131z\u0131 do\u011frulay\u0131n. Bu, spam olarak i\u015faretlenme olas\u0131l\u0131\u011f\u0131n\u0131 azalt\u0131r. Do\u011frulad\u0131\u011f\u0131n\u0131z e-posta adresini DigitalOcean Functions&#8217;taki <code>SENDER_EMAIL<\/code> ortam de\u011fi\u015fkenine ekleyeceksiniz.<br \/>\n4.  <strong>Fonksiyon \u0130\u00e7inde SendGrid Kullan\u0131m\u0131:<\/strong><br \/>\n    Yukar\u0131daki Node.js kod \u00f6rne\u011finde <code>sgMail.send(msg)<\/code> sat\u0131r\u0131, SendGrid API&#8217;sini kullanarak e-posta g\u00f6nderme i\u015flemini ger\u00e7ekle\u015ftirir. <code>msg<\/code> objesi, al\u0131c\u0131, g\u00f6nderen, konu ve e-posta i\u00e7eri\u011fi gibi bilgileri i\u00e7erir.<\/p>\n<h3>Ad\u0131m 4: Fonksiyonu Zamanlama<\/h3>\n<p>Fonksiyonumuzun her g\u00fcn otomatik olarak \u00e7al\u0131\u015fmas\u0131n\u0131 sa\u011flamak i\u00e7in bir tetikleyici ayarlamam\u0131z gerekiyor.<\/p>\n<p>1.  <strong>DigitalOcean Functions Tetikleyici Ayarlar\u0131:<\/strong><br \/>\n    *   DigitalOcean kontrol panelinde fonksiyonunuzun (\u00f6rn: <code>check-birthdays<\/code>) detay sayfas\u0131na gidin.<br \/>\n    *   &#8220;Triggers&#8221; sekmesine t\u0131klay\u0131n.<br \/>\n    *   &#8220;Add Trigger&#8221; butonuna t\u0131klay\u0131n.<br \/>\n    *   Tetikleyici tipi olarak &#8220;Scheduled&#8221; (Zamanlanm\u0131\u015f) se\u00e7ene\u011fini se\u00e7in.<br \/>\n    *   <strong>Cron Expression:<\/strong> Bu alana fonksiyonunuzun ne zaman \u00e7al\u0131\u015faca\u011f\u0131n\u0131 belirten bir cron ifadesi girin. \u00d6rne\u011fin:<br \/>\n        <em>   <code>0 8 <\/em> <em> <\/em><\/code>: Her g\u00fcn sabah 8:00 UTC&#8217;de \u00e7al\u0131\u015f\u0131r.<br \/>\n        <em>   <code>0 0 <\/em> <em> <\/em><\/code>: Her g\u00fcn gece yar\u0131s\u0131 0:00 UTC&#8217;de \u00e7al\u0131\u015f\u0131r.<br \/>\n        <em>   <code>0 8 <\/em> * 1-5<\/code>: Hafta i\u00e7i her g\u00fcn sabah 8:00 UTC&#8217;de \u00e7al\u0131\u015f\u0131r.<br \/>\n        Do\u011fum g\u00fcn\u00fc hat\u0131rlat\u0131c\u0131lar\u0131 i\u00e7in genellikle sabah saatleri tercih edilir, b\u00f6ylece ki\u015fi g\u00fcn i\u00e7inde kutlama yapabilir.<br \/>\n    *   Tetikleyiciyi kaydedin.<\/p>\n<h3>Ad\u0131m 5: Test ve Hata Ay\u0131klama<\/h3>\n<p>Kurulum tamamland\u0131ktan sonra, sistemin do\u011fru \u00e7al\u0131\u015ft\u0131\u011f\u0131ndan emin olmak i\u00e7in test etmeliyiz.<\/p>\n<p>1.  <strong>Manuel Tetikleme:<\/strong> Fonksiyonunuzun detay sayfas\u0131nda &#8220;Run Function&#8221; veya &#8220;Invoke&#8221; butonunu kullanarak fonksiyonu manuel olarak \u00e7al\u0131\u015ft\u0131r\u0131n. Bu, veritaban\u0131 ba\u011flant\u0131s\u0131 ve bildirim g\u00f6nderme ad\u0131mlar\u0131n\u0131n do\u011fru \u00e7al\u0131\u015f\u0131p \u00e7al\u0131\u015fmad\u0131\u011f\u0131n\u0131 kontrol etmenizi sa\u011flar.<br \/>\n2.  <strong>Log Takibi:<\/strong> Fonksiyon \u00e7al\u0131\u015ft\u0131ktan sonra, &#8220;Logs&#8221; sekmesinden \u00e7\u0131kt\u0131lar\u0131 ve olas\u0131 hatalar\u0131 kontrol edin. Veritaban\u0131 ba\u011flant\u0131 hatalar\u0131, API anahtar\u0131 sorunlar\u0131 veya SendGrid taraf\u0131ndan reddedilen e-postalar gibi sorunlar burada g\u00f6r\u00fcnecektir.<br \/>\n3.  <strong>Veritaban\u0131 Kontrol\u00fc:<\/strong> Fonksiyon \u00e7al\u0131\u015ft\u0131ktan sonra, <code>last_notified_year<\/code> alan\u0131n\u0131n g\u00fcncellenip g\u00fcncellenmedi\u011fini kontrol etmek i\u00e7in veritaban\u0131n\u0131za bak\u0131n.<br \/>\n4.  <strong>E-posta Kontrol\u00fc:<\/strong> Belirtti\u011finiz al\u0131c\u0131 e-posta adresine hat\u0131rlat\u0131c\u0131 e-postas\u0131n\u0131n gelip gelmedi\u011fini kontrol edin. Spam kutusunu da kontrol etmeyi unutmay\u0131n.<br \/>\n5.  <strong>Hata Durumlar\u0131 Y\u00f6netimi:<\/strong> Kodunuzda <code>try-catch<\/code> bloklar\u0131 kullanarak olas\u0131 hatalar\u0131 yakalay\u0131n ve loglay\u0131n. Gerekirse, bir hata durumunda size bildirim g\u00f6nderecek (\u00f6rne\u011fin, farkl\u0131 bir e-posta adresine) ek bir mekanizma d\u00fc\u015f\u00fcnebilirsiniz.<\/p>\n<h2>Alternatif Yakla\u015f\u0131mlar ve Geli\u015ftirmeler<\/h2>\n<p>Kurdu\u011fumuz temel sistem olduk\u00e7a i\u015flevsel olsa da, farkl\u0131 ihtiya\u00e7lara g\u00f6re \u00e7e\u015fitli alternatif yakla\u015f\u0131mlar ve geli\u015ftirmeler d\u00fc\u015f\u00fcn\u00fclebilir.<\/p>\n<h3>Droplet \u00dczerinde Cron Job Kullan\u0131m\u0131<\/h3>\n<p>E\u011fer sunucusuz mimari size yabanc\u0131 geliyorsa veya daha fazla sunucu kontrol\u00fcne ihtiyac\u0131n\u0131z varsa, bir DigitalOcean Droplet \u00fczerinde geleneksel bir cron job kullanabilirsiniz.<\/p>\n<p>*   <strong>Avantajlar\u0131:<\/strong> Tam kontrol (i\u015fletim sistemi, yaz\u0131l\u0131mlar), tan\u0131d\u0131k ortam (Linux kullan\u0131c\u0131lar\u0131 i\u00e7in).<br \/>\n*   <strong>Dezavantajlar\u0131:<\/strong> Sunucu y\u00f6netimi (g\u00fcncellemeler, g\u00fcvenlik, yedekleme), daha y\u00fcksek maliyet (s\u00fcrekli \u00e7al\u0131\u015fan sunucu), daha az \u00f6l\u00e7eklenebilirlik (manuel \u00f6l\u00e7ekleme gerektirebilir).<br \/>\n*   <strong>Kurulum Ad\u0131mlar\u0131:<\/strong><br \/>\n    1.  Bir Droplet olu\u015fturun (\u00f6rne\u011fin Ubuntu).<br \/>\n    2.  \u0130lgili \u00e7al\u0131\u015fma zaman\u0131n\u0131 (Node.js, Python vb.) ve ba\u011f\u0131ml\u0131l\u0131klar\u0131 y\u00fckleyin.<br \/>\n    3.  Yukar\u0131daki fonksiyon kodunu bir script dosyas\u0131na (\u00f6rn: <code>birthday_checker.js<\/code>) kaydedin.<br \/>\n    4.  <code>crontab -e<\/code> komutunu kullanarak cron tab&#8217;\u0131 d\u00fczenleyin ve \u015fu sat\u0131r\u0131 ekleyin:<br \/>\n        <code>0 8 <em> <\/em> * \/usr\/bin\/node \/path\/to\/your\/birthday_checker.js >> \/var\/log\/birthday_checker.log 2>&1<\/code><br \/>\n        Bu, scripti her g\u00fcn sabah 8&#8217;de \u00e7al\u0131\u015ft\u0131racak ve \u00e7\u0131kt\u0131lar\u0131 bir log dosyas\u0131na y\u00f6nlendirecektir.<\/p>\n<h3>DigitalOcean App Platform ile Web Aray\u00fcz\u00fc<\/h3>\n<p>Do\u011fum g\u00fcn\u00fc bilgilerini veritaban\u0131na do\u011frudan eklemek veya d\u00fczenlemek yerine, kullan\u0131c\u0131 dostu bir web aray\u00fcz\u00fc sunmak isterseniz, DigitalOcean App Platform&#8217;u kullanabilirsiniz.<\/p>\n<p>*   <strong>Kullan\u0131c\u0131 Aray\u00fcz\u00fc:<\/strong> Bir web uygulamas\u0131 (React, Vue, Angular veya sunucu tabanl\u0131 bir \u00e7er\u00e7eve) geli\u015ftirerek do\u011fum g\u00fcn\u00fc ekleme, d\u00fczenleme ve silme i\u015flemleri i\u00e7in bir aray\u00fcz sa\u011flayabilirsiniz.<br \/>\n*   <strong>API Endpointleri:<\/strong> Web aray\u00fcz\u00fc ile veritaban\u0131 aras\u0131nda ileti\u015fim kurmak i\u00e7in bir API (RESTful veya GraphQL) olu\u015fturabilirsiniz. Bu API, App Platform \u00fczerinde bar\u0131nd\u0131r\u0131labilir.<br \/>\n*   <strong>Entegrasyon:<\/strong> Bu web uygulamas\u0131, Functions taraf\u0131ndan kullan\u0131lan ayn\u0131 veritaban\u0131n\u0131 payla\u015fabilir.<\/p>\n<h3>Di\u011fer Bildirim Kanallar\u0131<\/h3>\n<p>E-posta ve SMS&#8217;in yan\u0131 s\u0131ra, farkl\u0131 platformlara bildirim g\u00f6ndermek de m\u00fcmk\u00fcnd\u00fcr:<\/p>\n<p>*   <strong>Slack\/Discord:<\/strong> Ekip i\u00e7i veya ki\u015fisel bildirimler i\u00e7in bu platformlar\u0131n webhook API&#8217;leri kullan\u0131labilir. Fonksiyon kodunuzda, <code>notification_type<\/code> &#8216;slack&#8217; oldu\u011funda bir HTTP POST iste\u011fi ile mesaj g\u00f6nderebilirsiniz.<br \/>\n*   <strong>WhatsApp:<\/strong> Twilio gibi baz\u0131 servisler, WhatsApp Business API entegrasyonu sunar. Bu, daha karma\u015f\u0131k bir kurulum gerektirse de, WhatsApp \u00fczerinden bildirim g\u00f6nderme imkan\u0131 sa\u011flar.<br \/>\n*   <strong>Push Bildirimleri:<\/strong> Mobil uygulama geli\u015ftiriyorsan\u0131z, Firebase Cloud Messaging (FCM) gibi servisleri kullanarak do\u011frudan cihazlara push bildirimleri g\u00f6nderebilirsiniz.<\/p>\n<h3>Geli\u015fmi\u015f \u00d6zellikler<\/h3>\n<p>Sisteminizi daha da kullan\u0131\u015fl\u0131 hale getirecek baz\u0131 geli\u015ftirmeler:<\/p>\n<p>*   <strong>Birden Fazla Hat\u0131rlatma:<\/strong> Sadece do\u011fum g\u00fcn\u00fcnde de\u011fil, bir hafta \u00f6nce veya bir g\u00fcn \u00f6nce de hat\u0131rlatma g\u00f6ndermek isteyebilirsiniz. Fonksiyonunuzun sorgu mant\u0131\u011f\u0131n\u0131, farkl\u0131 zaman aral\u0131klar\u0131n\u0131 kapsayacak \u015fekilde geni\u015fletebilirsiniz.<br \/>\n*   <strong>Ki\u015fiselle\u015ftirilmi\u015f Mesaj \u015eablonlar\u0131:<\/strong> Farkl\u0131 ki\u015filer veya gruplar i\u00e7in farkl\u0131 e-posta veya SMS \u015fablonlar\u0131 kullanabilirsiniz. Bu \u015fablonlar\u0131 veritaban\u0131nda saklayabilir veya ayr\u0131 dosyalarda tutabilirsiniz.<br \/>\n*   <strong>Hata Bildirimleri:<\/strong> Fonksiyonunuzda bir hata olu\u015ftu\u011funda (\u00f6rne\u011fin, veritaban\u0131 ba\u011flant\u0131 hatas\u0131, SendGrid API hatas\u0131), bu hatay\u0131 size bildiren (\u00f6rne\u011fin, farkl\u0131 bir e-posta adresine) otomatik bir e-posta g\u00f6nderecek bir mekanizma ekleyebilirsiniz.<br \/>\n*   <strong>Do\u011fum G\u00fcn\u00fc Listesi Y\u00f6netimi:<\/strong> Web aray\u00fcz\u00fc ile entegre bir \u015fekilde, do\u011fum g\u00fcn\u00fc listesini kolayca i\u00e7e\/d\u0131\u015fa aktarma, toplu d\u00fczenleme gibi \u00f6zellikler ekleyebilirsiniz.<\/p>\n<h2>Maliyet Analizi ve Optimizasyon<\/h2>\n<p>DigitalOcean \u00fczerinde kurdu\u011fumuz bu sistemin maliyet etkinli\u011fi, \u00f6zellikle sunucusuz fonksiyonlar sayesinde olduk\u00e7a y\u00fcksektir.<\/p>\n<p><em>   <strong>DigitalOcean Functions:<\/strong> Functions, &#8220;kulland\u0131k\u00e7a \u00f6de&#8221; (pay-as-you-go) modeliyle \u00e7al\u0131\u015f\u0131r. Yani, sadece fonksiyonunuz \u00e7al\u0131\u015ft\u0131\u011f\u0131nda kaynak t\u00fcketir ve \u00fccretlendirilirsiniz. Do\u011fum g\u00fcn\u00fc hat\u0131rlat\u0131c\u0131lar\u0131 gibi g\u00fcnde sadece bir kez \u00e7al\u0131\u015fan bir g\u00f6rev i\u00e7in bu model son derece ekonomiktir. Genellikle ilk birka\u00e7 y\u00fcz bin \u00e7a\u011fr\u0131 ve belirli bir GB-saniye (bellek <\/em> \u00e7al\u0131\u015fma s\u00fcresi) \u00fccretsizdir. Bu da ki\u015fisel veya k\u00fc\u00e7\u00fck \u00f6l\u00e7ekli kullan\u0131mlar i\u00e7in neredeyse s\u0131f\u0131r maliyet anlam\u0131na gelebilir.<br \/>\n*   <strong>DigitalOcean Managed Databases:<\/strong> Y\u00f6netilen veritabanlar\u0131, s\u00fcrekli \u00e7al\u0131\u015fan kaynaklar oldu\u011fu i\u00e7in Functions&#8217;tan daha y\u00fcksek bir maliyete sahiptir. Ancak, en k\u00fc\u00e7\u00fck planlar bile ayl\u0131k olarak olduk\u00e7a uygun fiyatl\u0131d\u0131r ve veritaban\u0131 y\u00f6netimi y\u00fck\u00fcn\u00fc \u00fczerinizden al\u0131r. K\u00fc\u00e7\u00fck bir veritaban\u0131 i\u00e7in ayl\u0131k birka\u00e7 dolardan ba\u015flayan fiyatlarla hizmet alabilirsiniz.<br \/>\n*   <strong>\u00dc\u00e7\u00fcnc\u00fc Taraf Servisler (SendGrid, Twilio vb.):<\/strong> \u00c7o\u011fu e-posta ve SMS sa\u011flay\u0131c\u0131s\u0131, belirli bir limit dahilinde \u00fccretsiz katmanlar sunar. \u00d6rne\u011fin, SendGrid ayda binlerce e-posta g\u00f6ndermenize \u00fccretsiz izin verir. Twilio ise deneme bakiyesi veya d\u00fc\u015f\u00fck maliyetli SMS paketleri sunar. Bu da ba\u015flang\u0131\u00e7 maliyetlerini minimumda tutar.<\/p>\n<p><strong>Genel Maliyet Etkinli\u011fi:<\/strong><br \/>\nBu sistemin toplam maliyeti, kullan\u0131lan veritaban\u0131 plan\u0131na ve \u00fc\u00e7\u00fcnc\u00fc taraf servislerin kullan\u0131m miktar\u0131na ba\u011fl\u0131 olacakt\u0131r. Ancak, ayl\u0131k birka\u00e7 dolarl\u0131k bir b\u00fct\u00e7eyle (hatta \u00fccretsiz katmanlarla daha da az) olduk\u00e7a g\u00fcvenilir ve otomatik bir do\u011fum g\u00fcn\u00fc hat\u0131rlat\u0131c\u0131 sistemine sahip olabilirsiniz. Droplet \u00fczerinde bir cron job \u00e7al\u0131\u015ft\u0131rmak, Droplet&#8217;in s\u00fcrekli \u00e7al\u0131\u015fmas\u0131 gerekti\u011fi i\u00e7in genellikle daha y\u00fcksek ayl\u0131k sabit maliyet anlam\u0131na gelir. Functions, bu t\u00fcr aral\u0131kl\u0131 g\u00f6revler i\u00e7in a\u00e7\u0131k ara daha uygun maliyetli bir \u00e7\u00f6z\u00fcmd\u00fcr.<\/p>\n<h2>Sonu\u00e7: Otomasyonla Hayat\u0131 Kolayla\u015ft\u0131rmak<\/h2>\n<p>Bu makalede, DigitalOcean&#8217;\u0131n g\u00fc\u00e7l\u00fc bulut hizmetlerini kullanarak g\u00fcnl\u00fck tetikleyicilerle otomatik do\u011fum g\u00fcn\u00fc hat\u0131rlat\u0131c\u0131lar\u0131 sisteminin nas\u0131l kurulaca\u011f\u0131n\u0131 ayr\u0131nt\u0131l\u0131 bir \u015fekilde inceledik. DigitalOcean Functions, Managed Databases ve \u00fc\u00e7\u00fcnc\u00fc taraf bildirim servislerinin entegrasyonu sayesinde, ki\u015fisel ili\u015fkilerimizi g\u00fc\u00e7lendiren ve hayat\u0131m\u0131z\u0131 kolayla\u015ft\u0131ran bir otomasyon \u00f6rne\u011fi olu\u015fturduk.<\/p>\n<p>G\u00f6rd\u00fc\u011f\u00fcm\u00fcz gibi, DigitalOcean&#8217;\u0131n sunucusuz mimarisi, bu t\u00fcr periyodik g\u00f6revler i\u00e7in son derece uygun maliyetli, \u00f6l\u00e7eklenebilir ve y\u00f6netimi kolay bir \u00e7\u00f6z\u00fcm sunuyor. Sunucu y\u00f6netimiyle u\u011fra\u015fmadan, sadece kodumuzu yazarak ve basit tetikleyiciler ayarlayarak karma\u015f\u0131k otomasyonlar\u0131 hayata ge\u00e7irebiliriz. Bu sistem, sadece do\u011fum g\u00fcnleri i\u00e7in de\u011fil, ayn\u0131 zamanda fatura hat\u0131rlat\u0131c\u0131lar\u0131, proje son tarih uyar\u0131lar\u0131 veya g\u00fcnl\u00fck rapor \u00f6zetleri gibi bir\u00e7ok di\u011fer periyodik g\u00f6rev i\u00e7in de temel te\u015fkil edebilir.<\/p>\n<p>Otomasyon, sadece i\u015f s\u00fcre\u00e7lerini h\u0131zland\u0131rmakla kalmaz, ayn\u0131 zamanda g\u00fcnl\u00fck hayat\u0131m\u0131zdaki k\u00fc\u00e7\u00fck ama \u00f6nemli detaylar\u0131 da y\u00f6netmemize yard\u0131mc\u0131 olarak zihinsel y\u00fck\u00fcm\u00fcz\u00fc azalt\u0131r. DigitalOcean&#8217;\u0131n esnek ve kapsaml\u0131 ara\u00e7 setiyle, yarat\u0131c\u0131l\u0131\u011f\u0131n\u0131z\u0131n s\u0131n\u0131rlar\u0131n\u0131 zorlayabilir ve hayat\u0131n\u0131z\u0131 daha verimli hale getirecek say\u0131s\u0131z \u00e7\u00f6z\u00fcm\u00fc hayata ge\u00e7irebilirsiniz. Unutulan do\u011fum g\u00fcnleri art\u0131k ge\u00e7mi\u015fte kald\u0131; gelecekte ise otomasyonun getirdi\u011fi huzur ve kolayl\u0131k var.<\/body><\/p>\n","protected":false},"excerpt":{"rendered":"12 Days of DigitalOcean (Day 5) &#8211; G\u00fcnl\u00fck Tetikleyicilerle Do\u011fum G\u00fcn\u00fc Hat\u0131rlat\u0131c\u0131lar\u0131n\u0131 Otomatikle\u015ftirme\nGiri\u015f: Unutulan Do\u011fum G\u00fcnlerine","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"csco_page_header_type":"","csco_page_load_nextpost":"","csco_page_subscribe_form":"","csco_page_contact_form":"","footnotes":""},"categories":[1401],"tags":[],"class_list":{"0":"post-38848","1":"post","2":"type-post","3":"status-publish","4":"format-standard","6":"category-git","7":"cs-entry","8":"cs-video-wrap"},"yoast_head":"<!-- This site is optimized with the Yoast SEO Premium plugin v20.5 (Yoast SEO v25.3.1) - https:\/\/yoast.com\/wordpress\/plugins\/seo\/ -->\n<title>12 Days of DigitalOcean (Day 5) - G\u00fcnl\u00fck Tetikleyicilerle Do\u011fum G\u00fcn\u00fc Hat\u0131rlat\u0131c\u0131lar\u0131n\u0131 Otomatikle\u015ftirme - Kodlar\u0131n Gizemli D\u00fcnyas\u0131<\/title>\n<meta name=\"robots\" content=\"index, follow, max-snippet:-1, max-image-preview:large, max-video-preview:-1\" \/>\n<link rel=\"canonical\" href=\"https:\/\/fatihsoysal.com\/blog\/12-days-of-digitalocean-day-5-gunluk-tetikleyicilerle-dogum-gunu-hatirlaticilarini-otomatiklestirme\/\" \/>\n<meta property=\"og:locale\" content=\"tr_TR\" \/>\n<meta property=\"og:type\" content=\"article\" \/>\n<meta property=\"og:title\" content=\"12 Days of DigitalOcean (Day 5) - G\u00fcnl\u00fck Tetikleyicilerle Do\u011fum G\u00fcn\u00fc Hat\u0131rlat\u0131c\u0131lar\u0131n\u0131 Otomatikle\u015ftirme\" \/>\n<meta property=\"og:description\" content=\"12 Days of DigitalOcean (Day 5) - G\u00fcnl\u00fck Tetikleyicilerle Do\u011fum G\u00fcn\u00fc Hat\u0131rlat\u0131c\u0131lar\u0131n\u0131 Otomatikle\u015ftirme Giri\u015f: Unutulan Do\u011fum G\u00fcnlerine\" \/>\n<meta property=\"og:url\" content=\"https:\/\/fatihsoysal.com\/blog\/12-days-of-digitalocean-day-5-gunluk-tetikleyicilerle-dogum-gunu-hatirlaticilarini-otomatiklestirme\/\" \/>\n<meta property=\"og:site_name\" content=\"Kodlar\u0131n Gizemli D\u00fcnyas\u0131\" \/>\n<meta property=\"article:published_time\" content=\"2026-02-08T19:40:54+00:00\" \/>\n<meta name=\"author\" content=\"Fatih Soysal\" \/>\n<meta name=\"twitter:card\" content=\"summary_large_image\" \/>\n<meta name=\"twitter:label1\" content=\"Yazan:\" \/>\n\t<meta name=\"twitter:data1\" content=\"Fatih Soysal\" \/>\n\t<meta name=\"twitter:label2\" content=\"Tahmini okuma s\u00fcresi\" \/>\n\t<meta name=\"twitter:data2\" content=\"24 dakika\" \/>\n<script type=\"application\/ld+json\" class=\"yoast-schema-graph\">{\"@context\":\"https:\/\/schema.org\",\"@graph\":[{\"@type\":\"Article\",\"@id\":\"https:\/\/fatihsoysal.com\/blog\/12-days-of-digitalocean-day-5-gunluk-tetikleyicilerle-dogum-gunu-hatirlaticilarini-otomatiklestirme\/#article\",\"isPartOf\":{\"@id\":\"https:\/\/fatihsoysal.com\/blog\/12-days-of-digitalocean-day-5-gunluk-tetikleyicilerle-dogum-gunu-hatirlaticilarini-otomatiklestirme\/\"},\"author\":{\"name\":\"Fatih Soysal\",\"@id\":\"https:\/\/fatihsoysal.com\/blog\/#\/schema\/person\/002a254750921dcfd568a99e48240dd1\"},\"headline\":\"12 Days of DigitalOcean (Day 5) &#8211; G\u00fcnl\u00fck Tetikleyicilerle Do\u011fum G\u00fcn\u00fc Hat\u0131rlat\u0131c\u0131lar\u0131n\u0131 Otomatikle\u015ftirme\",\"datePublished\":\"2026-02-08T19:40:54+00:00\",\"mainEntityOfPage\":{\"@id\":\"https:\/\/fatihsoysal.com\/blog\/12-days-of-digitalocean-day-5-gunluk-tetikleyicilerle-dogum-gunu-hatirlaticilarini-otomatiklestirme\/\"},\"wordCount\":4058,\"commentCount\":0,\"publisher\":{\"@id\":\"https:\/\/fatihsoysal.com\/blog\/#\/schema\/person\/002a254750921dcfd568a99e48240dd1\"},\"articleSection\":[\"Git\"],\"inLanguage\":\"tr\",\"potentialAction\":[{\"@type\":\"CommentAction\",\"name\":\"Comment\",\"target\":[\"https:\/\/fatihsoysal.com\/blog\/12-days-of-digitalocean-day-5-gunluk-tetikleyicilerle-dogum-gunu-hatirlaticilarini-otomatiklestirme\/#respond\"]}],\"copyrightYear\":\"2026\",\"copyrightHolder\":{\"@id\":\"https:\/\/fatihsoysal.com\/blog\/#organization\"}},{\"@type\":\"WebPage\",\"@id\":\"https:\/\/fatihsoysal.com\/blog\/12-days-of-digitalocean-day-5-gunluk-tetikleyicilerle-dogum-gunu-hatirlaticilarini-otomatiklestirme\/\",\"url\":\"https:\/\/fatihsoysal.com\/blog\/12-days-of-digitalocean-day-5-gunluk-tetikleyicilerle-dogum-gunu-hatirlaticilarini-otomatiklestirme\/\",\"name\":\"12 Days of DigitalOcean (Day 5) - G\u00fcnl\u00fck Tetikleyicilerle Do\u011fum G\u00fcn\u00fc Hat\u0131rlat\u0131c\u0131lar\u0131n\u0131 Otomatikle\u015ftirme - Kodlar\u0131n Gizemli D\u00fcnyas\u0131\",\"isPartOf\":{\"@id\":\"https:\/\/fatihsoysal.com\/blog\/#website\"},\"datePublished\":\"2026-02-08T19:40:54+00:00\",\"breadcrumb\":{\"@id\":\"https:\/\/fatihsoysal.com\/blog\/12-days-of-digitalocean-day-5-gunluk-tetikleyicilerle-dogum-gunu-hatirlaticilarini-otomatiklestirme\/#breadcrumb\"},\"inLanguage\":\"tr\",\"potentialAction\":[{\"@type\":\"ReadAction\",\"target\":[\"https:\/\/fatihsoysal.com\/blog\/12-days-of-digitalocean-day-5-gunluk-tetikleyicilerle-dogum-gunu-hatirlaticilarini-otomatiklestirme\/\"]}]},{\"@type\":\"BreadcrumbList\",\"@id\":\"https:\/\/fatihsoysal.com\/blog\/12-days-of-digitalocean-day-5-gunluk-tetikleyicilerle-dogum-gunu-hatirlaticilarini-otomatiklestirme\/#breadcrumb\",\"itemListElement\":[{\"@type\":\"ListItem\",\"position\":1,\"name\":\"Anasayfa\",\"item\":\"https:\/\/fatihsoysal.com\/blog\/\"},{\"@type\":\"ListItem\",\"position\":2,\"name\":\"12 Days of DigitalOcean (Day 5) &#8211; G\u00fcnl\u00fck Tetikleyicilerle Do\u011fum G\u00fcn\u00fc Hat\u0131rlat\u0131c\u0131lar\u0131n\u0131 Otomatikle\u015ftirme\"}]},{\"@type\":\"WebSite\",\"@id\":\"https:\/\/fatihsoysal.com\/blog\/#website\",\"url\":\"https:\/\/fatihsoysal.com\/blog\/\",\"name\":\"Fatihsoysal.com\",\"description\":\"Blog - Yaz\u0131l\u0131m D\u00fcnyas\u0131 Tecr\u00fcbelerim\",\"publisher\":{\"@id\":\"https:\/\/fatihsoysal.com\/blog\/#\/schema\/person\/002a254750921dcfd568a99e48240dd1\"},\"potentialAction\":[{\"@type\":\"SearchAction\",\"target\":{\"@type\":\"EntryPoint\",\"urlTemplate\":\"https:\/\/fatihsoysal.com\/blog\/?s={search_term_string}\"},\"query-input\":{\"@type\":\"PropertyValueSpecification\",\"valueRequired\":true,\"valueName\":\"search_term_string\"}}],\"inLanguage\":\"tr\"},{\"@type\":[\"Person\",\"Organization\"],\"@id\":\"https:\/\/fatihsoysal.com\/blog\/#\/schema\/person\/002a254750921dcfd568a99e48240dd1\",\"name\":\"Fatih Soysal\",\"image\":{\"@type\":\"ImageObject\",\"inLanguage\":\"tr\",\"@id\":\"https:\/\/fatihsoysal.com\/blog\/#\/schema\/person\/image\/\",\"url\":\"https:\/\/fatihsoysal.com\/blog\/wp-content\/uploads\/2024\/04\/cropped-replicate-prediction-3kgg1hgjn5rgp0cf0p5tr0jw7w-1.png\",\"contentUrl\":\"https:\/\/fatihsoysal.com\/blog\/wp-content\/uploads\/2024\/04\/cropped-replicate-prediction-3kgg1hgjn5rgp0cf0p5tr0jw7w-1.png\",\"width\":512,\"height\":512,\"caption\":\"Fatih Soysal\"},\"logo\":{\"@id\":\"https:\/\/fatihsoysal.com\/blog\/#\/schema\/person\/image\/\"},\"description\":\"Kullan\u0131m ve kodlama m\u00fckemmeliyetini odak alan uygulamalar olu\u015fturma deneyimine sahip, profesyonel olarak 15+ y\u0131l \u00fczeri deneyime sahip bir yaz\u0131l\u0131m m\u00fchendisi.\",\"url\":\"https:\/\/fatihsoysal.com\/blog\/author\/fatihsoysal\/\"}]}<\/script>\n<!-- \/ Yoast SEO Premium plugin. -->","yoast_head_json":{"title":"12 Days of DigitalOcean (Day 5) - G\u00fcnl\u00fck Tetikleyicilerle Do\u011fum G\u00fcn\u00fc Hat\u0131rlat\u0131c\u0131lar\u0131n\u0131 Otomatikle\u015ftirme - Kodlar\u0131n Gizemli D\u00fcnyas\u0131","robots":{"index":"index","follow":"follow","max-snippet":"max-snippet:-1","max-image-preview":"max-image-preview:large","max-video-preview":"max-video-preview:-1"},"canonical":"https:\/\/fatihsoysal.com\/blog\/12-days-of-digitalocean-day-5-gunluk-tetikleyicilerle-dogum-gunu-hatirlaticilarini-otomatiklestirme\/","og_locale":"tr_TR","og_type":"article","og_title":"12 Days of DigitalOcean (Day 5) - G\u00fcnl\u00fck Tetikleyicilerle Do\u011fum G\u00fcn\u00fc Hat\u0131rlat\u0131c\u0131lar\u0131n\u0131 Otomatikle\u015ftirme","og_description":"12 Days of DigitalOcean (Day 5) - G\u00fcnl\u00fck Tetikleyicilerle Do\u011fum G\u00fcn\u00fc Hat\u0131rlat\u0131c\u0131lar\u0131n\u0131 Otomatikle\u015ftirme Giri\u015f: Unutulan Do\u011fum G\u00fcnlerine","og_url":"https:\/\/fatihsoysal.com\/blog\/12-days-of-digitalocean-day-5-gunluk-tetikleyicilerle-dogum-gunu-hatirlaticilarini-otomatiklestirme\/","og_site_name":"Kodlar\u0131n Gizemli D\u00fcnyas\u0131","article_published_time":"2026-02-08T19:40:54+00:00","author":"Fatih Soysal","twitter_card":"summary_large_image","twitter_misc":{"Yazan:":"Fatih Soysal","Tahmini okuma s\u00fcresi":"24 dakika"},"schema":{"@context":"https:\/\/schema.org","@graph":[{"@type":"Article","@id":"https:\/\/fatihsoysal.com\/blog\/12-days-of-digitalocean-day-5-gunluk-tetikleyicilerle-dogum-gunu-hatirlaticilarini-otomatiklestirme\/#article","isPartOf":{"@id":"https:\/\/fatihsoysal.com\/blog\/12-days-of-digitalocean-day-5-gunluk-tetikleyicilerle-dogum-gunu-hatirlaticilarini-otomatiklestirme\/"},"author":{"name":"Fatih Soysal","@id":"https:\/\/fatihsoysal.com\/blog\/#\/schema\/person\/002a254750921dcfd568a99e48240dd1"},"headline":"12 Days of DigitalOcean (Day 5) &#8211; G\u00fcnl\u00fck Tetikleyicilerle Do\u011fum G\u00fcn\u00fc Hat\u0131rlat\u0131c\u0131lar\u0131n\u0131 Otomatikle\u015ftirme","datePublished":"2026-02-08T19:40:54+00:00","mainEntityOfPage":{"@id":"https:\/\/fatihsoysal.com\/blog\/12-days-of-digitalocean-day-5-gunluk-tetikleyicilerle-dogum-gunu-hatirlaticilarini-otomatiklestirme\/"},"wordCount":4058,"commentCount":0,"publisher":{"@id":"https:\/\/fatihsoysal.com\/blog\/#\/schema\/person\/002a254750921dcfd568a99e48240dd1"},"articleSection":["Git"],"inLanguage":"tr","potentialAction":[{"@type":"CommentAction","name":"Comment","target":["https:\/\/fatihsoysal.com\/blog\/12-days-of-digitalocean-day-5-gunluk-tetikleyicilerle-dogum-gunu-hatirlaticilarini-otomatiklestirme\/#respond"]}],"copyrightYear":"2026","copyrightHolder":{"@id":"https:\/\/fatihsoysal.com\/blog\/#organization"}},{"@type":"WebPage","@id":"https:\/\/fatihsoysal.com\/blog\/12-days-of-digitalocean-day-5-gunluk-tetikleyicilerle-dogum-gunu-hatirlaticilarini-otomatiklestirme\/","url":"https:\/\/fatihsoysal.com\/blog\/12-days-of-digitalocean-day-5-gunluk-tetikleyicilerle-dogum-gunu-hatirlaticilarini-otomatiklestirme\/","name":"12 Days of DigitalOcean (Day 5) - G\u00fcnl\u00fck Tetikleyicilerle Do\u011fum G\u00fcn\u00fc Hat\u0131rlat\u0131c\u0131lar\u0131n\u0131 Otomatikle\u015ftirme - Kodlar\u0131n Gizemli D\u00fcnyas\u0131","isPartOf":{"@id":"https:\/\/fatihsoysal.com\/blog\/#website"},"datePublished":"2026-02-08T19:40:54+00:00","breadcrumb":{"@id":"https:\/\/fatihsoysal.com\/blog\/12-days-of-digitalocean-day-5-gunluk-tetikleyicilerle-dogum-gunu-hatirlaticilarini-otomatiklestirme\/#breadcrumb"},"inLanguage":"tr","potentialAction":[{"@type":"ReadAction","target":["https:\/\/fatihsoysal.com\/blog\/12-days-of-digitalocean-day-5-gunluk-tetikleyicilerle-dogum-gunu-hatirlaticilarini-otomatiklestirme\/"]}]},{"@type":"BreadcrumbList","@id":"https:\/\/fatihsoysal.com\/blog\/12-days-of-digitalocean-day-5-gunluk-tetikleyicilerle-dogum-gunu-hatirlaticilarini-otomatiklestirme\/#breadcrumb","itemListElement":[{"@type":"ListItem","position":1,"name":"Anasayfa","item":"https:\/\/fatihsoysal.com\/blog\/"},{"@type":"ListItem","position":2,"name":"12 Days of DigitalOcean (Day 5) &#8211; G\u00fcnl\u00fck Tetikleyicilerle Do\u011fum G\u00fcn\u00fc Hat\u0131rlat\u0131c\u0131lar\u0131n\u0131 Otomatikle\u015ftirme"}]},{"@type":"WebSite","@id":"https:\/\/fatihsoysal.com\/blog\/#website","url":"https:\/\/fatihsoysal.com\/blog\/","name":"Fatihsoysal.com","description":"Blog - Yaz\u0131l\u0131m D\u00fcnyas\u0131 Tecr\u00fcbelerim","publisher":{"@id":"https:\/\/fatihsoysal.com\/blog\/#\/schema\/person\/002a254750921dcfd568a99e48240dd1"},"potentialAction":[{"@type":"SearchAction","target":{"@type":"EntryPoint","urlTemplate":"https:\/\/fatihsoysal.com\/blog\/?s={search_term_string}"},"query-input":{"@type":"PropertyValueSpecification","valueRequired":true,"valueName":"search_term_string"}}],"inLanguage":"tr"},{"@type":["Person","Organization"],"@id":"https:\/\/fatihsoysal.com\/blog\/#\/schema\/person\/002a254750921dcfd568a99e48240dd1","name":"Fatih Soysal","image":{"@type":"ImageObject","inLanguage":"tr","@id":"https:\/\/fatihsoysal.com\/blog\/#\/schema\/person\/image\/","url":"https:\/\/fatihsoysal.com\/blog\/wp-content\/uploads\/2024\/04\/cropped-replicate-prediction-3kgg1hgjn5rgp0cf0p5tr0jw7w-1.png","contentUrl":"https:\/\/fatihsoysal.com\/blog\/wp-content\/uploads\/2024\/04\/cropped-replicate-prediction-3kgg1hgjn5rgp0cf0p5tr0jw7w-1.png","width":512,"height":512,"caption":"Fatih Soysal"},"logo":{"@id":"https:\/\/fatihsoysal.com\/blog\/#\/schema\/person\/image\/"},"description":"Kullan\u0131m ve kodlama m\u00fckemmeliyetini odak alan uygulamalar olu\u015fturma deneyimine sahip, profesyonel olarak 15+ y\u0131l \u00fczeri deneyime sahip bir yaz\u0131l\u0131m m\u00fchendisi.","url":"https:\/\/fatihsoysal.com\/blog\/author\/fatihsoysal\/"}]}},"yoast_meta":{"yoast_wpseo_title":"","yoast_wpseo_metadesc":"","yoast_wpseo_canonical":""},"amp_enabled":true,"_links":{"self":[{"href":"https:\/\/fatihsoysal.com\/blog\/wp-json\/wp\/v2\/posts\/38848","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/fatihsoysal.com\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/fatihsoysal.com\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/fatihsoysal.com\/blog\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/fatihsoysal.com\/blog\/wp-json\/wp\/v2\/comments?post=38848"}],"version-history":[{"count":1,"href":"https:\/\/fatihsoysal.com\/blog\/wp-json\/wp\/v2\/posts\/38848\/revisions"}],"predecessor-version":[{"id":38849,"href":"https:\/\/fatihsoysal.com\/blog\/wp-json\/wp\/v2\/posts\/38848\/revisions\/38849"}],"wp:attachment":[{"href":"https:\/\/fatihsoysal.com\/blog\/wp-json\/wp\/v2\/media?parent=38848"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/fatihsoysal.com\/blog\/wp-json\/wp\/v2\/categories?post=38848"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/fatihsoysal.com\/blog\/wp-json\/wp\/v2\/tags?post=38848"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}