---
title: 'Bağımlılık ve Tetikleme'
source: 'https://academia.sh/tr/kurslar/veri-hatlari/bagimlilik-ve-tetikleme'
course: 'Veri Hatları ve Orkestrasyon'
language: tr
updated: '2026-08-17T18:08:49+00:00'
license: 'CC BY-SA 4.0'
---

# Bağımlılık ve Tetikleme

Zincirin başındaki görevi neyin başlattığının ve aynı işin kaç kez ve ne zaman koştuğunun ölçülmesi: kaynağın yükü üç dönemde bir adım gecikmeli başlayıp dört dönemde iki parça hâlinde gelirken sabit takvim 12 koşumun 3'ünü boş, 3'ünü yarım bitiriyor ve altı dönem eksik kalarak tüketimi 2200'den 900 satıra düşürüyor, takvime iki dönemlik emniyet penceresi eklendiğinde koşum 24'e çıkıyor ve on iki dönemin tamamı ikinci kez işleniyor ama bir dönem yine eksik kalıyor, veri hazırlığı tetikleyicisi 12 koşumla boş ve yarım koşum üretmeden tam sonucu veriyor ve bedeli yedi dönemlik toplam gecikme oluyor, hazırlık ölçütü sabit satır sayısına bağlandığında ise dört dönem hiç tetiklenmiyor.

Önceki ders hattı kırk sekiz görevlik bir çizge olarak kurdu ve bir görev düştüğünde kaçının hiç
koşamadığını saydı. Çizgenin söylemediği tek şey vardı: zinciri kim başlatıyor. Otuz altı görev
bir başka görevin bitmesiyle tetiklenir — bağımlılık tetiklemesi çizgenin kendisidir. Geriye
kalan on iki `al` görevinin atası yoktur ve onları çizge değil, dışarıdan bir karar çalıştırır.

Bu ders o kararı üç sınıfa ayırır ve aynı hatta ölçer. Ölçülen sayı basit bir sorunun yanıtıdır:
**aynı iş kaç kez ve ne zaman koştu.** Bir görevin fazladan koşması bedava değildir, hiç koşmaması
ise sessizdir; iki kusur aynı tabloda yan yana durur.

- **OR9.** Kaynak, hat ve varış planı **kurgudur**; gerçek bir zamanlayıcı, iş akışı ürünü ya da
  mesaj sistemi çağrılmaz. Tohum **20260218**, ölçü koşumdan bağımsızdır.
- **OR10.** Bir **adım** bir dönemdir. **Ham süre yazılmaz**; gecikme **dönem** olarak sayılır.
- **OR11.** Kaynağın yükü ya kendi döneminde ya bir adım gecikmeli başlar, ve bir ya da iki
  **parça** hâlinde gelir. İki bilgi de tohumdan türetilir, elle seçilmez.
- **OR12.** **Boş koşum**, hiçbir satır görmeden biten görevdir. **Yarım koşum**, dönemin
  satırlarının yalnız bir bölümünü gören görevdir.
- **OR13.** Bu derste yazım **anahtarlıdır**: aynı dönemin ikinci koşumu satır çoğaltmaz. Çoğalma
  sonraki dersin konusudur ve buradaki sayıları kirletmemesi için dışarıda tutulur.
- **OR14.** Taban çizgisi **orkestrasyonsuz koşumdur**: elle konmuş sabit takvim, yeniden deneme
  yok, hazırlık ölçütü yok.
- **OR15.** Kuyruk, konu ve teslim garantisi yordamı Önbellekleme, Kuyruklar ve Eşzamansız İşleme
  kursunda ölçüldü ve **tekrarlanmaz**. Buradaki soru yalnız tetikleyicinin görevi **ne zaman**
  başlattığıdır.
- **OR16.** Çözünürlük: dönem **12**, dönem başına satır **200**, sağlam tüketim **2200**.
  **Sunum üzerinde oran basılmaz**, değerin kendisi yazılır.

