Selam, Livekit'de çağrı kapandığında ekstra bir f...
# ask-ai
a
Selam, Livekit'de çağrı kapandığında ekstra bir fonksiyon çalıştırmak istiyorum. Ve her çağrı bittiğinde kesinlikle bunun çalışmasını istiyorum. Bunu nasıl yapabilirim?
t
Thanks for reaching out, İbrahim. I'm an AI assistant and I'm here to help. Give me a moment while I research this topic.
Selam — çağrı kapandığında ekstra bir fonksiyonun "kesinlikle ve her seferinde" çalışmasını sağlamak istediğini anladım. Aşağıda bunu güvenilir şekilde yapman için en doğrudan ve önerilen yöntemleri kısa ve net şekilde paylaşıyorum. Özet — en güvenilir çözüm • LiveKit Agents framework'ünde
rtc_session
dekoratörüne
on_session_end
(veya shutdown hook) parametresiyle bir callback ekle. Bu callback oturum kapandığında (kullanıcı kapattığında, hata ile sonlandığında veya programatik olarak kapatıldığında) her zaman çalıştırılır. Nasıl uygulayabilirsin (örnek) 1.
on_session_end
adında asenkron bir fonksiyon oluştur:
Copy code
async def on_shutdown_hook():
    # Çağrı bittiğinde kesinlikle çalışmasını istediğin işleri buraya koy
    # Örnekler: veritabanına kayıt, log gönderme, bildirim tetikleme, kaynak temizleme
    print("Çağrı sonlandı — cleanup çalışıyor")
1.
rtc_session
dekoratöründe bu fonksiyonu belirt:
Copy code
@server.rtc_session(
    agent_name="my-agent",
    on_session_end=on_shutdown_hook
)
async def entrypoint(ctx: JobContext):
    # Oturum başlatma ve normal işlem akışı
    session = AgentSession(...)
    await session.start(...)
Neden bu yöntem "kesinlikle" çalışır? •
on_session_end
callback’i, oturum normal ya da hatalı şekilde sonlansa bile tetiklenmek üzere tasarlanmıştır. Yani çağrı sonlanmasının tüm temel yollarında bu hook çalışacaktır. Ek alternatif (oda temizliğiyle ilgili) • Eğer amacın sadece oda/oturum kaynaklarını temizlemekse,
RoomOptions
içindeki
delete_room_on_close=True
gibi ayarlar odanın kapanınca otomatik silinmesini sağlar. Bu, ekstra fonksiyondan ziyade otomatik temizlik içindir:
Copy code
await session.start(
    ...,
    room_options=room_io.RoomOptions(delete_room_on_close=True)
)
Kontrol listesi — uygulamadan önce doğrula • Callback fonksiyonunun asenkron olduğundan ve hata yakalama/loglama içerdiğinden emin ol (aksi halde hata iletisi callback’in erken sonlanmasına neden olabilir). • Callback içinde kritik bir işlem yapıyorsan (ör. ödeme, veritabanı güncellemesi), idempotent (tekrar çağrılsa da sorun çıkarmayan) bir yapı kur: aynı işlemin tekrar gerçekleştirilmesi durumunda yan etki oluşmasın. • Test: çağrıyı normal kapatma, hata ile kapatma ve programatik shutdown senaryolarında callback’in her durumda tetiklendiğini test et. Dilersen yardım edebilirim: • Mevcut kodundan küçük bir örnek paylaşırsan
on_session_end
hook’unu nasıl entegre edeceğini doğrudan kod üzerinde gösterebilirim. • Callback içinde tipik olarak yapılan görevler (veritabanı kayıtları, bildirimler, temizleme) için örnek şablonlar verebilirim. Hangi kısmı görmek istersin—kod örneği mi yoksa callback içinde yapılabilecek örnek görevlerin şablonları mı? Sources: Agent session | LiveKit Documentation | Job lifecycle | LiveKit Documentation
a
session.aclose() sırasında bir hata olursa event yollayamıyor ama bana.
t
Anladım — sorun,
session.aclose()
sırasında hata olduğunda gönderdiğin event'in çalışmaması. Bunu çözmek için doğru yaklaşım: cleanup/teardown kodunu `session.aclose()`'a bağlamak yerine job/entrypoint kapanışına kayıtlı bir shutdown callback olarak eklemek. Bu şekilde
session.aclose()
hata verse bile callback çalıştırılacaktır. Önerilen çözüm (kısa ve uygulanabilir): 1.
ctx.add_shutdown_callback()
ile post-call fonksiyonunu kaydet. 2. Callback içinde event gönderme kodunu hata yakalayacak şekilde sarmala (idempotent ve retry mantığı eklemek faydalı). 3. Gerekirse birden fazla cleanup callback ekle (her biri farklı işi yapsın). Örnek (Python, LiveKit Agents giriş noktasında):
Copy code
@server.rtc_session(agent_name="my-agent")
async def entrypoint(ctx: JobContext):
    session = AgentSession(...)
    await session.start(agent=MyAgent(), room=ctx.room)

    async def on_shutdown():
        try:
            # Burada kesinlikle çalışmasını istediğin event gönderme/log/DB güncellemesi
            await send_event("call_ended", payload)
        except Exception as e:
            logger.error(f"Post-call event gönderilemedi: {e}")
            # İstersen retry veya fallback (ör. queue'ya koyma) yap
            # await retry_send_event(...)
    
    ctx.add_shutdown_callback(on_shutdown)

    # Normal kapanış denemesi
    await session.aclose()
