
Hook Operasyonları-Entegrasyon Sihirbazı🧙♂️(Iron Hook🪝)
Özellikle SaaS modelini benimseyen ürünlerde hook veya web hook kavramları her zaman ön planda tutulmuştur. Hook kelimesinin arkasında bulunan temel espiri, önceden tanımlanmış bir olay gerçekleştiğinde belirli bir servise veya servislere haber verilmesidir. Belirli bir operasyonu yönetmek için kullandığınız bir üründe ilk aramanız gereken özellik hook operasyonları olmalıdır. Eğer kullandığınız bu ürün tüm olayları kendi içerisinde tutuyor ve kendisinde olmayan servislere bildirmiyorsa entegrasyon anlamında işinizi oldukça zorlaştıracaktır. FowApps ürün ailesi içerisinde geliştirmekte olduğumuz ürünler için entegrasyon oldukça önemli bir süreçtir. Bu sihirli kelimeyi biraz daha açalım ve Entegrasyon
süreçlerine bir deep-dive gerçekleştirelim.
Entegrasyon kelimesinin her domainde veya her üründe farklı bir tanımı olabilir. Bu kelimeye ilkel bir bakış açısıyla yaklaşacak olursak; sistem üzerinde gerçekleşen olayların, iki taraflı tüketilmesi veya kullanılması olarak tanımlayabiliriz.
Bir ürün geliştirdiğinizi düşünün. Domain bazında olması gereken onlarca belki yüzlerce endpoint yani uç noktanız olacaktır. Bu uç noktaları customer create
, customer update
ve customer delete
olarak sınırlandıralım. Bu uç noktaların tetiklenmesi ilk aşamada kullanıcının gerçekleştirdiği bir aksiyon sonucunda oluşacaktır. Adım adım bu aksiyonu inceleyelim;
- Kullanıcı
Email
,Password
gibi bilgileri belirlenen arayüzden doldurur ve sisteme giriş yapar. - Sağ üst köşede bulunan ➕ simgesine tıklayarak
Customer Create
formunu açar. - Zorunlu alanları doldurur.
- Kaydet butonuna tıklar.
Kullanıcının yaptığı bu aksiyon arka tarafta kullanıcının bilmediği customer create
uç noktasını tetikler ve süreç tamamlanır.
Bu hikaye, hepimizin bildiği ve sistem içerisindeki bir uç noktayı tetikleyebileceğimiz en ilkel yöntemdir. Şimdi geliştirdiğimiz bu ürünün farklı ürünlerle nasıl entegrasyon sağlayabileceğini düşünelim.
Son kullanıcımız kendi sisteminde gerçekleşen bir aksiyon sonucunda ürünümüzde bulunan customer create
uç noktasını tetiklemek ve süreci tamamlamak istiyor. Bu örnekte odaklanmamız gereken nokta istenilen entegrasyonun yön bilgisi olmalıdır. Entegrasyon süreçlerini yönetmek istiyorsak sormamız gereken ilk soru “Entegrasyonun yönü nedir?” olmalıdır.
Entegrasyon Süreçlerinde Yön Kavramı
Entegrasyon, gerçekten havalı bir isim. Aslında bu kelimenin sırrı veri paylaşmaktır. Her entegrasyon sürecinde bir miktar veri bir sistemden bir başka sisteme doğru yolculuğa başlar. Bu yolculuğun nereden nereye olacağı bizim için oldukça önemli. Bu yönleri listeleyecek olursak;
- ▶️Bizden dışarıya
- ⬅️ Dışarıdan bize
- 💘 Çift yönlü
maddelerini söyleyebiliriz.
Yönler belirlendikten sonra entegrasyonu başlatacak taraf belirlenmelidir.
Tanımlanan entegrasyon her zaman iki nokta arasında gerçekleşmez. Bazen dört veya beş taraflı bir entegrasyon yapmamız gerekebilir. Örneğin kredi kartı ile ödeme entegrasyonu yaparken genelde tercih ettiğiniz provider ile aranızda bir entegrasyon gerçekleştirirsiniz. Ancak ödeme ekranında kullanıcıdan fatura bilgileri alıp bu bilgileri anlık bir sağlayıcıdan doğruluyorsanız entegrasyon taraflarınız ve maliyetiniz artmış olur.
Eğer entegrasyonu başlatacak taraf siz değilseniz o zaman karşı tarafın entegrasyonu kolay bir şekilde tamamlaması için aşağıdaki adımları uygulamalısınız;
- Authentication (Mandotary)
- Api Documentation (Mandotary)
- Validation Rules (Mandotary)
- Api Credit (Optional)
- Limit Rules (Optional)
Şimdiye kadar belirtilen kavramların tamamı entegrasyon sürecini anlamak içindi. Şimdi odağımızı biraz daha teknik tarafa çevireceğiz. Asp.Net Core ile geliştirdiğimiz api tabanlı uygulamalarımızda “Entegrasyon maliyetini nasıl minimuma indirebiliriz?” sorusuna cevap arayacağız. Ek olarak bu süreci otomatikleştirmek için bir library tasarlayacağız ve Plug-Play
felsefesi ile tasarladığımız bu kütüphaneyi kullanacağız. Hadi öğrenelim. 🥸
Entegrasyon sürecinde ilk adımın tanımlamalar olduğunu artık biliyoruz.
Bu tanımlamaları gerçekleştirmek için Hook.cs
isimli bir class oluşturalım.
Odak noktamız SaaS uygulamalarda entegrasyon süreci olduğu için Tenant bilgisi bizim için önemli. Her tenant kendi entegrasyon tanımlarını yapabilir.
Key
bilgisiyle ilerleyen süreçlerde gerçekleştirilen bu tanımları tetikleyeceğiz.
Gerçekleştireceğimiz uygulama şimdilik entegrasyonu HTTP üzerinden sağlayacaktır. Bu sebeple yapılan bu tanımlamalar Url
, Method
ve Header
gibi bilgileri içermelidir. Bu bilgiler için HookRequest.cs
isimli bir class oluşturalım.
Veri tabanı olarak PostgreSql
kullanacağımız için tanımlanan Header
bilgilerini string
olarak saklayabiliriz. Entegrasyonun çalışacağı kısımlarda, bu bilgi gerekli objeye convert edilerek kullanılacaktır.
Entegrasyon tanımlamaları için Hook
ve HookRequest
varlıkları yeterli olacaktır. Şimdi yapılan bu tanımlamaları çalıştıralım.
Entegrasyon tanımları yapılırken girilen bilgiler doğrultusunda basit bir HTTP request operasyonu gerçekleştiren HttpHookOperator.cs
sınıfı ile entegrasyonu gerçekleştirebiliriz. Teorik bilgiler kafamızı biraz karıştırmış olabilir. Bazı görsel çizimlerle kurguladığımız bu yapıyı nasıl kullanabileceğimizi özetleyelim. Sonra FowApps ekibi olarak bu yapının doğru abstraction tekniklerinin uygulanmış sürümü olan IronHook
kütüphanesini inceleyeceğiz ve geliştirdiğimiz kütüphaneyi uygulamalarımızda nasıl kullanacağımızı öğreneceğiz.
Geliştirdiğimiz uygulamalarda genellikle domain nesnelerimiz bulunur. Kurguladığımız bu yapı veya IronHook
entegrasyon sürecinin uygulamamızda gerçekleşen olaylar sonucunda oluşan veriyi dışarıda bulunan bir servise bildirme işlemini gerçekleştirdiğini hatırlatalım.