## Üç Tetikleyici Sınıfı

**Zaman tetikleyicisi** (trigger) en ucuz olanıdır: görev takvimde yazılı bir anda koşar, kaynağa
hiç bakmaz. Bu, hattı elle çalıştırmanın yazıya geçmiş hâlidir ve bu dersin taban çizgisidir.
Sözleşmesi tek yönlüdür — zamanlayıcı söz verir, kaynak vermez.

**Olay tetikleyicisi** kararı kaynağa devreder: kaynak bir yük parçasını hatta bıraktığında bir
bildirim yollar, görev o bildirimle koşar. Kaynak ne zaman hazır olduğunu bilen taraf olduğu için
bu daha doğru görünür. Sorun bildirimin **neyi** haber verdiğidir: bir yük iki parça hâlinde
geliyorsa iki bildirim gider ve görev iki kez koşar.

**Veri hazırlığı tetikleyicisi** (readiness trigger) kararı hattın kendisine bırakır: görev,
dönemin yükünün tamamlandığını doğrulayana kadar bekler. Boş ve yarım koşum üretmez, ama beklediği
için gecikir ve **hazırlığın ölçütünü** yazmak gerekir. O ölçüt yanlış yazıldığında görev hiç
koşmaz.

```python
# KURGUDUR. Sayac okumalari, bes asamali hat ve varis plani ders icinde
# tanimlanir; gercek bir zamanlayici, orkestrator ya da mesaj sistemi cagrilmaz.
TOHUM, M32 = 20260218, 0xFFFFFFFF


def uretec(t):
    x = ((t ^ (t >> 16)) * 2246822507) & M32
    x = ((x ^ (x >> 13)) * 3266489909) & M32
    s = [(x ^ (x >> 16)) & M32]

    def sonraki():
        s[0] = (s[0] * 1664525 + 1013904223) & M32
        return s[0] / 4294967296
    return sonraki


BOLGE = ["dogu", "bati", "kuzey", "guney", "merkez"]
TIP = ["mesken", "isyeri"]
DONEM = [f"2026-{a:02d}" for a in range(1, 13)]
ABONE = {}
for i in range(200):
    r = uretec(TOHUM + 37 * i)
    ABONE[f"A{i + 1:03d}"] = {"bolge": BOLGE[int(r() * 5)], "tip": TIP[int(r() * 2)],
                              "baslangic": 10000 + int(r() * 60000)}


def kaynak_uret():
    kayit = []
    for i, (ab, a) in enumerate(ABONE.items()):
        e = a["baslangic"]
        for d in DONEM:
            r = uretec(TOHUM + 101 * i + 7 * DONEM.index(d))
            e += 4 + int(r() * 46)
            kayit.append({"abone": ab, "donem": d, "bolge": a["bolge"], "tip": a["tip"],
                          "endeks": e, "birim": "m3"})
    return kayit


def a1_ayikla(kayit):
    ZOR = ("abone", "donem", "bolge", "endeks", "birim")
    tut = [k for k in kayit if all(a in k for a in ZOR)]
    return tut, len(kayit) - len(tut)


def a2_tekille(kayit):
    gor, tut = set(), []
    for k in kayit:
        ad = (k["abone"], k["donem"])
        if ad in gor:
            continue
        gor.add(ad)
        tut.append(k)
    return tut, len(kayit) - len(tut)


def a3_tuketim(kayit):
    tablo = {(k["abone"], k["donem"]): k for k in kayit}
    cikti, dusen = [], 0
    for k in kayit:
        i = DONEM.index(k["donem"])
        if i == 0:
            continue
        onceki = tablo.get((k["abone"], DONEM[i - 1]))
        if onceki is None:
            dusen += 1
            continue
        try:
            f = int(k["endeks"]) - int(onceki["endeks"])
        except (TypeError, ValueError):
            dusen += 1
            continue
        cikti.append(dict(k, m3=f))
    return cikti, dusen


def a4_ozet(kayit):
    top = {}
    for k in kayit:
        ad = (k["bolge"], k["donem"])
        top[ad] = top.get(ad, 0) + k["m3"]
    return top, 0


def a5_sun(ozet):
    bolge = {}
    for (b, d), v in ozet.items():
        bolge.setdefault(b, []).append(v)
    return {b: round(sum(v) / len(v), 2) for b, v in bolge.items()}, 0


def okuma_sonucu(kayitlar):
    v, _ = a1_ayikla(kayitlar)
    v, _ = a2_tekille(v)
    v, _ = a3_tuketim(v)
    oz, _ = a4_ozet(v)
    sun, _ = a5_sun(oz)
    return sun, len(v)
```

