---
title: 'Olay Veri Yolu'
source: 'https://academia.sh/tr/kurslar/sunucusuz/olay-veri-yolu'
course: 'Sunucusuz ve Kenar Bilişim'
language: tr
updated: '2026-08-17T18:06:57+00:00'
license: 'CC BY-SA 4.0'
---

# Olay Veri Yolu

Yönlendirme kararının veri yoluna devredilmesi: aynı iki bin olaylık akışta kural kümesi genişledikçe hiçbir kurala uymayan ve birden çok hedefe giden olay sayısının taranması, süzgecin kuralda mı hedefte mi durduğunun taşınan olay sayısına etkisi ve yeni bir kuralın hiçbir sayıyı bozmadan trafik almasının ölçülmesi.

Önceki ders işlevin sınırlarını saydı ve nerede kullanılamayacağını yazdı. Geriye tek bir soru
kaldı: işlevler birbirine nasıl bağlanacak? Bir işlev kendi başına hiçbir şey yapmaz; bir şeyin
onu uyandırması gerekir. Uyandıran taraf çağıran işlevse, çağıranın hedefi bilmesi gerekir —
adresi, sürümü, kaç tane olduğu. Üretici sayısı arttıkça bu bilgi her üreticide ayrı ayrı
çoğalır.

**Olay veri yolu** (event bus) bu bağı tersine çevirir. Üretici olayı yazar ve kime gideceğini
bilmez; hedefi **kural** (rule) seçer. Karar üreticiden alınıp veri yoluna devredilmiştir. Bu
ders devredilen kararın karşılığında ne geldiğini sayar.

## Devredilen Karar: Kimin Uyanacağı

Doğrudan çağrıda hedef listesi kodun içindedir: kim kimi çağırıyor, çağrı yığınından okunur.
Kural tabanlı yönlendirmede hedef listesi kodun dışındadır — kural bir **veri** kalemidir.
Karşılığında gelen kısıt buradan doğar: yönlendirme artık kaynak deposundaki farkta görünmez,
işlevin çağrı çizgesinde durmaz ve bir olayın nereye gittiği ancak kural kümesi okunarak
bilinir.

Devredilen kararın ilk karşılığı bağ sayısındadır. Ölçüm ağında olay üreten altı bileşen ve
olayla iş yapan dokuz hedef var. Doğrudan çağrıda her üretici ilgilendiği hedefleri bilmek
zorundadır: en kötü durumda 54 bağ, her biri iki tarafta da tutulan bir adres ve bir sürüm.
Veri yolunda üretici tek bir yere yazar, hedefler tek bir yerden okur — 6 + 9 = 15 kayıt ve
aralarında bir kural kümesi. Bağ sayısı çarpımdan toplama iner. Kısıt de aynı yerden gelir:
54 bağın hepsi kodda görünürdü, kural kümesindeki hiçbir kalem kodda değildir.

İkinci kısıt eşleşmenin kendisindedir. Bir olay hiçbir kurala uymazsa veri yolunun öntanımlı
davranışı onu **düşürmektir**; hata üretmez, kimseyi uyandırmaz, geriye iz bırakmaz. Üçüncüsü
tersidir: bir olay birden çok kurala uyarsa her kural kendi hedefini uyandırır ve aynı olay
birden çok kez işlenir. İkisi de kural kümesinin genişliğine bağlıdır, ikisi de bir sayıdır.

Ölçüm, ders boyunca sürecek kurgu bir düzenek üzerinde yapılır: **bölgesel ölçüm ağı** —
sayaçların okumalarını gönderdiği, okumaların doğrulandığı, fatura üretilen ve saha ekiplerine
iş atanan bir sistem. Ağ da, olay adları da kurgudur.

- **OS1.** Akış 2.000 olaydır; olay türleri dokuz kalemdir ve türlerin payı sabittir.
- **OS2.** Her olayın üç alanı vardır: tür, bölge (dört bölge), öncelik (1–3).
- **OS3.** Kural, nokta ile ayrılmış bir tür deseni ve isteğe bağlı alan koşullarıdır; desendeki
  `*` o bölümden sonrasını serbest bırakır.
- **OS4.** Bir olay aynı hedefe iki kuraldan uyarsa tek teslim sayılır; teslim hedef başınadır.
- **OS5.** Rastgelelik gerektiren yerlerde üreteç kendi yazılır ve tohum görünürdür.
- **OS6.** Model yalnız yönlendirme kararını kurar; taşıma gecikmesi ve sıra ölçülmez.

