Transaction'lar sadece menüden açılan ekranlar değil

troia-platformu-nasil-calisir yazısında transaction'ları "bağımsız bir TROIA uygulamasını tanımlayan veritabanı kaydı" olarak tanımlamıştım. Bir transaction'ı kullanıcı menüden/kısayoldan açabilir, ama kod içinden de programatik olarak çağırabilirsiniz — ve bu çağrının nasıl yapıldığı (senkron mu, sunucuda mı, arayüzsüz mü) davranışı kökten değiştiriyor.

Transaction, en büyük kapsam (scope) birimidir

Belgelerin önemli bir tanımı: transaction'lar, TROIA kodunu çalıştırabilen tek yapı. troiada-degisken-kapsamlari yazısında ele alacağım GLOBAL değişkenler, bir transaction içinde tanımlandığında o transaction kapsamındaki her dialog/class koduna açık oluyor — yani transaction, değişken kapsamının en geniş sınırını çiziyor.

Dört çağırma biçimi

1. Basit, asenkron çağrı — çağıran kod beklemeden devam eder:

CALL TRANSACTION {transactionadi} [({girdiparametreleri})];

2. Senkron çağrı, çıktı parametreli — çağıran kod, çağrılan transaction kapanana kadar durur:

CALL TRANSACTION {transactionadi} [({girdiparametreleri})] WITH WAIT [({ciktiparametreleri})];

WITH WAIT kullanıldığında, çağrılan transaction açıkken çağıran transaction'a erişilemez — kullanıcı, alt işlem bitene kadar üst ekranla etkileşemez. Bu, troiada-dialog-yasam-dongusu yazısındaki CALL DIALOG'un davranışına çok benziyor, ama burada tüm bir transaction seviyesinde.

3-5. Sunucu tarafı (arayüzsüz) çağrı — üç varyasyon, parametrelerin yerleşimine göre:

CALL TRANSACTION {transaction} ({girdiparametreleri}) INSERVER;
CALL TRANSACTION {transaction} INSERVER ({girdiparametreleri});
CALL TRANSACTION {transaction} ({girdiparametreleri}) INSERVER ({ciktiparametreleri});

INSERVER ile çağrılan bir transaction, istemci arayüzü olmadan, sunucuda tüm standart transaction işlemlerini simüle ederek çalışır — troiada-paralel-islem yazısındaki CALL TRANSACTION ... ONTHREADGROUP ... EXCLUSIVEDB örneğinde gördüğünüz kalıp da bu INSERVER ailesinin bir uzantısıydı.

Parametre geçişi ve TRANSCALLED olayı

Girdi parametreleri, çağrılan transaction içinde global değişkenlere dönüşüyor. Parametre varsa, çağrılan transaction'ın ilk dialog'unun AFTER olayından hemen sonra TRANSCALLED olayı tetikleniyor. Bu olayı implemente etmek zorunlu değil — tanımlamazsanız, parametreler global değişken olarak zaten mevcut olur ama "parametre geldi" anına özel bir tepki veremezsiniz.

Batch transaction'lar: zamanlanmış görevler

Bir transaction, işletim sistemi zamanlayıcısı (Windows Task Scheduler, Linux crontab) üzerinden batch transaction olarak da tetiklenebiliyor. Bu modda sistem, transaction'ın normal başlangıç adımlarını ve SYST00'da tanımlı "Batch Code" sekmesindeki kodu çalıştırıyor. İstemci tabanlı (görünür arayüzlü) ya da konsol tabanlı sunucu yönetim aracıyla tetiklenebilir. troiada-message-komutu yazısında bahsettiğim gibi, batch modda MESSAGE çağrıları otomatik cevaplanıyor — bu iki bilgiyi birleştirdiğinizde, bir batch transaction yazarken kullanıcı onayına dayalı hiçbir akış kurmamanız gerektiği daha da netleşiyor.

Transaction bilgisini okumak

Değişken Ne döner
SYS_TRANSACTION Transaction adı
SYS_TRANSACTIONID Transaction ID
SYS_ISBATCHTRANSACTION Batch modda mı çalışıyor
SYS_ISSERVERONLYTRANSACTION Sadece sunucu modunda mı (INSERVER) çalışıyor
SYS_TRANCREATEDBY/SYS_TRANCREATEDAT Oluşturan/oluşturma tarihi
SYS_TRANMODIFIEDBY/SYS_TRANMODIFIEDAT Son değiştiren/tarih

Aynı kod parçası hem interaktif hem batch modda çalışabilecekse, SYS_ISBATCHTRANSACTION kontrolüyle davranışı dallandırmak (örneğin batch'te MESSAGE yerine bir log dosyasına yazmak) genelde daha güvenilir bir tasarım.

Gerçek bir örnek: bir onay transaction'ını sunucu tarafında tetiklemek

/* Bir sipariş onaylandığında, arayüzsüz bir muhasebe kaydı transaction'ını tetikler. */
LOCAL:
    INTEGER SONUCKODU;

CALL TRANSACTION MUHKAYT01 (SIPARISNO, TUTAR) INSERVER (SONUCKODU);

IF SONUCKODU <> 0 THEN
    MESSAGE 'Muhasebe kaydı oluşturulamadı, kod: ' + SONUCKODU TYPE ERROR;
ENDIF;

Sık yapılan hatalar

  • WITH WAIT'in çağıran ekranı tamamen bloke ettiğini unutmak — kullanıcının üst ekranla hiç etkileşemeyeceğini hesaba katmadan uzun süren bir alt transaction'ı WITH WAIT ile çağırmak, kullanıcı deneyimini "asılı kalmış" gibi hissettirebilir.
  • Batch transaction'da TRANSCALLED'ı interaktif senaryo gibi tasarlamak — batch'te kullanıcı etkileşimi olmadığını unutup, bu olayda bir onay/mesaj akışı kurmaya çalışmak işe yaramaz.
  • INSERVER çağrısının gerçek bir arayüz simüle ettiğini unutmak — arayüz olmasa da transaction'ın standart açılış/kapanış mantığı (dialog olayları dahil) çalışır; bu yüzden INSERVER ile çağrılan bir transaction'ın dialog kodunda görsel bir varsayım (örneğin bir kontrolün her zaman dolu olduğu varsayımı) yapmak hataya yol açabilir.
  • SYS_ISBATCHTRANSACTION kontrolünü atlayıp aynı kodu her ortamda aynı şekilde davranacakmış gibi yazmak — interaktif ve batch modun farklı gereksinimleri olduğunu (özellikle mesajlaşma tarafında) koda yansıtmamak, üretimde "neden kimse onaylamadan geçti" gibi sorulara yol açar.

Sıradaki adım

Bir sonraki yazıda değişken kapsamlarına (GLOBAL/MEMBER/LOCAL/OBJECT) daha derinlemesine, özellikle OBJECT anahtar kelimesinin bağlama göre nasıl farklı davrandığına değineceğim.