## Kurgu Varış Planı

Tetikleyicileri ayırt eden şey kaynağın davranışıdır. Kaynak takvime uysaydı üç sınıf da aynı
sonucu verirdi; ayrım kaynağın **bazen geç ve bazen bölünmüş** gelmesinden doğar. İkinci blok bu
davranışı tohumdan türetir: her dönemin yükü kendi adımında ya da bir adım sonra başlar, ve bir ya
da iki parça hâlinde gelir.

```python
KAYNAK = kaynak_uret()
TABAN_SUN, TABAN_N = okuma_sonucu(KAYNAK)
UFUK = 13


def varis_plani(gec_pay=0.25, bol_pay=0.35):
    """KURGU: her donemin yuku bir ya da iki parca gelir , bazi donemler bir adim gec baslar."""
    r = uretec(TOHUM + 11)
    plan = {}
    for d in DONEM:
        bas = DONEM.index(d) + (1 if r() < gec_pay else 0)
        parca = 2 if r() < bol_pay else 1
        plan[d] = {"bas": bas, "parca": parca, "tam": bas + parca - 1}
    return plan


PLAN = varis_plani()


def gorunen(donem, adim):
    """Bu adima kadar hatta ulasmis satirlar."""
    p, hepsi = PLAN[donem], [k for k in KAYNAK if k["donem"] == donem]
    if adim < p["bas"]:
        return []
    gelen = min(p["parca"], adim - p["bas"] + 1)
    return hepsi[:len(hepsi) * gelen // p["parca"]]


def kosumlar(kip):
    """(adim , donem) ciftleri: gorev ne zaman ve hangi donem icin kosuyor."""
    if kip == "zaman":                                   # sabit takvim
        return [(t, DONEM[t]) for t in range(12)]
    if kip == "zaman_pencere":                           # takvim , son iki donem
        return sorted((t, DONEM[g]) for t in range(UFUK) for g in (t, t - 1) if 0 <= g < 12)
    if kip == "olay":                                    # her parca bir bildirim yolluyor
        return sorted((PLAN[d]["bas"] + j, d) for d in DONEM for j in range(PLAN[d]["parca"]))
    return [(PLAN[d]["tam"], d) for d in DONEM]          # veri hazirligi


def olc(kip):
    """Yazim anahtarlidir: ayni donemin ikinci kosumu satir cogaltmaz."""
    depo, bos, yarim, sayac, tam = {}, 0, 0, {}, {}
    for adim, d in kosumlar(kip):
        v = gorunen(d, adim)
        if not v:
            bos += 1
        elif len(v) < 200:
            yarim += 1
        sayac[d] = sayac.get(d, 0) + 1
        for k in v:
            depo[(k["abone"], k["donem"])] = k
        if d not in tam and sum(1 for x in depo if x[1] == d) == 200:
            tam[d] = adim - DONEM.index(d)
    sun, n = okuma_sonucu(list(depo.values()))
    return {"kosum": len(kosumlar(kip)), "bos": bos, "yarim": yarim,
            "iki_kez": sum(1 for d in sayac if sayac[d] > 1), "eksik": len(DONEM) - len(tam),
            "gecikme": sum(tam.values()), "tuketim": n,
            "fark": {b: round(sun[b] - TABAN_SUN[b], 2) for b in TABAN_SUN}}


print("gec baslayan donem:", [d for d in DONEM if PLAN[d]["bas"] != DONEM.index(d)])
print("iki parca gelen donem:", [d for d in DONEM if PLAN[d]["parca"] == 2])
print("yuk tamamlanma gecikmesi (donem):", sum(PLAN[d]["tam"] - DONEM.index(d) for d in DONEM))
```