## Kural Kümesi Genişledikçe

Aşağıdaki kod bir veri yolu değil, yönlendirme kararının sayılabilir bir modelidir. Aynı akış
üç kural kümesinden geçirilir: dört kurallı **dar**, yedi kurallı **orta**, on kurallı ve bir
yakala-tümü kuralı içeren **geniş**.

```js
// kural-motoru.mjs — olay veri yolu modeli: kurallar deseni tutan olaylari hedeflere yonlendirir
// Model: gercek bir veri yolu degil, yonlendirme kararinin sayilabilir bicimde yeniden kurulmasi.

const TOHUM = 20260415;                       // uretec tohumu: kosum tekrarlanabilir
let durum = TOHUM;
const rastgele = () => (durum = (durum * 1103515245 + 12345) % 2147483648) / 2147483648;

const TURLER = [["olcum.okuma.alindi", 46], ["olcum.okuma.eksik", 9],
  ["olcum.dogrulama.basarisiz", 7], ["fatura.taslak.olustu", 12], ["fatura.kesinlesti", 6],
  ["cihaz.pil.dusuk", 8], ["cihaz.baglanti.koptu", 5], ["saha.ekip.atandi", 4],
  ["saha.ariza.kapandi", 3]];
const BOLGELER = ["kuzey", "dogu", "bati", "merkez"];

function olaylar(n) {
  const liste = [];
  for (let i = 0; i < n; i++) {
    let p = rastgele() * 100, tur = TURLER[0][0];
    for (const [ad, agirlik] of TURLER) { if ((p -= agirlik) < 0) { tur = ad; break; } }
    liste.push({ tur, bolge: BOLGELER[Math.floor(rastgele() * 4)],
                 oncelik: 1 + Math.floor(rastgele() * 3) });
  }
  return liste;
}

// Desen: nokta ile ayrilmis bolumler; "*" o bolumden sonrasini serbest birakir.
function tutuyor(desen, tur) {
  const d = desen.split("."), t = tur.split(".");
  for (let i = 0; i < d.length; i++) {
    if (d[i] === "*") return true;
    if (d[i] !== t[i]) return false;
  }
  return d.length === t.length;
}
const uyuyor = (k, o) => tutuyor(k.desen, o.tur) &&
  (k.bolge === undefined || k.bolge === o.bolge) &&
  (k.enAz === undefined || o.oncelik >= k.enAz);

const K = {
  dar: [
    { ad: "K1", desen: "olcum.okuma.alindi", hedef: "dogrulama" },
    { ad: "K2", desen: "fatura.*", hedef: "fatura" },
    { ad: "K3", desen: "cihaz.pil.dusuk", hedef: "bakim" },
    { ad: "K4", desen: "saha.*", hedef: "saha" }],
};
K.orta = [...K.dar,
  { ad: "K5", desen: "olcum.*", hedef: "arsiv" },
  { ad: "K6", desen: "cihaz.*", hedef: "izleme" },
  { ad: "K7", desen: "olcum.dogrulama.basarisiz", bolge: "kuzey", hedef: "uyari" }];
K.genis = [...K.orta,
  { ad: "K8", desen: "*", hedef: "denetim" },
  { ad: "K9", desen: "fatura.kesinlesti", hedef: "muhasebe" },
  { ad: "K10", desen: "olcum.okuma.alindi", enAz: 3, hedef: "oncelikli" }];

const AKIS = olaylar(2000);

function tara(kurallar) {
  let eslesmeyen = 0, tek = 0, cok = 0, teslim = 0;
  for (const o of AKIS) {
    const h = new Set(kurallar.filter((k) => uyuyor(k, o)).map((k) => k.hedef));
    teslim += h.size;
    if (h.size === 0) eslesmeyen++; else if (h.size === 1) tek++; else cok++;
  }
  return { eslesmeyen, tek, cok, teslim };
}

console.log("kume    kural  eslesmeyen  tek hedef  cok hedef  toplam teslim");
for (const ad of ["dar", "orta", "genis"]) {
  const s = tara(K[ad]);
  console.log(ad.padEnd(8) + String(K[ad].length).padStart(5) +
    String(s.eslesmeyen).padStart(12) + String(s.tek).padStart(11) +
    String(s.cok).padStart(11) + String(s.teslim).padStart(15));
}
console.log("olay sayisi: " + AKIS.length + ", tohum: " + TOHUM);
```

