Uygulamalarınızda uzun süren işlemleri, karmaşık iş akışlarını veya zamana bağlı görevleri yönetmek zorlu bir süreç olabilir. Geleneksel yöntemlerle bu tür arka plan işlerini ve olayları ele almak, genellikle yüksek maliyetli altyapılar, sürekli bakım gerektiren kuyruk sistemleri ve hataya dayanıklılık konusunda ciddi endişeler yaratır. Peki, bu zorlukların üstesinden gelerek uygulamalarınızı daha güvenilir, ölçeklenebilir ve geliştirici dostu hale getirmenin kolay bir yolu var mı? Bu makalede, modern bir arka plan işi ve olay yönetimi platformu olan Inngest’in bu sorunlara nasıl çözüm getirdiğini ve geliştirme sürecinizi nasıl basitleştirdiğini adım adım inceleyeceğiz.
Arka Plan İşleri ve Olay Yönetimi Neden Bu Kadar Zor?
Modern web uygulamaları, kullanıcıya anında yanıt verirken aynı zamanda arka planda birçok yoğun işlemi yürütmek zorundadır. Örneğin, bir e-ticaret sitesinde sipariş onaylandıktan sonra stok güncellemeleri, ödeme işlemleri, e-posta bildirimleri, fatura oluşturma ve kargo entegrasyonları gibi bir dizi asenkron görev devreye girer. Bu görevlerin doğrudan kullanıcı isteği sırasında yapılması, sayfa yükleme sürelerini uzatır, kullanıcı deneyimini kötüleştirir ve hatta sunucunun çökmesine neden olabilir.
Geleneksel olarak, bu tür arka plan işleri genellikle mesaj kuyrukları (RabbitMQ, Kafka, SQS), zamanlanmış görevler (cron jobs) veya özel işçi süreçleri (worker processes) kullanılarak yönetilir. Ancak bu çözümlerin her biri kendine özgü karmaşıklıklarla birlikte gelir:
- Altyapı Yönetimi: Mesaj kuyruklarını kurmak, yapılandırmak, izlemek ve ölçeklendirmek ciddi bir DevOps yükü getirir. Sunucuların bakımı, güncellemeler ve yedeklemeler sürekli dikkat gerektirir.
- Hata Yönetimi ve Yeniden Denemeler: Arka plan işleri başarısız olabilir. Ağ kesintileri, API limitleri veya geçici veritabanı sorunları gibi nedenlerle bir görevin yeniden denenmesi gerekebilir. Bu yeniden deneme mekanizmalarını (exponential backoff dahil) manuel olarak uygulamak hataya açık ve zaman alıcıdır.
- İş Akışı Koordinasyonu: Birden fazla adım içeren karmaşık iş akışlarında, adımların sırasını, bağımlılıklarını ve olası başarısızlık durumlarını koordine etmek oldukça zordur. Örneğin, bir video yükleme işleminde önce dönüştürme, sonra küçük resim oluşturma ve ardından bildirim gönderme adımları vardır. Bir adım başarısız olursa, tüm akışın nasıl ele alınacağı kritik bir konudur.
- Ölçeklenebilirlik: Yüksek trafik durumlarında arka plan işlerinin sorunsuz bir şekilde ölçeklenmesi gerekir. İş yükü arttığında ek kaynakların otomatik olarak tahsis edilmesi, işlerin gecikmeden işlenmesini sağlar. Bu otomatik ölçeklendirme yeteneğini kendi başınıza kurmak karmaşıktır.
- Geliştirici Deneyimi: Tüm bu altyapı detayları, geliştiricilerin ana iş mantığına odaklanmasını engeller. İş mantığını yazmak yerine, altyapı kodlarıyla boğuşmak zorunda kalırlar.
Bu zorluklar, özellikle hızla büyüyen veya sürekli değişen uygulamalar için ciddi operasyonel yük ve geliştirme gecikmeleri anlamına gelir. İşte tam bu noktada Inngest gibi modern, sunucusuz (serverless) ve olay odaklı (event-driven) bir platform devreye girerek bu karmaşıklığı önemli ölçüde azaltır ve geliştiricilerin daha verimli olmasını sağlar.
Inngest Nedir ve Temel Kavramları Nelerdir?
Inngest, geliştiricilerin karmaşık arka plan işlerini ve olay odaklı iş akışlarını kolayca oluşturmasını, dağıtmasını ve yönetmesini sağlayan bir sunucusuz platformdur. Temelinde, uygulamanızdan gelen olaylara (events) tepki veren ve bu olaylar üzerinden iş mantığını yürüten “fonksiyonlar” (functions) yatar. Inngest, kuyruk sistemlerinin, zamanlayıcıların ve hata yönetiminin tüm karmaşıklığını soyutlayarak, geliştiricilerin sadece iş mantığına odaklanmasına olanak tanır.
Peki, Inngest’i diğer çözümlerden ayıran ve bu kadar güçlü kılan temel kavramlar nelerdir?
- Olaylar (Events): Inngest’in kalbinde olaylar bulunur. Uygulamanızda meydana gelen her şey bir olay olarak temsil edilebilir:
user.signed.up,order.created,video.uploadedgibi. Bu olaylar, Inngest’e gönderilir ve tanımladığınız fonksiyonları tetikler. Olaylar, basit JSON objeleridir ve herhangi bir veri içerebilir. - Fonksiyonlar (Functions): Inngest fonksiyonları, belirli olaylara yanıt olarak çalışan kod parçalarıdır. Bu fonksiyonlar, uzun süren işlemleri, API çağrılarını, veritabanı güncellemelerini veya diğer arka plan görevlerini gerçekleştirebilir. Bir Inngest fonksiyonu, birden fazla adımdan oluşabilir ve bu adımlar sırayla veya paralel olarak yürütülebilir.
- Tetikleyiciler (Triggers): Bir Inngest fonksiyonunun ne zaman çalışacağını belirleyen mekanizmalardır. En yaygın tetikleyici türü bir olaydır (
event). Ancak belirli bir zaman diliminde düzenli olarak çalışan zamanlanmış tetikleyiciler (cron) veya harici bir webhook çağrısı (webhook) da kullanılabilir. - Adımlar (Steps): Karmaşık bir iş akışı genellikle birden fazla adımdan oluşur. Inngest fonksiyonları içinde
stepnesnesini kullanarak bu adımları tanımlarsınız. Her adım, kendi başına bir işlem gerçekleştirebilir ve bir sonraki adıma veri aktarabilir.step.run(),step.sleep(),step.waitForEvent()gibi metotlarla iş akışını kontrol edersiniz. Bu adımlar, otomatik olarak yeniden deneme, hata yönetimi ve durum takibi özelliklerine sahiptir. - Yeniden Denemeler (Retries): Inngest, fonksiyonlarınızın veya adımlarınızın başarısız olması durumunda otomatik yeniden deneme mekanizmalarına sahiptir. Gecikmeli yeniden denemeler (exponential backoff) varsayılan olarak gelir ve geçici hataların üstesinden gelmeye yardımcı olur. Bu, uygulamanızın daha dayanıklı olmasını sağlar.
- Durum Yönetimi (State Management): Inngest, her fonksiyonun durumunu otomatik olarak yönetir. Bir fonksiyonun birden fazla adım arasında geçiş yaparken veya başarısız olup yeniden denendiğinde, durumunu korur. Bu sayede geliştiricilerin karmaşık durum yönetimi mantığı yazmasına gerek kalmaz.
- Gözlemlenebilirlik (Observability): Inngest kontrol paneli, tüm olayları, fonksiyon yürütmelerini ve iş akışlarını gerçek zamanlı olarak izlemenizi sağlar. Başarılı/başarısız durumlar, süreler, loglar ve hatalar kolayca görüntülenebilir. Bu, sorun giderme ve performans izleme için hayati önem taşır.
Kısacası, Inngest, modern bir uygulamanın arka plan işi ihtiyaçlarını uçtan uca karşılayan, geliştirici dostu, ölçeklenebilir ve hataya dayanıklı bir platform sunar. Geliştiriciler, sunucu veya kuyruk yönetimiyle uğraşmak yerine, sadece iş mantıklarına odaklanabilir ve uygulamalarını daha hızlı bir şekilde pazara sunabilirler. Ayrıca, serverless yapısı sayesinde sadece kullandığınız kadar ödeme yaparak maliyetleri optimize edebilirsiniz. Bu, özellikle startup’lar ve hızla büyüyen şirketler için büyük bir avantajdır.
Inngest ile İlk Arka Plan İşinizi Nasıl Oluşturursunuz?
Inngest ile bir arka plan işi oluşturmak oldukça basittir. Süreci adım adım inceleyelim ve bir e-posta gönderme örneği üzerinden ilerleyelim. Amacımız, user.signed.up olayı tetiklendiğinde kullanıcıya hoş geldin e-postası göndermek.
1. Inngest Projenizi Kurmak
Öncelikle, projenize Inngest kütüphanesini eklemeniz gerekiyor. Genellikle Node.js/TypeScript ortamında kullanılır, ancak Python ve Go SDK’ları da mevcuttur. Terminalinizde aşağıdaki komutu çalıştırarak başlayın:
npm install inngest
# veya
yarn add inngest
Ardından, Inngest istemcisini (client) ve fonksiyonunuzu tanımlayacağınız bir dosya oluşturun. Örneğin, ./inngest/client.ts ve ./inngest/functions.ts.
2. Inngest İstemcisini Tanımlama
./inngest/client.ts dosyanızda Inngest istemcinizi başlatın. Bu istemci, olayları göndermek ve fonksiyonları tanımlamak için kullanılacaktır.
// ./inngest/client.ts
import { Inngest } from "inngest";
export const inngest = new Inngest({ name: "My Awesome App" });
Burada name parametresi, Inngest kontrol panelinde uygulamanızı tanımlamak için kullanılır. Bu basit kurulumla, Inngest’in temelini atmış oluyoruz.
3. İlk Inngest Fonksiyonunuzu Oluşturma
Şimdi, user.signed.up olayına yanıt verecek bir fonksiyon tanımlayalım. Bu fonksiyon, yeni kaydolan bir kullanıcıya hoş geldin e-postası gönderme işlemini simüle edecek. ./inngest/functions.ts dosyanızı açın ve aşağıdaki kodu ekleyin:
// ./inngest/functions.ts
import { inngest } from "./client";
export const sendWelcomeEmail = inngest.createFunction(
{ id: "send-welcome-email" }, // Fonksiyon için benzersiz bir ID
{ event: "user.signed.up" }, // Bu fonksiyonu tetikleyecek olay
async ({ event, step }) => {
// Adım 1: E-posta gönderme işlemini simüle et
await step.run("send-email-via-provider", async () => {
console.log(Kullanıcıya hoş geldin e-postası gönderiliyor: ${event.data.email});
// Gerçek bir e-posta gönderme servisi (SendGrid, Nodemailer vb.) burada kullanılabilir
// Örneğin: await emailService.send(event.data.email, "Hoş Geldiniz!", "Merhaba...");
return { success: true, message: "E-posta başarıyla gönderildi." };
});
// Adım 2: Loglama veya başka bir işlem
await step.run("log-email-sent", async () => {
console.log(E-posta gönderme işlemi ${event.data.email} için tamamlandı.);
});
return { message: Hoş geldin e-postası ${event.data.email} adresine gönderildi. };
}
);
Bu kodda:
id: "send-welcome-email": Bu, Inngest kontrol panelinde fonksiyonunuzu tanımlayan benzersiz bir kimliktir.event: "user.signed.up": Bu kısım, fonksiyonun ne zaman tetikleneceğini belirtir. Ne zamanuser.signed.upolayı Inngest’e gönderilirse, bu fonksiyon çalışacaktır.async ({ event, step }) => { ... }: Fonksiyonun ana mantığını içeren asenkron bir fonksiyondur.event: Tetikleyen olayın tüm verilerini içerir (örneğin,event.data.email).step: Fonksiyon içindeki adımları yönetmek için kullanılır.step.run()ile uzun süreli veya potansiyel olarak başarısız olabilecek işlemleri güvenli bir şekilde yürütebilirsiniz. Inngest, bu adımların durumunu yönetir ve gerekirse otomatik olarak yeniden dener.
4. Inngest Fonksiyonlarını Bir API Rotasında Tanımlama
Inngest’in fonksiyonlarınızı keşfedip çalıştırması için, uygulamanızda bir API rotası (örneğin, Next.js API rotası, Express rotası) tanımlamanız gerekir. Bu rota, Inngest sunucusu ile uygulamanız arasında bir köprü görevi görür.
// Next.js API rotası örneği: pages/api/inngest.ts
import { serve } from "inngest/next";
import { inngest } from "../../inngest/client";
import { sendWelcomeEmail } from "../../inngest/functions";
export default serve({
client: inngest,
functions: [sendWelcomeEmail],
});
Bu rota, Inngest’in fonksiyonlarınızı keşfetmesini ve olaylar tetiklendiğinde çalıştırmasını sağlar. Uygulamanızın çalıştığı sunucuda bu API rotasının erişilebilir olması önemlidir.
5. Bir Olayı Tetikleme
Son olarak, user.signed.up olayını tetikleyelim. Bu, uygulamanızın herhangi bir yerinden (örneğin, bir kullanıcı kayıt olduğunda) yapılabilir:
// Kullanıcı kaydolduğunda bu kodu çalıştırın
import { inngest } from "./inngest/client";
async function registerUser(email: string, name: string) {
// Kullanıcıyı veritabanına kaydetme vb. işlemler...
console.log(${email} adresi ile yeni kullanıcı kaydoldu.);
// Inngest'e bir olay gönder
await inngest.send({
name: "user.signed.up", // Fonksiyonun dinlediği olay adı
data: { email, name }, // Olayla birlikte gönderilecek veriler
user: { email }, // Opsiyonel: Kontrol panelinde kullanıcıyı ilişkilendirmek için
});
console.log("Hoş geldin e-postası olayı Inngest'e gönderildi.");
}
// Örnek kullanım
registerUser("user@example.com", "John Doe");
Bu kod çalıştırıldığında, user.signed.up olayı Inngest’e gönderilecek ve sendWelcomeEmail fonksiyonunuz tetiklenecektir. Inngest kontrol panelinde bu olayın ve fonksiyonun yürütme durumunu, loglarını ve başarılı olup olmadığını gerçek zamanlı olarak görebilirsiniz. Bu sayede, arka plan işlerinizi geliştirirken hızlı geri bildirim alabilir ve sorunları kolayca teşhis edebilirsiniz.
step.run() kullanmak, kodunuzun hataya dayanıklı olmasını sağlar. Bir adım başarısız olursa, Inngest otomatik olarak yeniden dener ve bu sayede geçici ağ sorunları veya API kesintileri gibi durumların üstesinden gelirsiniz. Bu, manuel yeniden deneme mantığı yazma yükünü ortadan kaldırır.
Karmaşık İş Akışları ve Olay Zincirleri Nasıl Yönetilir?
Inngest’in gerçek gücü, sadece basit arka plan işlerini değil, aynı zamanda birden fazla adımdan oluşan karmaşık iş akışlarını ve olay zincirlerini kolayca yönetebilmesinde yatar. Uygulamalarınızda sıkça karşılaşılan “bir şey olduğunda, başka bir şey yap, sonra bir süre bekle ve üçüncü bir şeyi tetikle” gibi senaryoları Inngest ile sorunsuz bir şekilde modelleyebilirsiniz.
Çok Adımlı Fonksiyonlar ve Durum Yönetimi
Inngest fonksiyonları içindeki step nesnesi, iş akışınızı adım adım inşa etmenizi sağlar. Her step.run() çağrısı, Inngest tarafından izlenen ve yönetilen ayrı bir işlemdir. Bu adımlar arasında veri aktarımı yapabilir, bekleme süreleri tanımlayabilir veya hatta başka olayları tetikleyebilirsiniz.
Örneğin, bir e-ticaret uygulamasında “sipariş işleme” sürecini düşünelim:
- Sipariş oluşturulduğunda.
- Stok güncellenmeli.
- Müşteriye sipariş onayı e-postası gönderilmeli.
- Ödeme işlenmeli.
- Fatura oluşturulmalı.
- Kargo entegrasyonuna bilgi gönderilmeli.
Bu adımların her biri uzun sürebilir ve bağımsız olarak başarısız olabilir. Inngest ile bu süreci nasıl modelleyebiliriz?
// ./inngest/functions.ts
import { inngest } from "./client";
export const processOrder = inngest.createFunction(
{ id: "process-order" },
{ event: "order.created" },
async ({ event, step }) => {
const order = event.data.order;
// Adım 1: Stok güncelleme
const stockUpdateResult = await step.run("update-inventory", async () => {
console.log(Sipariş ${order.id} için stok güncelleniyor...);
// Gerçek bir stok güncelleme API çağrısı
// await inventoryService.updateStock(order.items);
return { success: true, message: "Stok başarıyla güncellendi." };
});
if (!stockUpdateResult.success) {
throw new Error("Stok güncellenemedi, sipariş iptal ediliyor.");
}
// Adım 2: Müşteriye onay e-postası gönder
await step.run("send-order-confirmation-email", async () => {
console.log(Sipariş ${order.id} için onay e-postası gönderiliyor: ${order.customerEmail});
// await emailService.sendConfirmation(order);
});
// Adım 3: Ödeme işleme
const paymentResult = await step.run("process-payment", async () => {
console.log(Sipariş ${order.id} için ödeme işleniyor...);
// await paymentGateway.charge(order.total, order.paymentToken);
return { success: true, transactionId: "txn_12345" };
});
if (!paymentResult.success) {
// Ödeme başarısız olursa, bir telafi işlemi başlatabilir veya başka bir olay tetikleyebiliriz.
await inngest.send({
name: "order.payment.failed",
data: { orderId: order.id, reason: "Payment failed" },
});
throw new Error("Ödeme başarısız oldu.");
}
// Adım 4: Fatura oluşturma (paralel işlem örneği)
const [invoiceResult, shippingNotificationResult] = await Promise.all([
step.run("generate-invoice", async () => {
console.log(Sipariş ${order.id} için fatura oluşturuluyor...);
// return await invoiceService.generate(order, paymentResult.transactionId);
return { invoiceUrl: "http://example.com/invoice/123" };
}),
step.run("send-shipping-notification", async () => {
console.log(Sipariş ${order.id} için kargo bildirimi gönderiliyor...);
// await shippingService.notify(order);
return { success: true };
})
]);
// Adım 5: İşlem tamamlandığında başka bir olay tetikle
await inngest.send({
name: "order.processed",
data: {
orderId: order.id,
invoiceUrl: invoiceResult.invoiceUrl,
paymentTransactionId: paymentResult.transactionId,
},
});
return { message: Sipariş ${order.id} başarıyla işlendi. };
}
);
Bu örnekte, her adım step.run() ile izlenir. Inngest, bir adım başarısız olursa otomatik olarak yeniden dener. Ayrıca, Promise.all kullanarak fatura oluşturma ve kargo bildirimi gibi bağımsız adımları paralel olarak çalıştırabiliriz, bu da toplam yürütme süresini azaltır. Adımlar arasında veri aktarımı (örneğin, paymentResult.transactionId) sorunsuz bir şekilde gerçekleşir. Ödeme başarısız olursa, order.payment.failed gibi yeni bir olay tetikleyerek başka bir fonksiyona (örneğin, müşteriye bildirim gönderme veya manuel inceleme için bir görev oluşturma) bilgi verebiliriz.
Zamanlanmış Görevler ve Bekleme Adımları
Inngest sadece olaylara tepki vermekle kalmaz, aynı zamanda belirli bir süre bekleme veya zamanlanmış görevleri de destekler.
step.sleep(duration): Bir iş akışını belirli bir süre duraklatmak için kullanılır. Örneğin, bir kullanıcıya kaydolduktan 24 saat sonra hatırlatma e-postası göndermek isteyebilirsiniz.step.waitForEvent(eventName, timeout): Bir iş akışını belirli bir olayın gerçekleşmesini beklemek için duraklatır. Örneğin, bir kullanıcının kaydolduktan sonra e-postasını onaylamasını bekleyebilirsiniz. Belirtilen süre içinde olay gerçekleşmezse, akış devam edebilir veya bir hata fırlatılabilir.crontetikleyicisi: Belirli aralıklarla çalışan görevler için kullanılır (örneğin, her gece veritabanı yedeklemesi almak, her hafta rapor oluşturmak).
// Örnek: Kullanıcıya 24 saat sonra hatırlatma e-postası gönderme
export const sendReminderEmail = inngest.createFunction(
{ id: "send-reminder-email" },
{ event: "user.signed.up" },
async ({ event, step }) => {
// 24 saat bekle
await step.sleep("wait-24-hours", "24h");
// Ardından hatırlatma e-postası gönder
await step.run("send-reminder", async () => {
console.log(24 saat sonra hatırlatma e-postası gönderiliyor: ${event.data.email});
// await emailService.sendReminder(event.data.email);
});
return { message: "Hatırlatma e-postası gönderildi." };
}
);
// Örnek: Her gece çalışan yedekleme görevi
export const dailyBackup = inngest.createFunction(
{ id: "daily-database-backup" },
{ cron: "0 0 * * *" }, // Her gece yarısı çalışır (UTC)
async ({ step }) => {
await step.run("perform-backup", async () => {
console.log("Veritabanı yedeklemesi başlatılıyor...");
// await databaseService.backup();
});
return { message: "Veritabanı yedeklemesi tamamlandı." };
}
);
Bu yetenekler, Inngest’i sadece basit arka plan işleri için değil, aynı zamanda karmaşık ve zamana duyarlı iş akışları için de ideal bir çözüm haline getirir. Geliştiriciler, bu tür mantıkları kendi başlarına kodlamak zorunda kalmadan, Inngest’in güçlü soyutlamalarından faydalanabilirler.
Inngest ile Gerçek Dünya Problemlerini Çözmek
Inngest’in esnekliği ve gücü, çeşitli gerçek dünya senaryolarında kendini gösterir. İşte iki farklı vaka analizi ile Inngest’in nasıl değer kattığını görelim.
Vaka Analizi 1: E-ticaret Sipariş İşleme Akışı
Bir e-ticaret platformu düşünelim. Müşteri bir sipariş verdiğinde, arka planda birçok işlem tetiklenir:
- Stok miktarları güncellenir.
- Müşteriye sipariş onayı e-postası gönderilir.
- Ödeme işlemi yapılır.
- Fatura oluşturulur ve PDF olarak depolanır.
- Kargo firmasına sipariş bilgileri gönderilir.
- Satış ve pazarlama ekibi için CRM sistemine kayıt düşülür.
Bu işlemlerin herhangi birinin başarısız olması, tüm sipariş akışını etkileyebilir. Geleneksel yaklaşımlarla, bu karmaşık akışı yönetmek için çok sayıda kuyruk, işçi ve hata denetimi mekanizması kurmak gerekirdi. Inngest ile bu süreci tek bir fonksiyon içinde, adımlar halinde tanımlayabiliriz:
import { inngest } from "./client";
export const handleNewOrder = inngest.createFunction(
{ id: "handle-new-order", name: "Yeni Sipariş İşleme" },
{ event: "app/order.created" },
async ({ event, step }) => {
const { orderId, customerId, items, totalAmount, customerEmail } = event.data;
// 1. Stokları güncelle
const stockUpdate = await step.run("update-product-stock", async () => {
console.log(Sipariş ${orderId} için stok güncelleniyor.);
// await productInventoryService.updateStock(items);
return { success: true, message: "Stok güncellendi." };
});
if (!stockUpdate.success) {
// Stokta sorun varsa, siparişi iptal et ve müşteriye bildir
await inngest.send({
name: "app/order.failed",
data: { orderId, reason: "Stok yetersizliği" }
});
throw new Error("Stok güncellenemedi.");
}
// 2. Ödeme işlemini başlat
const paymentResult = await step.run("process-payment-gateway", async () => {
console.log(Sipariş ${orderId} için ödeme işleniyor.);
// await paymentGateway.charge(totalAmount, customerId);
return { transactionId: "txn_XYZ123", status: "completed" };
});
// 3. Müşteriye onay e-postası gönder
await step.run("send-order-confirmation-email", async () => {
console.log(Sipariş ${orderId} için onay e-postası gönderiliyor.);
// await emailService.send(customerEmail, "Sipariş Onayı", Siparişiniz: ${orderId});
});
// 4. Fatura oluştur ve kargo bilgilerini gönder (paralel)
const [invoice, shippingInfo] = await Promise.all([
step.run("generate-invoice-pdf", async () => {
console.log(Sipariş ${orderId} için fatura oluşturuluyor.);
// return await invoiceService.generate(orderId, paymentResult.transactionId);
return { invoiceUrl: https://invoices.com/${orderId}.pdf };
}),
step.run("send-shipping-details", async () => {
console.log(Sipariş ${orderId} kargo firmasına iletiliyor.);
// return await shippingProvider.sendOrder(orderId, items);
})
]);
// 5. CRM sistemine kayıt düş
await step.run("update-crm-system", async () => {
console.log(Sipariş ${orderId} CRM'e kaydediliyor.);
// await crmService.updateCustomerOrder(customerId, orderId);
});
// Tüm adımlar başarıyla tamamlandı
await inngest.send({
name: "app/order.completed",
data: { orderId, customerId, invoiceUrl: invoice.invoiceUrl }
});
return { message: Sipariş ${orderId} başarıyla işlendi., invoiceUrl: invoice.invoiceUrl };
}
);
Bu örnekte, Inngest her adımın durumunu izler, başarısız olan adımları otomatik olarak yeniden dener ve tüm akışın tutarlılığını sağlar. Paralel işlemler sayesinde, fatura oluşturma ve kargo entegrasyonu gibi bağımsız görevler aynı anda yürütülebilir, bu da toplam işlem süresini kısaltır. Geliştirici, altyapı karmaşıklığı yerine doğrudan iş mantığına odaklanabilir.
Vaka Analizi 2: Video İşleme ve Medya Dönüştürme
Kullanıcıların video yükleyebildiği bir platformda, yüklenen videoların farklı formatlara dönüştürülmesi, küçük resimlerin (thumbnail) oluşturulması ve ardından kullanıcılara bildirim gönderilmesi gibi yoğun işlemler gerekebilir. Bu işlemler genellikle uzun sürer ve sunucu kaynaklarını tüketir.
import { inngest } from "./client";
export const processVideoUpload = inngest.createFunction(
{ id: "process-video-upload", name: "Video Yükleme İşleme" },
{ event: "app/video.uploaded" },
async ({ event, step }) => {
const { videoId, filePath, userId } = event.data;
// 1. Videoyu farklı formatlara dönüştür
const conversionResult = await step.run("convert-video-formats", async () => {
console.log(Video ${videoId} farklı formatlara dönüştürülüyor.);
// return await videoConverterService.convert(filePath);
return {
success: true,
convertedPaths: ["path/to/video_hd.mp4", "path/to/video_sd.mp4"]
};
});
// 2. Küçük resimler (thumbnails) oluştur
const thumbnailResult = await step.run("generate-thumbnails", async () => {
console.log(Video ${videoId} için küçük resimler oluşturuluyor.);
// return await thumbnailService.generate(filePath);
return { success: true, thumbnailPath: "path/to/thumbnail.jpg" };
});
// 3. Video işlenene kadar bekle (isteğe bağlı, harici bir hizmetten onay bekleniyorsa)
// await step.waitForEvent("video.processing.completed", { timeout: "10m" });
// 4. Kullanıcıya bildirim gönder
await step.run("notify-user-video-ready", async () => {
console.log(Kullanıcı ${userId}'ye video hazır bildirimi gönderiliyor.);
// await notificationService.send(userId, Videonuz hazır: ${videoId});
});
// 5. Video işleme tamamlandı olayını tetikle
await inngest.send({
name: "app/video.processed",
data: {
videoId,
userId,
convertedPaths: conversionResult.convertedPaths,
thumbnailPath: thumbnailResult.thumbnailPath,
},
});
return { message: Video ${videoId} başarıyla işlendi. };
}
);
Bu senaryoda, video dönüştürme ve küçük resim oluşturma gibi zaman alıcı işlemler arka planda, Inngest’in yönetimi altında gerçekleşir. Bu sayede, kullanıcı videoyu yükledikten sonra anında yanıt alırken, yoğun işlemler sunucu kaynaklarını bloke etmeden asenkron olarak tamamlanır. Hata durumlarında Inngest otomatik yeniden denemeler yaparak işlemin güvenilirliğini artırır. Bu, özellikle büyük dosyalarla çalışan veya yoğun medya işleme gerektiren uygulamalar için hayati bir özelliktir.
Mobil Uyumlu HTML ve Yönetim Paneli
Inngest’in kendi yönetim paneli, arka plan işlerinizin durumunu izlemek için harika bir araçtır. Bu panel, mobil cihazlarda da rahatlıkla kullanılabilen duyarlı bir tasarıma sahiptir. Örneğin, bir iş akışının durumunu gösteren bir sayfanın mobil görünümü aşağıdaki gibi bir media query ile optimize edilebilir:
/* styles.css */
.job-card {
border: 1px solid #eee;
padding: 15px;
margin-bottom: 10px;
border-radius: 8px;
background-color: #fff;
}
.job-card-header {
display: flex;
justify-content: space-between;
align-items: center;
margin-bottom: 10px;
}
.job-status {
padding: 5px 10px;
border-radius: 5px;
font-size: 0.9em;
}
.status-success { background-color: #d4edda; color: #155724; }
.status-failed { background-color: #f8d7da; color: #721c24; }
.status-running { background-color: #fff3cd; color: #856404; }
/* Mobil cihazlar için responsive düzenleme */
@media (max-width: 768px) {
.job-card {
padding: 10px;
}
.job-card-header {
flex-direction: column;
align-items: flex-start;
}
.job-status {
margin-top: 5px;
}
}
Bu CSS kodu, .job-card gibi bir bileşenin mobil cihazlarda daha iyi görünmesini sağlar. Inngest kontrol paneli de benzer yaklaşımlarla, her yerden işlerinizin durumunu takip etmenize olanak tanır. Bu, operasyonel verimlilik ve hızlı müdahale yeteneği açısından kritik öneme sahiptir.
Performans ve Ölçeklenebilirlik İpuçları: Inngest ile Uygulamanızı Nasıl Optimize Edersiniz?
Inngest, doğası gereği yüksek performans ve ölçeklenebilirlik sunar. Ancak, uygulamanızın bu avantajlardan tam olarak yararlanmasını sağlamak için bazı en iyi uygulamaları ve ipuçlarını göz önünde bulundurmanız önemlidir.
1. Idempotency (Tekrarlanabilirlik)
Arka plan işleri, ağ sorunları veya diğer geçici hatalar nedeniyle birden fazla kez tetiklenebilir. Bu nedenle, Inngest fonksiyonlarınızın idempotent olması, yani aynı girdilerle birden fazla kez çağrıldığında aynı sonucu vermesi ve yan etkileri tekrar tekrar oluşturmaması önemlidir. Örneğin, bir ödeme işlemini idempotent hale getirmek için, her ödeme isteğine benzersiz bir işlem kimliği ekleyebilir ve bu kimlik zaten işlenmişse işlemi tekrar yapmaktan kaçınabilirsiniz.
await step.run("process-idempotent-payment", async () => {
const transactionId = event.data.uniqueTransactionId;
// Veritabanında bu transactionId'nin zaten işlenip işlenmediğini kontrol et
// if (await paymentService.isProcessed(transactionId)) return { status: "already_processed" };
// İşlemi gerçekleştir
// await paymentService.charge(amount, transactionId);
return { status: "completed" };
});
Inngest’in otomatik yeniden deneme mekanizması düşünüldüğünde, idempotent fonksiyonlar yazmak uygulamanızın güvenilirliğini önemli ölçüde artırır.
2. Concurrency Limits (Eşzamanlılık Limitleri)
Bazı harici API’ler veya veritabanları belirli bir eşzamanlı istek sayısını kaldırabilir. Inngest, fonksiyonlarınız için eşzamanlılık limitleri belirlemenize olanak tanır. Bu, bir API’ye aynı anda çok fazla istek göndererek onu aşırı yüklemekten kaçınmanıza yardımcı olur.
export const limitedApiCall = inngest.createFunction(
{
id: "limited-api-call",
concurrency: {
limit: 5, // Bu fonksiyon aynı anda en fazla 5 kez çalışabilir
key: "event.data.apiClientId", // Her API istemcisi için ayrı limit
},
},
{ event: "api.request.triggered" },
async ({ event, step }) => {
// API çağrısı yap
// await externalApiService.call(event.data.payload);
return { status: "success" };
}
);
Bu özellik, özellikle kritik üçüncü taraf hizmetlerle entegrasyonlarda sisteminizi korumak için çok değerlidir.
3. İzleme ve Gözlemlenebilirlik
Inngest kontrol paneli, fonksiyon yürütmelerinizi, olayları ve hataları gerçek zamanlı olarak izlemenizi sağlar. Logları düzenli olarak kontrol etmek, performans sorunlarını veya hataları erken aşamada tespit etmenize yardımcı olur. Ayrıca, Inngest’in sunduğu metrikleri (yürütme süreleri, hata oranları) kullanarak uygulamanızın genel sağlığını değerlendirebilirsiniz.
console.log() çıktıları Inngest kontrol panelinde görünür ve sorun giderme sırasında paha biçilmezdir. Özellikle, iş akışının hangi aşamasında olunduğunu ve hangi verilerin işlendiğini gösteren loglar eklemek, hata ayıklama sürecini hızlandırır.
4. Maliyet Optimizasyonu
Inngest, sunucusuz bir platform olduğu için yalnızca kullandığınız kadar ödeme yaparsınız. Fonksiyonlarınızı kısa ve odaklanmış tutmak, gereksiz hesaplama sürelerini azaltır. Ayrıca, gereksiz yere olay tetiklemekten kaçınmak veya iş akışlarını mümkün olduğunca optimize etmek de maliyetleri düşürmeye yardımcı olabilir. Özellikle step.sleep() veya step.waitForEvent() gibi bekleme adımları, aktif hesaplama süresi yerine sadece bekleme süresi olarak faturalandırıldığı için maliyet açısından verimlidir.
5. Veri Boyutu ve Yükü
Inngest olayları ve fonksiyonları aracılığıyla aktarılan verilerin boyutunu optimize etmek performansı artırabilir. Büyük dosyaları veya ikili verileri doğrudan olay yükünde göndermek yerine, bu verileri bir depolama hizmetine (AWS S3, Google Cloud Storage vb.) yükleyip, olaya sadece dosyanın referansını (URL veya ID) dahil etmek daha iyi bir yaklaşımdır. Fonksiyon daha sonra bu referansı kullanarak veriyi işleyebilir.
Bu ipuçlarını uygulayarak, Inngest ile oluşturduğunuz arka plan işleri ve olay odaklı iş akışlarının hem performanslı hem de maliyet açısından verimli olmasını sağlayabilirsiniz. Inngest’in sunduğu güçlü özelliklerle birleşen bu yaklaşımlar, uygulamanızın uzun vadeli başarısına katkıda bulunacaktır.
Sonuç: Inngest ile Geleceğe Yönelik Arka Plan İşleri
Bu makalede, Inngest’in modern uygulamalarda arka plan işleri ve olay yönetimi konusundaki zorlukları nasıl ortadan kaldırdığını detaylıca inceledik. Geleneksel kuyruk sistemlerinin ve manuel hata yönetiminin getirdiği karmaşıklıklar yerine, Inngest geliştiricilere basit, güçlü ve ölçeklenebilir bir çözüm sunar. Olay odaklı mimarisi, çok adımlı iş akışlarını yönetme yeteneği, otomatik yeniden denemeler ve kapsamlı gözlemlenebilirlik özellikleriyle Inngest, uygulamalarınızın daha dayanıklı ve verimli olmasını sağlar.
Inngest kullanarak, e-ticaret sipariş işleme, medya dönüştürme, bildirim gönderme veya zamanlanmış görevler gibi karmaşık senaryoları kolayca modelleyebilir ve uygulayabilirsiniz. Geliştiriciler, altyapı yönetimiyle uğraşmak yerine, doğrudan iş mantığına odaklanarak daha hızlı inovasyon yapabilirler. Ayrıca, sunucusuz yapısı sayesinde maliyetleri optimize eder ve uygulamalarınızın talebe göre otomatik olarak ölçeklenmesini sağlar.
Özetle, Inngest, modern yazılım geliştirme pratiklerinin getirdiği asenkron ve dağıtık sistemler gereksinimlerine mükemmel bir şekilde yanıt veren bir platformdur. Uygulamalarınızın arka plan süreçlerini basitleştirmek, güvenilirliği artırmak ve geliştirme hızınızı yükseltmek istiyorsanız, Inngest kesinlikle değerlendirmeniz gereken bir araçtır.
Sıkça Sorulan Sorular
-
Inngest’in diğer kuyruk sistemlerinden farkı nedir?
Inngest, sadece bir mesaj kuyruğu olmanın ötesinde, tam teşekküllü bir olay odaklı iş akışı motorudur. Geleneksel kuyruk sistemleri sadece mesajları iletirken, Inngest otomatik yeniden denemeler, gecikmeli çalıştırmalar, paralel adımlar, durum yönetimi ve kapsamlı gözlemlenebilirlik gibi özellikleri yerleşik olarak sunar. Bu, geliştiricilerin bu karmaşık mantıkları kendilerinin kodlamasına gerek kalmadan, iş akışlarını kolayca tanımlamasına olanak tanır. Ayrıca, sunucusuz yapısı sayesinde altyapı yönetimi yükünü tamamen ortadan kaldırır.
-
Inngest maliyetli mi?
Inngest, kullandıkça öde (pay-as-you-go) modeline sahiptir. Bu, sadece tetiklediğiniz olaylar ve çalışan fonksiyonlarınızın süresi kadar ödeme yapacağınız anlamına gelir. Genellikle, kendi kuyruk sistemlerinizi kurma ve bakımını yapma maliyetine kıyasla daha uygun maliyetli olabilir, özellikle operasyonel yük ve geliştirici zamanı hesaba katıldığında. Küçük projeler için ücretsiz bir katmanı da mevcuttur, bu da başlamayı kolaylaştırır.
-
Hangi programlama dillerini destekler?
Inngest, başlıca Node.js/TypeScript, Python ve Go için resmi SDK’lar sunar. Bu dillerde yazılmış uygulamalarla kolayca entegre olabilir. Ayrıca, platform bağımsız REST API’si sayesinde herhangi bir dilden olay göndermek veya fonksiyonları tetiklemek mümkündür, ancak tam iş akışı yetenekleri SDK’lar aracılığıyla daha kolay kullanılır.
-
Veri güvenliği nasıl sağlanır?
Inngest, verilerinizi taşınırken ve beklerken şifreler. Ayrıca, hassas verilere erişimi kontrol etmek için API anahtarları ve yetkilendirme mekanizmaları kullanır. Fonksiyonlarınızın çalıştığı ortamlar izole edilmiş ve güvenlidir. Kendi veri güvenliği politikalarınıza uygun olarak, hassas verileri doğrudan Inngest olaylarına dahil etmek yerine, güvenli bir depolama alanına kaydedip olayda sadece bir referans göndermek gibi ek önlemler almanız önerilir.
-
Inngest’i kendi sunucumda barındırabilir miyim?
Inngest, yönetilen bir hizmet (managed service) olarak sunulur ve kendi sunucunuzda (on-premise) barındırma seçeneği sunmaz. Bu model, altyapı yönetimi yükünü Inngest’e devretmenizi sağlar, böylece siz uygulamanızın iş mantığına odaklanabilirsiniz. Serverless yapısı ve küresel dağıtımı sayesinde yüksek kullanılabilirlik ve ölçeklenebilirlik sağlar.