```
gec baslayan donem: ['2026-02', '2026-10', '2026-12']
iki parca gelen donem: ['2026-01', '2026-02', '2026-06', '2026-09']
yuk tamamlanma gecikmesi (donem): 7
```

On iki dönemin üçü bir adım gecikmeli başlıyor, dördü iki parçaya bölünüyor ve toplam yedi dönemlik
bir gecikme birikiyor. Bu, bozuk bir kaynak değildir; sayaç okumalarının bir bölümünün geç
toplanması ve büyük yüklerin bölünerek gönderilmesi sıradan işlerdir. Ölçülecek olan şudur: aynı
kaynak karşısında dört tetikleyici kurulumu kaç görev koşturuyor ve elde ne bırakıyor.

## Aynı İşin Kaç Kez ve Ne Zaman Koştuğu

Dört kurulum karşılaştırılır. `zaman` takvime bir kez bakar. `zaman + iki dönem` aynı takvime elle
konmuş bir emniyet penceresi ekler: her adımda hem o dönemi hem bir öncekini yeniden işler.
`olay` her yük parçasının bildirimiyle koşar. `veri hazırlığı` dönemin iki yüz satırı tamamlanana
kadar bekler.

```python
print(f"{'tetikleyici':<20}{'kosum':>6}{'bos':>5}{'yarim':>7}{'iki kez':>9}"
      f"{'eksik':>7}{'gecikme':>9}{'tuketim':>9}")
for kip, ad in (("zaman", "zaman"), ("zaman_pencere", "zaman + iki donem"),
                ("olay", "olay"), ("hazirlik", "veri hazirligi")):
    o = olc(kip)
    print(f"{ad:<20}{o['kosum']:>6}{o['bos']:>5}{o['yarim']:>7}{o['iki_kez']:>9}"
          f"{o['eksik']:>7}{o['gecikme']:>9}{o['tuketim']:>9}")
print()
print("zaman sapmasi          :", olc("zaman")["fark"])
print("zaman + iki donem      :", olc("zaman_pencere")["fark"])
print("olay ve veri hazirligi :", olc("hazirlik")["fark"])
```

```
tetikleyici          kosum  bos  yarim  iki kez  eksik  gecikme  tuketim
zaman                   12    3      3        0      6        0      900
zaman + iki donem       24    3      4       12      1        5     2000
olay                    16    0      4        4      0        7     2200
veri hazirligi          12    0      0        0      0        7     2200

zaman sapmasi          : {'merkez': -317.28, 'kuzey': -382.88, 'dogu': -175.69, 'bati': -240.59, 'guney': -251.72}
zaman + iki donem      : {'merkez': -100.63, 'kuzey': -145.19, 'dogu': -65.54, 'bati': -86.82, 'guney': -80.46}
olay ve veri hazirligi : {'merkez': 0.0, 'kuzey': 0.0, 'dogu': 0.0, 'bati': 0.0, 'guney': 0.0}
```

İlk satır taban çizgisidir ve tablodaki en yanıltıcı satırdır. Sabit takvim **gecikme sütununda
sıfır** yazar; hiçbir dönem geç işlenmemiştir, çünkü hiçbir dönem beklenmemiştir. Aynı satırda
**altı dönem eksik** kalır: on iki koşumun üçü boş biter, üçü yarım. Tüketim 2200 yerine **900**
satır çıkar ve sunum beş bölgenin hepsinde çöker (−175,69 ile −382,88 arasında). **Sıfır gecikme,
beklemeyi ölçtüğü için değil, hiç beklemediği için sıfırdır.**

