Summary
I’m running long-running streaming requests and other async tasks that I want cancelled when an app session ends.
So I spent quite some time searching the forums, the web in general, and streamlit’s source for a way to stop an async loop when an app session has ended.
I came up with this simple approach that I haven’t seen before and I’m curious to learn what you think about it.
Steps to reproduce
Code snippet:
import asyncio
from datetime import datetime
import streamlit as st
from streamlit.runtime import get_instance
from streamlit.runtime.scriptrunner import get_script_run_ctx
async def watch(test):
print("new session")
runtime = get_instance()
ctx = get_script_run_ctx()
while runtime.is_active_session(ctx.session_id):
test.text(str(datetime.now()))
await asyncio.sleep(0.1)
print("session ended")
test = st.empty()
asyncio.run(watch(test))
Notes
- I can close and re-open tabs or reload them at will. The loop will stop iterating and the script runner will shutdown cleanly. I could also abort any ongoing requests or other streams.
- Yes, get_instance and get_script_run_ctx is considered using internals, but the surface is very limited
- Ideally i’d like a session end signal to stop the coroutine without having to check for state in a loop.
- I can’t use the ScriptRunners on_event SHUTDOWN signal. If the coroutine loop was infinite, it would keep running and never emit the signal.
I hope this is helpful to someone, or insulting enough to elicit a reply