customer.created
yani sistem üzerinde bir müşteri yaratıldığında, şekilde gösterilen bilgiler kullanılarak entegrasyon süreci başlayacak ve oluşturulan customer bilgisi dış bir kaynağa gönderilecektir.
Sistem içerisinde gerçekleşen bir olayı ve o olaya ait olan bilgiyi dış bir kaynak ile paylaşmak Hook
olarak isimlendirilebilir. FowApps ekibi olarak IronHook
isimli bir kütüphane geliştirdik. Hadi bu kütüphaneyi kullanarak bir web api projesi geliştirelim.
IronHook
şimdilik PostgreSql
ve Sql Server
veri tabanlarını destekler. Bu yazıda PostgreSql
sürümünü kullanacağız.
IronHook.PostgreSql
kütüphanesini Nuget
üzerinden indirelim.
Install-Package IronHook.PostgreSql -Version 2.0.0
Ardından IServiceCollection
üzerinde bulunan AddIronHook
extension metodunu kullanalım. IronHook
alt yapısının çalışacağı veri tabanının connection string bilgisini bu extension metodu içerisinde ayarlayacağız.
services.AddIronHook(options =>
{
options.UseNpgsql("{YOUR_CONNECTION_STRING}", opts => opts.UseIronHookNpgsqlMigrations());
});
IronHook
kullandığınız veri tabanında kendi şemasında işlem yapar. Her yeni sürümde veri tabanı varlıkları üzerinde değişiklik veya yeni eklenen yapılar olabilir. Bu sebeple migrationların otomatik gerçekleştirilmesi için Dotnet5
üzerinde IApplicationBuilder
Dotnet6
üzerinde ise IHost
üzerinde bulunan MigrateIronHook
extension metodunu kullanabilirsiniz.
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
app.MigrateIronHook();
// ...
}
Uygulamanızı çalıştırdıktan sonra veri tabanınızı kontrol ederseniz iron-hook
şemasının içerisinde ilgili veri tabanı tablolarını bulabilirsiniz.
Eğer Dotnet6
kullanıyorsanız IApplicationBuilder
yerine IHost
üzerinde bulunan extension metodu kullanabilirsiniz.
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddIronHook(opts =>
{
opts.UseNpgsql(
"{YOUR_CONNECTION_STRING}",
opts =>opts.UseIronHookNpgsqlMigrations()
);
});
var app = builder.Build();
app.MigrateIronHook();
Konfigürasyon adımı tamamlandı artık kullanabiliriz.
İlk olarak kullanıcının entegrasyon tanımlarını nasıl yapabileceğini öğrenelim.
Öncelikle IHookService
arayüzünü constructor üzerinden alalım.
Define Hook
var hook = new Hook
{
TenantId = "xx",
Key = "hook.key",
Name = "name of hook",
HookRequests = new List<HookRequest>
{
new HookRequest
{
Url = "https://google.com/search?q=ironhook",
MaxRetryCount = 3,
NotifiyEmail = "mail@ironhook.com",
Method = "GET",
Headers = JsonSerializer.Serialize(new List<HeaderParameter>
{
new HeaderParameter
{
Name = "Authorization",
Value = "Bearer xxx"
},
new HeaderParameter
{
Name = "ApiKey",
Value = "xxxxx"
},
})
},
new HookRequest
{
Url = "https://google.com/search?q=github",
MaxRetryCount = 4,
NotifiyEmail = "help@github.com",
Method = "GET",
Headers = JsonSerializer.Serialize(new List<HeaderParameter>
{
new HeaderParameter
{
Name = "Authorization",
Value = "Bearer xxx"
}
})
}
}
};
await hookService.AddAsync(hook);
Tanımlanan entegrasyonları çalıştırmak için RaiseHook
yöntemini kullanacağız.
Bu örnekte tanımlanan entegrasyonları bir endpoint’in arkasında çalıştıracağım. Best practice nedir diye sorarsanız, tanımlanan bu entegrasyonların backgrounda çalışması olacaktır. Tanımlanan entegrasyonlar uzun sürebilir veya hata verebilir bu sebeple business logic içerisinde bulunmaması gerekir.
Raise Hook
/// <summary>
/// Customers Endpoint
/// </summary>
[Route("api/[controller]")]
[ApiController]
public class CustomersController : ControllerBase
{
private readonly SampleDbContext sampleDbContext;
private readonly IHookService hookService;
/// <summary>
/// Ctor
/// </summary>
/// <param name="sampleDbContext">
/// Sample Database Context
/// </param>
/// <param name="hookService">
/// Hook Service
/// </param>
public CustomersController(SampleDbContext sampleDbContext, IHookService hookService)
{
this.sampleDbContext = sampleDbContext;
this.hookService = hookService;
}
/// <summary>
/// Customer Create
/// </summary>
/// <returns></returns>
[HttpPost(Name = "AddCustomer")]
[ProducesResponseType(typeof(HookResponse[]),200)]
public async Task<IActionResult> AddCustomerAsync([FromBody] CustomerRequestDto model)
{
var entity = await sampleDbContext.Customers.AddAsync(new Customer
{
Name = model.Name,
Surname = model.Surname,
Phone = model.Phone
});
await sampleDbContext.SaveChangesAsync();
var response = await hookService.RaiseHookAsync(EventNames.CUSTOMER_CREATED, "1", entity.Entity); // <---
return Ok(response);
}
}
İşte bu kadar. IronHook
sizlere belirli arayüzler sunuyor eğer isterseniz onu customize etmenizi de sağlıyor. Temel olarak tanımlanan entegrasyon tanımlarını HTTP üzerinden gerçekleştiriyor. İlerleyen aşamalarda farklı kanalları da destekleyebilir.
Daha detaylı bilgi ve örnek projeler için IronHook
github reposunu takip edebilirsiniz.
Yazdığınız kodlar production ortamında hatasız koşsun. Testler sizi korusun. 🙏