```sh
node kural-motoru.mjs
```

```
kume    kural  eslesmeyen  tek hedef  cok hedef  toplam teslim
dar         4         433       1567          0           1567
orta        7           0        881       1119           3119
genis      10           0          0       2000           5551
olay sayisi: 2000, tohum: 20260415
```

İlk satır sessiz düşmeyi gösteriyor. Dört kural iki bin olayın 1.567'sini bir hedefe verdi;
**433 olay hiçbir kurala uymadı** ve düşürüldü. Bu olaylar eksik okuma, doğrulama hatası ve
kopan bağlantı bildirimleridir — yani en çok bakılması gereken üç türden ikisi. Düşme bir hata
değildir; veri yolu için "eşleşme yok" olağan bir sonuçtur. Üretici tarafında da bir belirti
yoktur: olay yazıldı, kabul edildi, iş bitti.

İkinci satır kısıtın öbür ucudur. Üç kural eklenince eşleşmeyen sıfıra indi, ama **1.119 olay
birden çok hedefe** gitti ve toplam teslim 1.567'den 3.119'a çıktı. Aynı okuma hem doğrulama
hem arşiv hedefini uyandırıyor. İki hedef ayrı iş yapıyorsa bu doğrudur; ikisi de fatura
kalemi yazıyorsa aynı kalem iki kez yazılır. Kural kümesi bu farkı bilmez.

Bu iki satır arasındaki geçiş, kural kümesi genişletilirken izlenen olağan yoldur: eşleşmeyen
bir olay fark edilir, desen genişletilir, eşleşmeyen sayısı düşer. Düşen tek şey o değildir —
her genişletme, daha önce tek hedefe giden olayları da yeni kurala uygun hale getirir. Dört
kuralda hiçbir olay çok hedefli değilken, üç kural eklendikten sonra akışın yüzde 56'sı çok
hedeflidir. Genişletmenin etkisi yalnız hedeflenen türle sınırlı kalmaz; desen, hedeflenmeyen
türleri de kapsar.

Üçüncü satırda yakala-tümü kuralı eşleşmeyeni sıfırda tutuyor, ama artık **her olay çok
hedefli**: 2.000 olay 5.551 teslime, olay başına 2,78 uyandırmaya dönüştü. Sessiz düşmeden
kaçmanın bedeli üç kat teslimdir ve teslim, işlev tarafında çağrı demektir.

## Süzgecin Yeri

Yönlendirme kararı devredilince ikinci bir karar da devredilebilir: **süzme**. Doğrulama hedefi
gerçekte yalnız kuzey bölgesinin öncelikli okumalarıyla ilgilenir. Bu koşul ya kuralın içine
yazılır ya da hedefin ilk satırlarına. İkisi de aynı işi yapar; taşınan olay sayısı aynı
değildir.

```js
// suzgec-yeri.mjs — ayni akis, suzgec kuralda ve hedefte; sonra gorunmeyen bir kural eklenir
const TOHUM = 20260415;                       // ilk kosumla ayni tohum, ayni akis
let durum = TOHUM;
const rastgele = () => (durum = (durum * 1103515245 + 12345) % 2147483648) / 2147483648;
const TURLER = [["olcum.okuma.alindi", 46], ["olcum.okuma.eksik", 9],
  ["olcum.dogrulama.basarisiz", 7], ["fatura.taslak.olustu", 12], ["fatura.kesinlesti", 6],
  ["cihaz.pil.dusuk", 8], ["cihaz.baglanti.koptu", 5], ["saha.ekip.atandi", 4],
  ["saha.ariza.kapandi", 3]];
const BOLGELER = ["kuzey", "dogu", "bati", "merkez"];
const AKIS = [];
for (let i = 0; i < 2000; i++) {
  let p = rastgele() * 100, tur = TURLER[0][0];
  for (const [ad, agirlik] of TURLER) { if ((p -= agirlik) < 0) { tur = ad; break; } }
  AKIS.push({ tur, bolge: BOLGELER[Math.floor(rastgele() * 4)],
              oncelik: 1 + Math.floor(rastgele() * 3) });
}

const ilgili = (o) => o.bolge === "kuzey" && o.oncelik >= 2;   // hedefin gercekten istedigi
const okuma = AKIS.filter((o) => o.tur === "olcum.okuma.alindi");
const BIRIM = 1000;                            // kurgu birim: her 1000 teslim 1 tasima birimi

console.log("suzgecin yeri".padEnd(16) + "tasinan".padStart(8) +
  "bosa uyandirma".padStart(16) + "tasima birimi".padStart(15));
for (const [yer, tasinan] of [["suzgec kuralda", okuma.filter(ilgili)], ["suzgec hedefte", okuma]]) {
  const bosa = tasinan.length - tasinan.filter(ilgili).length;
  console.log(yer.padEnd(16) + String(tasinan.length).padStart(8) + String(bosa).padStart(16) +
    (tasinan.length / BIRIM).toFixed(2).padStart(15));
}

// Gorunmeyen kural: mevcut hedefin sayilarina dokunmadan ayni olaylari ikinci bir hedefe verir.
const oncesi = okuma.filter(ilgili).length;
const golge = AKIS.filter((o) => o.tur.startsWith("olcum.okuma.")).length;
console.log("\nkural eklemeden once  dogrulama hedefi: " + oncesi + ", toplam teslim: " + oncesi);
console.log("K11 eklendikten sonra dogrulama hedefi: " + oncesi + ", toplam teslim: " +
  (oncesi + golge) + ", hata: 0");
```

