Bir kaynak sistem mesajı Lunex’e asenkron olarak verdiğinde onayını alır ve işine devam eder. Çoğu zaman mesajı yeniden gönderebileceği bir kuyruğu yoktur; SAP’ye senkron bir BAPI çağrısı da SAP tarafında hiçbir şey saklamaz. Lunex mesajı tutmazsa kimse tutmaz. Bu sayfa Lunex’in böyle bir mesaj için üstlendiği sorumluluğu ve route’un hedef bir mesajı reddettiğinde ne yapacağını açıklar.
Sorumluluk sözleşmesi
| Akış | Lunex’in sorumluluğu |
|---|---|
| Asenkron | Lunex mesajı kalıcı bir Artemis kuyruğuna yazdıktan sonra kaynağı onaylar. Mesajdan o andan itibaren, hedef sistem mesajı kabul edene veya yetkili bir kişi onu bilerek silene kadar sorumludur. Dead letter’lar hiçbir zaman otomatik silinmez. |
| Senkron | Hedefin hatası çağırana döner ve Lunex hiçbir şey saklamaz. Mesajı çağıran sistem tutar ve hatayı kendisi ele alır. |
Asenkron bir akış iki parçadan oluşur: mesajı kalıcı kuyruğa yazan kabul akışı ve kuyruğu transacted: true ile tüketen ayrı bir teslim akışı. Kurulum adımları kuyruk oluşturma ve teslim rehberindedir.
Teslim en az bir kez yapılır: Hedef mesajı kabul ettikten sonra onay kaybolursa mesaj tekrar işlenir. Hedef tarafı iş anahtarıyla tekrarı tanıyacak şekilde tasarlayın. Yeniden teslim sırayı korumaz; bekleyen bir mesajın arkasındaki mesajlar işlenmeye devam eder.
Hata olduğunda: fırlatın veya park edin
Teslim akışı her hata için iki şeyden birini yapar. Hangi hatanın hangisi olduğuna route’u yazan karar verir; Lunex hataları sınıflandırmaz.
| Karar | Ne zaman? | Sonuç |
|---|---|---|
| Fırlat | Geçici olabilecek her hata: bağlantı kesintisi, kilitli kayıt, bakımdaki hedef. Sınıflandırmadığınız her hata da buraya girer. | Teslim geri alınır; broker mesajı artan beklemelerle yeniden verir. Bütün denemeler başarısız olursa mesaj dead letter olur. |
| Park et | Hedefin yeniden denendiğinde de aynı şekilde reddedeceğini bildiğiniz hata: var olmayan sipariş, bloke malzeme. | Mesaj hemen dead letter olur; hedef boşuna denenmez ve mesaj hemen görünür. Neden giderildiğinde yeniden denenebilir. |
Hatayı yakalayıp handled olarak bitirmek ikisi de değildir: teslim başarılı sayılır ve mesaj kaybolur.
Yeniden teslim süresi
Paket içindeki broker geri alınan teslimi 1 dakika sonra, sonra her seferinde iki kat (en çok 30 dakika) bekleyerek yeniden verir. Her bekleme %15’e kadar rastgele sapar; bir kesintiden sonra bekleyen mesajlar hedefe aynı anda gitmez. 30. başarısız teslimden sonra, yaklaşık 12,5 saat içinde, mesaj dead letter olur. Bu süre, planlı bir SAP bakımının mesajları dead letter’a düşürmeden atlatılmasını sağlar. Değerleri yönetici kurulum rehberindeki ayarlarla değiştirir.
Tüketicinin broker’dan önceden aldığı mesajlar, yeniden teslim için bekleyen bir mesajın arkasında bekler. Bağlantı bean’inde consumerWindowSize: 0 kullanırsanız önceden alma kapanır ve kuyruğun geri kalanı beklemeden işlenir.
Mesajı park edin
Teslim akışı, mesajın işlenemeyeceğine ve yeniden denemenin işe yaramayacağına karar verdiğinde tek bir adım yazar:
- throwException:
exceptionType: io.etzel.lunex.ParkMessage
message: "SAP returned E: material blocked"
Başka bir şey eklemezsiniz: proje ayarı, bean, Kamelet veya route yapılandırması gerekmez. Her Run ve paketlenmiş entegrasyon bu hatayı her route’ta yakalar ve mesajı park eder:
- Mesajı, route’un kuyruktan aldığı haliyle saklar: özgün gövde ve özgün başlıklar. Route’un park kararından önce değiştirdiği gövde (örneğin SAP yanıtı) ve eklediği başlıklar dead letter’a girmez.
messagemetnini dead letter’ınLunexParkReasonözelliğine yazar. Aynı metin Message Monitor’de çalışmanın yakalanmış (handled) hatası olarakio.etzel.lunex.ParkMessage: SAP returned E: material blockedbiçiminde görünür. Metni destek ekibinin okuyacağı bir cümle olarak yazın.- Mesajı
DLAadresine, teslim akışının kendi Artemis bağlantısıyla kalıcı olarak gönderir. Mesajdead.letterskuyruğunda saklanır vedead.letter.eventsolay akışında görünür. Ardından teslim onaylanır ve mesaj kaynak kuyruktan silinir.
Hangi hatanın park edileceğine yalnız route’u yazan karar verir; Lunex hiçbir hatayı sınıflandırmaz. io.etzel.lunex.ParkMessage dışındaki her hata teslimi geri alır ve broker mesajı yeniden verir. Route’ta bütün Exception’lar için kendi onException tanımınız olsa bile park sinyali park edilir; Camel hataya en yakın türü seçer.
Park edilen kopya:
_AMQ_ORIG_ADDRESSve_AMQ_ORIG_QUEUEözelliklerinde mesajın geldiği adresi taşır. Yeniden deneme mesajı bu kuyruğa döndürür ve aynı teslim akışı tekrar çalışır. Bu yüzden teslim akışının kuyruğu, iş kuyruklarında olduğu gibi adresiyle aynı adı taşımalıdır.- Daha önceki bir dead letter’dan kalmış
_AMQ_ORIG_MESSAGE_IDve_AMQ_ORIG_ROUTING_TYPEözelliklerini taşımaz. - Yeni bir
JMSMessageIDalır.JMSCorrelationID, teslim edilen mesajınJMSMessageIDdeğerini taşır; park edilen mesaj bu değerle bulunur. LunexSourceMessageIdözelliğinde ilk park edilen kaynak mesajınJMSMessageIDdeğerini taşır ve yeniden denemelerde korur. Yeniden denenip tekrar park edilen bir mesaj, ilk başarısız çalışmanın Message Monitor mesaj kimliğiyle de bulunur.
Park başarısız olursa, örneğin broker’a ulaşılamazsa, teslim geri alınır ve broker mesajı yeniden verir; mesaj kaybolmaz.
Park en az bir kez yapılır: dead letter kopyası, teslim onaylanmadan hemen önce kaydedilir. Bu iki adım arasında runtime durursa veya broker bağlantısı koparsa broker mesajı yeniden verir ve akış yine park ederse aynı LunexSourceMessageId ile ikinci bir dead letter oluşur; mesaj hiçbir durumda kaybolmaz.
Sinyal yalnız şu koşullarda park eder:
- Route mesajı bir Artemis kuyruğundan
sjms2veyajmsbileşeniyle ve Artemis JMS istemcisiyle (ActiveMQConnectionFactory) tüketir. Sinyali teslim akışında veya onun çağırdığı birdirectroute’unda fırlatın; park edilen yine teslim akışının kuyruktan aldığı mesajdır. - Route kendi
routeConfigurationIddeğerini taşımaz. Bu alanı taşıyan route’a park kuralı uygulanmaz ve sinyal sıradan bir hata gibi yeniden teslime gider. Teslim akışlarındarouteConfigurationIdkullanmayın.
Kuyruktan gelmeyen bir mesajda, örneğin bir HTTP isteğinde, AMQP istemcisiyle tüketilen bir mesajda veya bir Kamelet’in içinde fırlatılan sinyal park edilmez: Lunex io.etzel.lunex.ParkMessage adını taşıyan bir hata verir. Mesaj bir kuyruktan geldiyse teslim geri alınır ve broker mesajı yeniden verir.
SAP RETURN örneği
SAP bileşeni BAPI’nin RETURN alanını yorumlamaz. Bir iş hatası Java exception olmadan döner; route bunu kontrol etmezse “malzeme bloke” gibi bir hata başarı olarak raporlanır ve mesaj tüketilir. Aşağıdaki teslim akışı, MES onaylarını SAP’ye bir RFC fonksiyonuyla gönderir ve yanıtın RETURN tablosunu kontrol eder:
- route:
id: post-mes-confirmations
from:
uri: sjms2:queue:mes.confirmations
parameters:
connectionFactory: '#mesBroker'
transacted: true
steps:
- to:
uri: sap-jco:ZMES_POST_CONFIRMATION
parameters:
destination: '#erp'
- choice:
when:
- jsonpath:
expression: "$.RETURN[?(@.TYPE in ['E','A'] && @.ID == 'ZMES' && @.NUMBER in ['001','002'])]"
steps:
- throwException:
exceptionType: io.etzel.lunex.ParkMessage
message: "SAP refused the confirmation: ${jsonpath($.RETURN[0].MESSAGE)}"
- jsonpath:
expression: "$.RETURN[?(@.TYPE in ['E','A'])]"
steps:
- throwException:
exceptionType: java.lang.IllegalStateException
message: "SAP RETURN error: ${body}"
RETURN | Route’un kararı |
|---|---|
TYPE E veya A, ID ZMES, NUMBER 001 veya 002 | Bu örnekte fonksiyonun sahibinin kalıcı olduğunu bildirdiği hatalar. Mesaj park edilir; neden, RETURN tablosunun ilk satırındaki SAP mesaj metnidir. |
Başka bir E veya A | Sınıflandırılmamış hata. Route hata fırlatır; broker mesajı yeniden verir. |
Hata yok (S, W, I veya boş) | Teslim başarılı; mesaj kuyruktan silinir. |
ZMES, 001 ve 002 örnek değerlerdir. Kendi fonksiyonunuzun hangi mesaj sınıfı ve numaralarının kalıcı olduğunu fonksiyonun sahibinden öğrenin ve yalnız bunları park edin. RETURN tablo yerine yapı döndüren fonksiyonlarda alanları $.RETURN.TYPE gibi okuyun. Bağlantı ve RFC hataları zaten exception olarak gelir ve broker tarafından yeniden denenir. SAP bağlantısı ve RETURN ayrıntıları için SAP rehberine bakın.
Dead letter’ların yeri
Her kurulumda bütün dead letter’lar DLA adresinde toplanır. Broker’ın yeniden teslim sonunda ayırdığı mesajlar ve route’ların park ettiği mesajlar aynı yere gider.
| Kuyruk | İçerik |
|---|---|
dead.letters | Her dead letter. Mesajlar yeniden denenene veya silinene kadar burada kalır. |
dead.letter.events | Yeni dead letter’ların olay akışı. Tüketen olmadığında son 1000 olayı tutar. Bu akışı tüketen bir route’un kendi başarısız mesajları akışa geri gelmez. |
Her dead letter, geldiği kuyruğu _AMQ_ORIG_QUEUE özelliğinde taşır. Yeniden deneme mesajı bu kuyruğa döndürür ve yeni bir teslim döngüsü başlar; mesaj yine başarısız olursa tekrar dead letter olur.
Dead letter’ları ajanınızla yönetin
Lunex MCP sunucusu dead letter’lar için dört araç sunar. Ajanınız (Claude Code, Codex) bu araçları sizin hesabınızla ve sizin rolünüzle çağırır; ekran yoktur, isteğinizi ajanınıza cümleyle söylersiniz.
| Araç | Ne yapar | Kim kullanabilir |
|---|---|---|
list_dead_letters | Kaynak kuyruk başına sayı ve en eski dead letter’ın zamanı; bir kuyruk seçilirse o kuyruğun dead letter’ları (en eskisi önce, en fazla 200), Message Monitor mesaj kimlikleri, yeniden denenip denenemeyeceği ve geçerli redelivery ayarları | Message Monitor’ü okuyabilen herkes |
inspect_dead_letter | Tek dead letter’ın kaynak kuyruğu, başlıkları, özellikleri (park nedeni LunexParkReason özelliğindedir) ve 64 KiB’a kadar gövdesi. Her okuma Monitor denetim kaydına yazılır | Message Monitor’ü okuyabilen herkes |
retry_dead_letters | Seçilen dead letter’ları geldikleri kaynak kuyruğa geri gönderir; orada yeni bir teslim döngüsü başlar | Yalnız platform-admin |
discard_dead_letters | Seçilen dead letter’ları kalıcı olarak siler | Yalnız platform-admin |
platform-user veya platform-developer rolüyle retry ve discard reddedilir; okuma yetkisi broker’daki hiçbir mesajı değiştirmez.
Seçim ve sayı onayı
Retry ve discard her zaman tek bir kaynak kuyrukta çalışır. Seçimi mesaj kimlikleriyle (dead letter kimliği ID:... veya Message Monitor mesaj kimliği) ve sentBefore zamanından önce gönderilmiş mesajlarla daraltabilirsiniz.
- Ajan önce
list_dead_lettersile seçimi listeler ve size sayıyı gösterir. - Siz onaylarsınız; ajan bu sayıyı
expectedCountolarak gönderir. - Lunex seçimi yeniden sayar. Sayı değişmişse hiçbir şey yapmaz ve güncel sayıyı döndürür; ajan yeniden listeleyip size sorar.
- Lunex yalnız saydığı dead letter’lara dokunur. İşlem sırasında gelen yeni dead letter’lar olduğu gibi kalır.
Her çağrı 45 saniye içinde döner. Çok büyük bir seçim bu sürede bitmezse Lunex iki mesaj arasında durur, yaptığını ve kalan sayıyı bildirir; ajan yeniden listeleyip devam eder. Listeleme de süre dolunca durur ve truncated ile eksik olduğunu söyler: kuyruk seçiliyse o ana kadar okunan dead letter’ları, seçili değilse her kuyruğun sayısını verir; süresi yetmeyen kuyrukların en eski zamanı boş kalır.
Message Monitor zamanında yanıt vermezse liste ve inceleme yine döner. Dead letter’lar eksiksizdir; yalnız Monitor mesaj kimlikleri boş kalır ve monitorLinksUnavailable alanı nedenini söyler. Bu sırada bir dead letter’ı Monitor mesaj kimliğiyle bulamazsınız; kendi ID:... kimliğiyle inceleyin.
Kaynak kuyruğu artık olmayan veya hiç kaynak kuyruğu taşımayan (örneğin DLA adresine başka bir yolla gönderilmiş) dead letter’lar yeniden denenemez. Retry bunları notReturned listesinde bildirir; mesajlar dead letter deposunda kalır. Yeniden denenen bir mesaj hâlâ başarısız olursa redelivery ayarlarına göre yeniden dead letter’lara döner; park eden bir akış onu hemen yeniden park eder.
Ajana örnek istekler
- “Dead letter’larda ne bekliyor, neden?”
- “
orders.incomingkuyruğunun dead letter’larını listele; Monitor’de açabileceğim mesaj kimlikleriyle.” - “
jms-4f2a…Monitor mesajının dead letter’ını incele; SAP ne dönmüş?” - “SAP yeniden ayakta.
confirmationskuyruğunun bütün dead letter’larını yeniden dene.” Ajan önce sayıyı gösterir, onayınızdan sonra dener. - “Malzeme kilidi kalktı; şu iki mesajı yeniden dene:
ID:…,ID:….” - “
test.orderskuyruğundaki 1 Ekim’den önceki dead letter’ları sil.” Silinen mesaj geri getirilemez.
Kayıtlar
Her inceleme bir DeadLetterRead, yeniden denenen veya silinen her dead letter bir DeadLetterRetry veya DeadLetterDiscard kaydı oluşturur. Kayıt işlemi yapanı, zamanı, kaynak mesajın kimliğini ve sonucu tutar; gövde tutmaz. Kayıtlar Message Monitor denetim kaydının saklama süresi (varsayılan 90 gün) boyunca kalır. platform-admin bunları Message Monitor’ün denetim kaydında okur. Broker işlemi başarısız olursa kayıt yazılmaz. Broker işlemi yaptıktan sonra kayıt yazılamazsa araç hata döndürür ve kaç mesajın kayıtsız değiştiğini söyler.
Acil durum: Artemis console
Lunex veya MCP erişilemezken platform-admin sol menüdeki Artemis console ile dead.letters kuyruğunda mesajları yeniden deneyebilir (retryMessage) veya silebilir (removeMessage). Konsoldaki işlemler Lunex’te hiçbir kayıt bırakmaz. Kayıt gerektiğinde araçları kullanın; konsolu yalnız Lunex’e ulaşılamadığında kullanın.
Yeni dead letter’lar için uyarı projesi
Lunex’in bir uyarı özelliği yoktur. Yeni dead letter’lardan mail veya Teams mesajıyla haberdar olmak isteyen ekip, dead.letter.events olay akışını tüketen sıradan bir Lunex projesi kurar. Ne zaman, kime ve hangi kanaldan haber verileceğine bu proje karar verir. Ajanınızdan “yeni dead letter’ları mail atan bir route” istediğinizde ajan bu bölümdeki deseni kullanır.
Desenin kuralları:
- Akışı tam kuyruk adıyla tüketin:
sjms2:queue:DLA::dead.letter.events. Yalnızdead.letter.eventsyazarsanız broker aynı adla yeni, boş bir kuyruk oluşturur ve route hiçbir olay almaz. - Mesaj gövdesini hiçbir zaman göndermeyin. Bildirim yalnız kaynak kuyruğu ve o kuyruktan gelen dead letter sayısını söyler; içeriği yetkili kişi Message Monitor’de veya ajanıyla inceler.
- Olayları kaynak kuyruğa göre belli aralıklarla toplayın. Bir kesintiden sonra yüzlerce mesaj aynı anda dead letter olabilir; her biri için ayrı mail gönderilmez.
- Kurulumda tek bir uyarı projesi akışı tüketsin. İki proje aynı kuyruğu tüketirse olayları paylaşırlar ve her biri yalnız bir kısmını görür. Birden fazla kanal gerekiyorsa aynı route’tan hepsine gönderin.
Bağlantı ve ayarlar
Broker bağlantısını kuyruk rehberindeki gibi bir bean olarak ekleyin; bu örnekte adı alertBroker. Broker kullanıcısını alert-broker, mail sunucusunun kullanıcısını alert-mail Secret’ında, System → Secrets bölümünde username ve password anahtarlarıyla tutun.
- beans:
- name: alertBroker
type: '#class:org.apache.activemq.artemis.jms.client.ActiveMQConnectionFactory'
properties:
brokerURL: '{{alert.broker.url}}'
user: '{{secret:alert-broker/username}}'
password: '{{secret:alert-broker/password}}'
Projenin application.properties dosyasına şu satırları ekleyin:
alert.broker.url=tcp://artemis:61616
alert.interval=300000
alert.smtp.host=smtp.example.com
alert.smtp.port=25
alert.mail.from[email protected]
alert.mail.to[email protected]
Aynı dosyadaki mevcut camel.jbang.dependencies listesinin sonuna, virgülle, mvn:org.apache.activemq:artemis-jakarta-client-all:2.56.0 ekleyin. Listedeki mevcut bağımlılıkları silmeyin; {{secret:...}} değerleri onlarla okunur.
alert.interval toplama aralığıdır, milisaniye; örnekteki değer 5 dakikadır. Mail sunucusu TLS istiyorsa smtp yerine smtps ve sunucunun portunu kullanın.
Uyarı route’u
- route:
id: alert-dead-letters
description: Mail new dead letters per source queue
from:
uri: sjms2:queue:DLA::dead.letter.events
parameters:
connectionFactory: '#alertBroker'
transacted: true
steps:
- setBody:
constant: ""
- aggregate:
correlationExpression:
header: _AMQ_ORIG_QUEUE
aggregationStrategy: '#class:org.apache.camel.processor.aggregate.UseLatestAggregationStrategy'
completionInterval: '{{alert.interval}}'
steps:
- removeHeaders:
pattern: '*'
- setHeader:
name: Subject
simple: '${exchangeProperty.CamelAggregatedSize} dead letter: ${exchangeProperty.CamelAggregatedCorrelationKey}'
- setBody:
simple: "${exchangeProperty.CamelAggregatedCorrelationKey} kuyruğunda ${exchangeProperty.CamelAggregatedSize} yeni dead letter var. Ayrıntılar için ajanınızdan list_dead_letters isteyin veya Message Monitor'ü açın."
- to:
uri: smtp:{{alert.smtp.host}}:{{alert.smtp.port}}
parameters:
from: '{{alert.mail.from}}'
to: '{{alert.mail.to}}'
useHeaderSubject: true
username: '{{secret:alert-mail/username}}'
password: '{{secret:alert-mail/password}}'
Route şunları yapar:
- Her olayın gövdesini hemen boşaltır ve olayları
_AMQ_ORIG_QUEUEözelliğine, yani kaynak kuyruğa göre toplar. Her aralığın sonunda olay gelen her kaynak kuyruk için bir mail gönderir: konu2 dead letter: orders.incomingbiçimindedir. - Mailden önce bütün başlıkları siler. Mesajın özellikleri, örneğin sipariş numarası, mail başlıklarına geçmez.
- Konuyu
Subjectbaşlığından alır. Mail bileşeni bu başlığı yalnızuseHeaderSubject: trueile kullanır; bu parametre olmadan mail konusuz gider.
Teams için kanalınızda bir Workflows webhook’u oluşturun ve smtp adımı yerine webhook adresine bir HTTP POST gönderin. Webhook adresini bir Secret’ta tutun; gövdenin biçimini oluşturduğunuz Workflow belirler. Konu ve gövdedeki kaynak kuyruk ve sayı aynı kalır.
Uyarı neyi görür, neyi görmez
- Broker’ın yeniden teslimden sonra ayırdığı ve route’ların park ettiği her dead letter için bir olay gelir. Yeniden denenen bir mesaj tekrar dead letter olursa yeni bir olay gelir; nedeni giderilmemiş mesajları tekrar tekrar denemek yeni uyarılar üretir.
- Olay, toplamaya girdiği anda akıştan silinir. Aralığın sonunda mail sunucusuna ulaşılamazsa o aralığın maili gönderilmez ve hata route’un loglarında görünür. Uyarı projesi yeniden başlarsa henüz gönderilmemiş sayılar da kaybolur. Dead letter’ların kendisi her durumda
dead.letterskuyruğunda kalır; gerçek durumulist_dead_lettersgösterir. - Route olayı toplamaya almadan hata verirse, örneğin bir adım hata fırlatırsa, olay yeniden teslim edilir ve sonunda kendisi dead letter olur. Bu dead letter
dead.letterskuyruğuna gider, kaynak kuyruğudead.letter.eventsolarak görünür ve akışa geri dönmez; uyarı route’u kendi hatasıyla döngüye girmez. - Akışı tüketen yoksa
dead.letter.eventsson 1000 olayı tutar; daha eskiler akıştan düşer,dead.letterskuyruğundan düşmez. Uyarı projesi uzun süre durduysa ilk mailler eksik sayı gösterebilir.
Disk: dead letter’lar silinene kadar kalır
Dead letter’lar hiçbir zaman otomatik silinmez; yeniden denenene veya yetkili bir kişi silene kadar broker diskinde kalır. Yeniden teslim bekleyen mesajlar da aynı diskte durur. Paket içindeki ayarlarla bir mesaj dead letter olmadan önce yaklaşık 12,5 saat kuyruğunda bekleyebilir.
- Yönetici broker diskini kabul ettiğiniz en uzun kesintiye göre boyutlandırır: o sürede gelen mesaj sayısı çarpı mesaj boyutu, artı tuttuğunuz dead letter’lar. Hesap kurulum rehberindedir.
- Bir olay kapandığında kimsenin işlemeyeceği dead letter’ları yaşa göre silin:
discard_dead_lettersaracı bir kuyruğun belli bir zamandan önce gönderilmiş dead letter’larını seçer. Broker’ın ayırdığı dead letter kaynak mesajın gönderilme zamanını, park edilen kopya ise park edildiği zamanı taşır. - Disk %90 dolduğunda broker yer açılana kadar mesaj kabul etmez. Mesajı kuyruğa yazan kabul akışının gönderimi bekler ve kaynak sistemin çağrısı hata veya zaman aşımıyla döner. Broker logunda
AMQ222210veAMQ222212uyarıları görünür. Bu durumda hiçbir mesaj kaybolmaz; teslim akışları çalışmaya devam eder ve tüketilen ya da silinen mesajlar yer açar.