İkinci satır bu kusura sahada verilen yanıttır: takvimi bırakmadan bir emniyet penceresi eklemek.
Koşum sayısı 12'den **24**'e çıkar ve **on iki dönemin tamamı ikinci kez işlenir** — yani hattın
yarısı gereksiz iştir. Karşılığında eksik dönem altıdan bire iner ve tüketim 2000'e çıkar. Ama
kalan tek dönem cezasını ödetmeye devam eder: `2026-02` hem bir adım gecikmeli başlar hem iki
parçaya bölünür, üçüncü adımda tamamlanır ve iki dönemlik pencere üçüncü adımda ona artık bakmaz.
Sunum hâlâ her bölgede yanlıştır (−65,54 ile −145,19 arasında). **Pencereyi genişletmek bir sınır
seçmektir ve seçilen her sınır bir varış planını dışarıda bırakır.**

Üçüncü satır olay tetikleyicisinin hem gücünü hem kusurunu gösterir. Eksik dönem sıfırdır, sunum
sapması boştur, sonuç tamdır. Buna karşılık **16 koşum** yapılmıştır: iki parça gelen dört dönem
iki kez işlenmiştir ve o dördün ilk koşumu **yarım** koşumdur. Bu ders yazımı anahtarlı tuttuğu
için yarım koşum zarar vermiyor; sonraki ders aynı yarım koşumun yazım anahtarsız olduğunda ne
yaptığını ölçecek.

Dördüncü satır aranan kurulumdur ve neyin satın alındığını açıkça yazar. Veri hazırlığı
tetikleyicisi **12 koşumla** sonucu tam verir: boş koşum yok, yarım koşum yok, ikinci kez işlenen
dönem yok. Ödediği bedel **gecikme sütunundaki yedidir** — yükün tamamlanmasını beklediği için
toplam yedi dönem geç bitirmiştir. Bu sayı kaynağın gecikmesiyle birebir aynıdır, yani tetikleyici
kendi başına gecikme eklemez; yalnızca kaynağın gecikmesini **görünür kılar**.

## Hazırlık Ölçütünün Kendi Kusuru

Veri hazırlığı tetikleyicisinin bedeli yalnız gecikme değildir. Görevin ne zaman koşacağını artık
bir **ölçüt** belirler ve o ölçüt elle yazılır. Yukarıdaki kurulumda ölçüt "iki yüz satır geldi"
biçimindeydi; iki yüz sayısı kaynağın bugünkü abone sayısıdır ve bir varsayımdır.

```python
# Dokuzuncu donemden itibaren dort abone aboneligini sonlandirdi: kaynak 196 satir gonderiyor.
AYRILAN = {"A197", "A198", "A199", "A200"}
KAYNAK2 = [k for k in KAYNAK if not (k["donem"] >= "2026-09" and k["abone"] in AYRILAN)]
SAYI = {d: sum(1 for k in KAYNAK2 if k["donem"] == d) for d in DONEM}
print("donem basina satir:", sorted(set(SAYI.values())), " toplam:", len(KAYNAK2))
print(f"{'hazirlik olcutu':<28}{'kosan donem':>12}{'satir':>7}{'tuketim':>9}")
sonuc = {}
for ad, esik in (("kaynagin bildirdigi parca", 0), ("sabit 200 satir", 200)):
    kosan = [d for d in DONEM if SAYI[d] >= esik]
    kabul = [k for k in KAYNAK2 if k["donem"] in kosan]
    sun, n = okuma_sonucu(kabul)
    sonuc[ad] = sun
    print(f"{ad:<28}{len(kosan):>12}{len(kabul):>7}{n:>9}")
a, b = sonuc["kaynagin bildirdigi parca"], sonuc["sabit 200 satir"]
print("sabit esigin sapmasi:", {x: round(b[x] - a[x], 2) for x in a})
```