```sh
node suzgec-yeri.mjs
```

```
suzgecin yeri    tasinan  bosa uyandirma  tasima birimi
suzgec kuralda       145               0           0.14
suzgec hedefte       926             781           0.93

kural eklemeden once  dogrulama hedefi: 145, toplam teslim: 145
K11 eklendikten sonra dogrulama hedefi: 145, toplam teslim: 1257, hata: 0
```

Süzgeç kuralda durunca 145 olay taşındı ve hepsi işlendi. Hedefte durunca 926 olay taşındı,
**781'i ilk satırda elendi**: işlev uyandı, olayı okudu, ilgisiz olduğunu gördü, döndü. Aynı
işin görünen maliyeti taşıma tarafında 0,14 birime karşı 0,93 birim — 6,4 kat. Birim kurgudur;
oran kural kümesinden çıkar.

Boşa uyandırmanın bedeli yalnız taşıma değildir. 781 çağrı eşzamanlılık havuzundan pay alır,
soğuk başlangıç ihtimalini taşır ve işlev tarafındaki her ölçüte gürültü olarak girer: çağrı
sayısı, hata oranı, ortalama süre. Süzgeci kurala taşımanın bedeli ise koşulun kod
incelemesinden çıkıp yapılandırmaya geçmesidir — bir sonraki bölümün konusu.

Kaynakta süzmenin bir sınırı var ve bu sınır ölçümün dışında kalan asıl kısıttır: süzgeç yalnız
olayın kendi alanlarına bakabilir. Doğrulama hedefi "yalnız sözleşmesi askıya alınmış
aboneliklerin okumaları" isteseydi, bu koşul olayda taşınan üç alandan hiçbiriyle
yazılamazdı — aboneliğin durumu başka bir yerde tutulur. O durumda tek yol, koşulu ilgilendiren
alanı olaya eklemektir; bedeli, üreticinin artık tüketicinin ihtiyacını bilmesi, yani devredilen
bağın bir ucundan geri gelmesidir. Alan eklenemiyorsa 781 boşa uyandırma kaçınılmazdır ve
seçim, süzgecin yeri değil, hangi maliyetin kabul edileceğidir.

## Kuralın Görünmezliği Bir Yüzeydir

Çıktının son iki satırı tek bir şey gösteriyor. Kural kümesine, doğrulama hedefine dokunmayan
yeni bir kural eklendi: `olcum.okuma.*` desenli K11, olayları ikinci bir hedefe veriyor.
Doğrulama hedefinin teslim sayısı **145'te kaldı**, hata sayısı sıfır kaldı, hiçbir ölçüt
kıpırdamadı.
Toplam teslim ise 145'ten 1.257'ye çıktı — akıştaki bütün okuma olayları artık ikinci bir yere
de gidiyor.

Bu, yönlendirmeyi devretmenin en pahalı kısıtıdır. Kural bir veri kalemi olduğu için:

- Kaynak deposundaki farkta görünmez; işlev kodunda tek satır değişmez.
- Var olan hedeflerin ölçütlerini bozmaz, dolayısıyla hiçbir uyarı eşiğini aşmaz.
- Yeni hedefe giden olayların içeriği üreticinin niyetinden bağımsızdır: üretici okumayı
  doğrulama için yazmıştı, kural onu başka bir yere de verdi.