Neden bu işe yarar? •
add_shutdown_callback()
register edilen fonksiyonları job kapanırken çalıştırır;
session.aclose()
hata verirse bile bu kapanış akışı içinde callback tetiklenir. • Callback içinde hata yakalarsan event gönderme hataları nedeniyle tüm cleanup'in durması engellenir. • Callback’leri idempotent yaparsan (aynı event birden fazla gönderilse sorun olmaması) hata sonrası retry veya tekrar tetiklenmelerin zarar vermesini önlersin. Ek pratik öneriler • Event gönderimini güvenilir yapmak için retry + exponential backoff veya yazımsal bir queue (örn. Redis/DB kuyruk) kullan. • Kritik işlemler için işlemi tamamlandığını belirten bir durum alanı (DB flag) kullan; böylece callback tekrar çalışsa bile tekrarı tespit edip atlayabilirsin. • Callback içinde yeterli logging koy (başarılı/başarısız kayıtları) — sorun tespiti kolaylaşır. İstersen şimdi: • Mevcut entrypoint kodunu paylaşırsın; ben ona göre
ctx.add_shutdown_callback()
ile tam entegre örnek vereyim. • Veya callback içinde retry/fallback mantığı örneği görmek istersen onu detaylandırayım. Hangi kısmı istersin? Sources: Job lifecycle | LiveKit Documentation | Python Agents: Handling exceptions in your entrypoint | LiveKit
a
Tamam da. ctx.shutdown ile kapattığımda livekit session.aclose() çalıştırıyor. Orada hata varsa bana event yolluyor mu yine de?
t
Kısa cevap: Hayır —
ctx.shutdown()
çağırdığında LiveKit framework'ü
session.aclose()
çalıştırıyor, fakat
session.aclose()
içinde bir hata oluşursa o sıradaki normal akışta gönderdiğin event(ler) çalışmayabilir. Bu yüzden
session.aclose()
içindeki işlemlere güvenmek kritik event'lerin "kesinlikle" gönderileceği garantisini vermez. Neden: •
ctx.shutdown()
job kapanış akışını başlatır ve framework içinde
session.aclose()
çağrılabilir. Ancak
session.aclose()
hata verirse sonraki kod akışı kesilebilir veya hata fırlatılabilir; bu durumda event gönderme kodun çalışmayabilir. • Yani sadece
session.aclose()
sonrası event gönderme yazdıysan,
aclose()
hata verdiğinde o event atlanma riski vardır. Güvenli çözüm (önerilen uygulama): • Kritik event gönderimini
ctx.add_shutdown_callback()
ile kaydet. Shutdown callback'leri job kapanışının parçası olarak çalıştırılır ve
session.aclose()
hata verse bile bu callback tetiklenir. • Callback içinde hata yakala, logla ve gerekiyorsa retry/fallback (ör. kuyruğa atma) uygula. • Callback'i idempotent yap: aynı event birden fazla kez gönderilse sistemin bozulmaması için kontrol koy. Örnek (özet):
Copy code
@server.rtc_session(agent_name="my-agent")
async def entrypoint(ctx: JobContext):
    session = AgentSession(...)
    await session.start(...)

    async def on_shutdown():
        try:
            await send_event("call_ended", payload)
        except Exception as e:
            logger.error(f"Event gönderilemedi: {e}")
            # fallback: queue'ya yaz veya retry başlat
            # await enqueue_event_for_retry(...)
    
    ctx.add_shutdown_callback(on_shutdown)

    await session.aclose()  # Eğer burada hata olursa bile on_shutdown çalışacaktır
Ek tavsiyeler: • Callback içinde kritik işi DB'ye bir "işlem tamamlandı" flag'i olarak yazarsan, tekrar çalışsa bile tekrarı atlayabilirsin. • Event gönderiminde retry + exponential backoff veya bir dayanıklı kuyruk kullanmak güvenilirliği artırır. • Detaylı logging koy ki hangi durumda event gönderildi/atlandı/başarısız oldu kolayca görülebilsin. İstersen mevcut kodunu paylaş — ben
ctx.add_shutdown_callback()
ile tam entegre olacak şekilde düzenleyip hata/yedekleme (retry/queue) örneği ekleyeyim.