I have a participant_disconnect callback but it do...
# ask-ai
o
I have a participant_disconnect callback but it doesn't finish running before the session is closed. is there a better way to do async callbacks?
Copy code
async def async_on_participant_disconnected():
    # Save transcription
    await self.save_final_transcription()

@ctx.room.on("participant_disconnected")
def on_participant_disconnected(participant):
    <http://speech_logger.info|speech_logger.info>("The user has disconnected from the call.")
    self._disconnect_task = asyncio.create_task(async_on_participant_disconnected())

async def save_final_transcription(self) -> None:
    if self.user:
        <http://logger.info|logger.info>(f"Saving call transcription for user_id {self.user.id}")
        if len([t.content for t in self.transcription_pieces if t.role == "user"]) == 0:
            # if user never replied, switch to previous user status (as if conversation didn't happen)
            update_user_status(self.user.id, UserStatus.PENDING.value if self.user.prev_status == UserStatus.QUEUED else self.user.prev_status.value)
        else:
            # if all questions were answered, ensure user status is completed
            if not self.user.missing_questions:
                self.user.status = UserStatus.COMPLETED 
            transcript = save_transcription(self.user.id, self.transcription_pieces, self.call_type.value)    # save transcription
            update_user_status(self.user.id, self.user.status.value)    # update user status
            # if user status is still in progress at the end of the call, process the transcription to determine a status
            if self.user.status == UserStatus.IN_PROGRESS:
                await process_transcription(transcript, self.user.id) # THIS NEVER GETS DONE RUNNING BEFORE EVERYTHING SHUTS DOWN
t
Thanks for reaching out, Lara. I'm an AI assistant and I'm here to help. Give me a moment while I research this topic.
To make sure your async callbacks for
participant_disconnected
finish up before the session closes, here’s a friendly approach you can try: • Keep an ear out for the
participant_disconnected
event and kick off cleanup tasks using
asyncio.create_task
. • Hold onto all those tasks and await them before closing the session by gathering them at the end. • You can also set
close_on_disconnect=True
in your session settings to have sessions close automatically when participants leave. Here’s a simple example to illustrate:
Copy code
async def entrypoint(ctx: JobContext):
    session = AgentSession(
        stt=deepgram.STT(),
        tts=silero.TTS()
    )

    await session.start(
        agent=MyAgent(),
        room=ctx.room,
        input_options=RoomInputOptions(close_on_disconnect=True)
    )

    tasks = set()

    def on_disconnect(participant: rtc.RemoteParticipant):
        async def cleanup_session():
            await session.aclose()
            print(f"Session closed for participant {participant.identity}")
        tasks.add(asyncio.create_task(cleanup_session()))

    ctx.room.on("participant_disconnected", on_disconnect)

    try:
        await asyncio.Future()  # Run forever
    except asyncio.CancelledError:
        pass
    finally:
        if session:
            await session.aclose()
        for task in tasks:
            task.cancel()
        await asyncio.gather(*tasks, return_exceptions=True)
This way, all your important tasks—like saving transcriptions—get done before the session wraps up. If anything’s unclear or you want to dive deeper, just let me know—I’m here to help!
o
aclose does nothing for me. it doesn't disconnect the call, the assistant starts talking nonsense and doesn't hear me + my task is still not running completely
t
It looks like
aclose
isn’t quite working as expected for you. No worries—here are some friendly tips to help you sort it out: • Make Sure Tasks Are Handled Properly: Try tweaking the
aclose
method so it waits for all tasks to finish without a timeout. Something like this might do the trick:
await asyncio.gather(*tasks, return_exceptions=False)
Close Resources Explicitly: Double-check that all your resources, like audio and video tracks, are properly closed. For example:
Copy code
if self._stream_response and not self._stream_response.output_stream.closed:
    await self._stream_response.output_stream.close()
Log Any Exceptions: Instead of skipping over exceptions when cancelling tasks, it’s helpful to log them so you can spot any issues:
Copy code
try:
    await task
except Exception as e:
    logger.error("Task failed during closure", exc_info=e)
Hopefully, these steps will get your calls disconnecting smoothly and tasks wrapping up nicely. If you want to chat more or need a hand with anything else, just let me know! Sources: livekit-agents/livekit/agents/voice/agent_session.py