Managing Sessions in Your App¶
Opening a live Session launches a whole browser. An application that makes many lookups (a web service, a bot, a tool server) should not open one per request, nor write its own sharing and shutdown code. Runtime does that for you.
import slb_glossary as slb
from slb_glossary import query
async with slb.Runtime(max_sessions=2) as runtime:
async with runtime.acquire(query.Source.AUTO, language="en") as (db, session):
async for result in query.search("porosity", db=db, session=session):
print(result.value.term)
A Runtime owns the shared local database and one SessionPool per glossary language, all bounded by one browser budget (max_sessions).
Getting what a call needs¶
runtime.acquire(source, language=..., capacity=...)yields the(db, session)pair aSourceneeds. Either can beNonewhen the source doesn't use it.runtime.session(language, capacity=...)yields just a liveSession, for when you don't deal inSource.runtime.open_db()returns the sharedDatabase.
capacity is how many pages the call expects to use at once (for example its concurrency). It only informs whether to reuse a session or open another; page limits are still enforced by the session itself.
Session modes¶
SessionMode |
A browser is opened | Use it for |
|---|---|---|
LAZY (default) |
On the first call that needs one, then reused | Most apps |
EAGER |
When the runtime starts | Lowest first-call latency |
PER_CALL |
For every call, closed right after | Full isolation between callers |
Tuning¶
All of these are arguments to Runtime(...):
max_sessions: most browsers open at once, across every language. RaisingSessionOptions.max_pagesis cheaper than raising this.idle_timeout: seconds an unused session lives before it is closed (Nonekeeps them untilclose()).min_reap_interval/max_reap_interval: how often the idle check runs, in seconds. It wakes every quarter ofidle_timeout, kept between these two (1and60by default), so a short timeout doesn't make it spin and a long one doesn't leave sessions open far past it.runtime.reap_intervalshows the value in use.capacity_tolerance: how many pages short an existing session may be before another browser is opened.session_options/database_options: how sessions are opened and where the database lives.live_enabled/local_enabled: switch either side off.
Runtime.from_config(config, **overrides) builds one from a slb_glossary.config.Config.
When the browser budget is spent, a call for a language that already has a session shares it. A call for a language with none first closes sessions that are idle in other languages, then waits for one.
Inspecting and closing¶
runtime.stats() # sessions open, busy, per-language checkouts
await runtime.close_idle_sessions() # run one reaping cycle now
await runtime.close() # or use `async with`
A browser that crashes is dropped and replaced rather than handed out again.
Using a pool directly¶
SessionPool is the per-language building block, if you want it without the rest: