Etzel Art of Digital Manufacturing
Bize ulaşın
Lunex 1.6.0 kullanım kılavuzu

Siparişi onaylayın; hata olursa değişiklikleri geri alın

İki yazmayı birlikte yapın; stok yetersizliği ve teknik hatada verinin geri alındığını doğrulayın.

Bir siparişi onaylamak bu örnekte iki değişikliktir: siparişin durumunu APPROVED yapmak ve ürün stoğunu azaltmak. Bunlardan yalnız biri kalıcılaşırsa veri tutarsız olur. Transaction, bu değişikliklerin birlikte kalıcılaşmasını (commit) veya birlikte geri alınmasını (rollback) sağlar.

Örnek proje bu işlemi approveOrder API’sinden çağırır. Önceki bölümde iptal ettiğiniz ORD-2001 yerine aşağıdaki yeni siparişleri kullanın.

1. Başarılı onayı deneyin

  1. getStock → COFFEE-01 ile başlangıç stoğunun 8 olduğunu doğrulayın.
  2. createOrder üzerinden şu siparişi ekleyin:
{"orderId":"ORD-3001","customerId":"C-100","sku":"COFFEE-01","quantity":3}
  1. approveOrder → Try it açın. Target → Running project, orderId = ORD-3001, failAfterWrite = false ve Response content type (Accept) → No preference seçip Send kullanın.
  2. 200, status: APPROVED, version: 1 bekleyin.
  3. Ayrı getOrder ve getStock istekleriyle siparişin onaylandığını ve stoğun 5 olduğunu doğrulayın.

Aynı siparişi yeniden onaylamaya çalışın: 409 / ORDER_NOT_NEW gelir, stok tekrar azalmaz.

2. Stok yetmediğinde geri almayı görün

createOrder ile dokuz adetlik ikinci siparişi oluşturun:

{"orderId":"ORD-3002","customerId":"C-100","sku":"COFFEE-01","quantity":9}

approveOrder içinde orderId = ORD-3002, failAfterWrite = false gönderin. 422 / INSUFFICIENT_STOCK bekleyin.

Stok yetersizliğinde onayın 422 yanıtıyla geri alınması

Ardından iki ayrı okuma yapın:

OkumaBeklenen değer
getOrder → ORD-3002status: NEW, version: 0
getStock → COFFEE-01available: 5

Akış önce siparişi onaylamayı denediği halde son durumda sipariş NEW kalır. Bu, transaction içindeki ilk yazmanın da geri alındığını gösterir. Yalnız hata yanıtını görmek yeterli değildir.

Geri alma sonrasında siparişin NEW ve version 0 olarak okunması

3. İki yazmadan sonra teknik hata üretin

createOrder ile üçüncü siparişi ekleyin:

{"orderId":"ORD-3003","customerId":"C-100","sku":"COFFEE-01","quantity":2}

approveOrder içinde orderId = ORD-3003, failAfterWrite = true gönderin. Bu alan örneğe özel bir hata anahtarıdır: sipariş ve stok güncellendikten sonra bilinçli exception üretir. Yanıt 500 / APPROVAL_FAILED olur.

Ayrı okumalarda ORD-3003 hâlâ NEW / version: 0, kahve stoğu hâlâ 5 olmalıdır. İki yazma da geri alınır. Sonra aynı siparişi failAfterWrite = false ile onaylayın: 200, APPROVED / version: 1 ve stok 3 bekleyin.

Kendi iş akışınıza taşırken bu gösterim parametresini sözleşmeden ve ona bağlı hata dalını akıştan kaldırın.

4. Transaction sınırını inceleyin

Source → approve.camel.yaml → Designer içinde iki akış vardır:

  • approve-order, API isteğini alır ve alt işlemi çağırır. Teknik hata varsa kullanıcıya güvenli bir hata yanıtı verir.
  • approve-transaction, Transacted ile başlayıp bütün veritabanı değişikliklerini aynı transaction içinde yürütür.

İki akış direct:approveTransaction ile aynı çalışan proje içinde eşzamanlı bağlanır. Bu bağlantı yeni HTTP isteği veya bağımsız mesaj kuyruğu değildir. Teknik hatanın yanıta çevrilmesi transaction’ı yürüten çağrıdan sonra, dıştaki Catch içinde yapılır; hata içeride başarıya çevrilip yarım işin commit edilmesine izin verilmez.