```
donem basina satir: [196, 200]  toplam: 2384
hazirlik olcutu              kosan donem  satir  tuketim
kaynagin bildirdigi parca             12   2384     2184
sabit 200 satir                        8   1600     1400
sabit esigin sapmasi: {'merkez': -37.59, 'kuzey': -10.75, 'dogu': -18.5, 'bati': 8.11, 'guney': -13.98}
```

Dört abone aboneliğini sonlandırdığı için kaynak dokuzuncu dönemden sonra 196 satır gönderiyor.
Bu bir bozulma değildir; kaynak doğru veriyi eksiksiz yolluyor. Sabit eşiğe bağlanmış hazırlık
ölçütü ise ikinci yüzüncü satırı beklediği için **dört dönemde hiç tetiklenmiyor**: koşan dönem
12 yerine **8**, tüketim 2184 yerine **1400**. Hiçbir görev hata vermiyor, hiçbir günlük satırı
yazılmıyor, hattın durumu bekliyor olarak kalıyor.

Sapma satırı bu kusurun sunumda nasıl göründüğünü söyler: merkez −37,59 düşerken **batı +8,11
yükseliyor**. Kayıp dönemler bölgelere eşit dağılmadığı için sapmanın işareti bile tutarlı
değildir, yani sunuma bakarak "dört dönem eksik" sonucuna varmak olanaksızdır. Doğru ölçüt sabit
bir sayı değil, kaynağın **kendi bildirdiği parça tamlığıdır**; o kullanıldığında on iki dönemin
tamamı koşar ve tüketim 2184 satırda kalır.

## Özet

- Çizgedeki otuz altı görev bağımlılıkla tetiklenir; on iki `al` görevini dışarıdan bir karar
  başlatır ve bu karar zaman, olay ya da veri hazırlığı tetikleyicisidir.
- Taban çizgisi olan sabit takvim **gecikme sütununda sıfır** yazar ama **altı dönemi eksik**
  bırakır: 12 koşumun 3'ü boş, 3'ü yarım biter ve tüketim 2200 yerine **900** satır olur.
- Takvime iki dönemlik emniyet penceresi eklemek koşumu **24**'e çıkarır ve on iki dönemin tamamını
  ikinci kez işletir; eksik dönem bire iner ama sunum hâlâ her bölgede yanlıştır.
- Olay tetikleyicisi tam sonucu verir, bedeli **16 koşum** ve dört dönemin ikinci kez işlenmesidir;
  iki parça gelen dört dönemin ilk koşumu **yarım koşumdur**.
- Veri hazırlığı tetikleyicisi **12 koşumla** boş ve yarım koşum üretmeden tam sonucu verir; bedeli
  **yedi dönemlik toplam gecikmedir** ve bu gecikme kaynağınkiyle birebir aynıdır.
- Hazırlık ölçütü sabit satır sayısına bağlandığında dört dönem **hiç tetiklenmez**: tüketim
  2184'ten 1400'e iner, sapmanın işareti bölgeye göre değişir ve hiçbir görev hata vermez.

## Sonraki Adım

Bu dersteki bütün koşumların ortak bir yanı vardı: hiçbiri başarısız olmadı. Görev ya koştu ya hiç
tetiklenmedi; koştuğunda gördüğü satırların tamamını yazdı. Gerçek bir hatta üçüncü bir sonuç
vardır — görev koşar, yazmaya başlar ve **ortasında düşer**. Yarım koşum bu derste zararsızdı,
çünkü yazım anahtarlıydı ve eksik kalan parça bir sonraki koşumda tamamlandı. Sonraki ders o
güvenceyi kaldırır ve iki soruyu ölçer: yarım yazılan bir bölüm sunuma ne yapıyor, ve düşen görevi
yeniden denemek hattı onarıyor mu yoksa satır mı çoğaltıyor.