Aynı görünmezlik ters yönde de çalışır. Bir kural silindiğinde ya da deseni daraltıldığında
hedef trafik almayı bırakır; işlev hata vermez, çünkü hiç çağrılmaz. Çağrı sayısı sıfıra iner
ve sıfır, bir arıza belirtisi gibi değil, "bu saatte iş yok" gibi okunur. Birinci ölçümdeki
433 sessiz düşme ile bu durum arasında hiçbir gözlemsel fark yoktur: ikisinde de olay yazılmış,
kabul edilmiş ve hiçbir yere gitmemiştir. Aradaki farkı görebilmenin tek yolu, üretilen olay
sayısı ile teslim edilen olay sayısını ayrı ayrı sayıp aralarındaki farkı izlemektir.

Kısıtın etrafından dolaşmanın üç yolu var ve üçü de sayılabilir bir bedel ister. Birincisi,
kural kümesini kaynak deposunda tutup değişiklikleri kod gibi incelemektir; bedeli, her kural
değişikliğinin yayın hattına girmesi ve dakikalar süren bir işlemin saatlere yayılmasıdır.
İkincisi hedef başına teslim sayacı tutmaktır; K11 eklendiğinde toplam teslimin 145'ten
1.257'ye çıkması ancak böyle görülür ve bedeli, on kurallı bir kümede on ayrı sayaç ile bunları
okuyan bir eşik kümesidir. Üçüncüsü desen genişliğini yasaklamaktır — yakala-tümü kuralı
kaldırılır, `*` yalnız son bölümde kullanılır. Bunun bedeli birinci ölçümdeki ilk satırdır:
desen daraldıkça eşleşmeyen olay sayısı yeniden yükselir ve 433 olay sessizce düşer.

Üçü arasında seçim yapılırken bakılacak sayı, düşen olayın maliyeti ile fazladan teslimin
maliyetinin karşılaştırılmasıdır. Ölçüm ağında düşen bir doğrulama hatası faturaya yanlış
tüketim olarak yansır; fazladan bir arşiv teslimi yalnız depolama yazar. Bu ağda kural kümesi
geniş, süzgeç kuralda, sayaç hedef başınadır.

## Özet

- Olay veri yolu yönlendirme kararını üreticiden alır: üretici hedefi bilmez, hedefi kural
  seçer. Karşılığında kural bir veri kalemi olur ve kod incelemesinin dışına çıkar.
- Aynı 2.000 olaylık akışta dört kurallı küme 433 olayı hiçbir hedefe vermedi ve bunu hata
  üretmeden yaptı; sessiz düşme veri yolunun öntanımlı davranışıdır.
- Kural sayısı yediye çıkınca eşleşmeyen sıfırlandı ama 1.119 olay çok hedefli oldu; on kurallı
  kümede toplam teslim 5.551'e, olay başına 2,78 uyandırmaya çıktı.
- Süzgeç kuralda 145 olay taşıdı, hedefte 926 olay taşıdı ve bunların 781'i işlevi boşuna
  uyandırdı; taşıma tarafındaki fark 0,14 birime karşı 0,93 kurgu birimdir.
- Yeni bir kural, var olan hedefin teslim sayısını 145'te bırakıp toplam teslimi 1.257'ye
  çıkardı ve hiçbir hata üretmedi; kuralın görünmezliği bu yüzden bir yüzeydir.
- Sessiz düşme ile silinmiş kural aynı belirtiyi verir: her ikisinde de çağrı sayısı sıfırdır.
  Aradaki farkı ayırt etmenin yolu, üretilen olay sayısı ile teslim sayısını ayrı saymaktır.

## Sonraki Adım

Yönlendirme kararı verildi: hangi olayın kimi uyandıracağı artık kural kümesinde yazılı. Ama
bu ölçümde bir şey hiç sorulmadı — hedef uyandığında **ayakta değilse** ne olur? Model her
teslimi başarılı saydı; oysa işlev kısılabilir, hata verebilir, eşzamanlılık sınırına çarpabilir.
Olayı tutan, yeniden deneyen ve tüketici hazır olana kadar bekleten bir katman gerekir. Sonraki
ders bu katmanı hizmet olarak ölçer: kuyruk ve konu servisleri devralındığında hangi kararlar
elden çıkar, görünürlük süresi hangi eşikte çift işleme, hangi eşikte gecikme üretir.