database.camel.yaml içindeki bağlantı ve transaction ayarı:

- beans:
    - name: ordersDb
      type: '#class:org.apache.commons.dbcp2.BasicDataSource'
      properties:
        driverClassName: org.postgresql.Driver
        url: '{{orders.jdbc.url}}'
        username: '{{secret:help-order-lab-db/username}}'
        password: '{{secret:help-order-lab-db/password}}'
        maxTotal: 4
        maxWaitMillis: 5000
        validationQuery: SELECT 1
    - name: ordersTransactionManager
      type: '#class:org.springframework.jdbc.datasource.DataSourceTransactionManager'
      properties:
        dataSource: '#bean:ordersDb'
    - name: ordersRequired
      type: '#class:org.apache.camel.spring.spi.SpringTransactionPolicy'
      properties:
        transactionManager: '#bean:ordersTransactionManager'
        propagationBehaviorName: PROPAGATION_REQUIRED

SQL adımları ile transaction manager aynı ordersDb nesnesini kullanır. Sadece aynı sunucu adresini yazmak veya iki ayrı bağlantıya aynı adı vermek işlemleri otomatik birleştirmez. ordersRequired, çağrıda bu yöneticiye ait bir transaction varsa ona katılır; yoksa yeni transaction açar.

Transaction’ın giriş adımı:

- transacted:
    ref: ordersRequired

Tam akış dosyası indirilen projededir. Designer içinde Transacted, SQL, Choice ve Rollback adımlarını; Code içinde bütün kapsamı birlikte inceleyebilirsiniz.

5. Aynı anda gelen siparişlerde stoğu koruyun

Örnek siparişi SELECT … FOR UPDATE ile okur. Aynı siparişi onaylamak isteyen başka işlem, ilk transaction bitene kadar o satırın kilidini bekler; sonra yeni durumu görür.

Stok azaltma ve yeterlilik kontrolü tek SQL ifadesindedir:

UPDATE products
SET available = available - :#${exchangeProperty.selectedOrder[quantity]}
WHERE sku = :#${exchangeProperty.selectedOrder[sku]}
  AND available >= :#${exchangeProperty.selectedOrder[quantity]}

Bu adım CamelSqlUpdateCount = 0 döndürürse stok ayrılamamıştır. Akış 422 yanıtını hazırlayıp transaction’ı geri alınacak olarak işaretler:

- rollback:
    markRollbackOnly: true

Önce stoğu okuyup, daha sonra koşulsuz düşmek eşzamanlı isteklerde fazla satışa yol açabilir. Bu örnekte koşul ve azaltma aynı veritabanı işleminde yapılır. Sipariş satırının kilidi ve transaction bitişi arasına uzun HTTP çağrıları veya kullanıcı bekleyişi koymayın.

6. Geri almanın kapsamadığı işleri ayırın

Bu transaction yalnızca tek veritabanında, aynı bağlantı yöneticisine katılan SQL işlemlerini kapsar. Gönderilmiş e-postayı, başka sistemin kabul ettiği HTTP isteğini veya bağımsız bir kuyruğa bırakılmış mesajı geri çekmez. Message Monitor kayıtları da iş tablolarıyla birlikte silinmez; başarısız denemeyi araştırabilmeniz için ayrı tutulur.

Sipariş onaylandıktan sonra dış sisteme bildirim gerekiyorsa “veritabanı commit oldu, bildirim gönderilemedi” durumunu ayrıca tasarlayın. Örneğin gönderilecek işi aynı transaction içinde bir görev tablosuna kaydedip sonradan teslim etmek bu boşluğu yönetmenin bir yoludur; dış alıcıda tekrar teslimata dayanıklılık yine gerekir. Bu örnek dağıtık transaction veya bildirim teslimi kurmaz.

Sonraki adım: Tekrar denemeye karar verin ve hatanın izini bulun.

Lunex’i kendi entegrasyonunuzla görün

Kılavuzda okuduklarınızı kendi sistemlerinizle deneyelim. Demo için bize yazın.