* perf: bound concurrent full-session resolution * Release — bound concurrent full-session resolution (#7127) * ci: re-trigger fresh run (Playwright-install hang on prior run) * ci: re-trigger (Playwright-install CDN hang on 3 shards, 12/15 passed) * ci: re-trigger (sustained Playwright-CDN hang, run 4) * ci: supersede 2h20m-zombie Playwright-hung run (run 6) --------- Co-authored-by: Dr. Carlos Daniel Carvalho <292283903+Dandandad@users.noreply.github.com> Co-authored-by: n <a@n>
This commit is contained in:
3 files changed
+351
-1
No files matched your search
+112
-1
@@ -4684,7 +4684,46 @@ def get_session_for_scan(sid):
|
||||
return None
|
||||
|
||||
|
||||
def _resolve_session(sid, metadata_only=False, *, promote_cache=True, cache_on_miss=True):
|
||||
class _FullSessionResolveRequired(RuntimeError):
|
||||
"""Internal signal that a full sidecar load must enter the bounded path."""
|
||||
|
||||
|
||||
_FULL_SESSION_RESOLVE_MAX_CONCURRENT = 2
|
||||
_FULL_SESSION_RESOLVE_SLOTS = threading.BoundedSemaphore(
|
||||
_FULL_SESSION_RESOLVE_MAX_CONCURRENT
|
||||
)
|
||||
_FULL_SESSION_RESOLVE_INFLIGHT: dict[str, threading.Event] = {}
|
||||
_FULL_SESSION_RESOLVE_INFLIGHT_LOCK = threading.Lock()
|
||||
_FULL_SESSION_RESOLVE_LOCAL = threading.local()
|
||||
|
||||
|
||||
def _claim_full_session_resolve(session_id: str) -> tuple[bool, threading.Event]:
|
||||
"""Return whether this caller owns the single-flight for ``session_id``."""
|
||||
with _FULL_SESSION_RESOLVE_INFLIGHT_LOCK:
|
||||
event = _FULL_SESSION_RESOLVE_INFLIGHT.get(session_id)
|
||||
if event is not None:
|
||||
return False, event
|
||||
event = threading.Event()
|
||||
_FULL_SESSION_RESOLVE_INFLIGHT[session_id] = event
|
||||
return True, event
|
||||
|
||||
|
||||
def _finish_full_session_resolve(session_id: str, event: threading.Event) -> None:
|
||||
"""Release one single-flight owner and wake every waiter."""
|
||||
with _FULL_SESSION_RESOLVE_INFLIGHT_LOCK:
|
||||
if _FULL_SESSION_RESOLVE_INFLIGHT.get(session_id) is event:
|
||||
_FULL_SESSION_RESOLVE_INFLIGHT.pop(session_id, None)
|
||||
event.set()
|
||||
|
||||
|
||||
def _resolve_session_once(
|
||||
sid,
|
||||
metadata_only=False,
|
||||
*,
|
||||
promote_cache=True,
|
||||
cache_on_miss=True,
|
||||
allow_full_load=False,
|
||||
):
|
||||
"""Resolve a session through the canonical freshness/recovery path.
|
||||
|
||||
``get_session_for_scan`` shares this resolver with normal reads so that
|
||||
@@ -4715,6 +4754,8 @@ def _resolve_session(sid, metadata_only=False, *, promote_cache=True, cache_on_m
|
||||
cached = None
|
||||
if cached is not None:
|
||||
if not metadata_only and _cached_session_lags_disk(cached):
|
||||
if not allow_full_load:
|
||||
raise _FullSessionResolveRequired
|
||||
try:
|
||||
disk_session = Session.load(sid)
|
||||
with LOCK:
|
||||
@@ -4727,6 +4768,8 @@ def _resolve_session(sid, metadata_only=False, *, promote_cache=True, cache_on_m
|
||||
"cached session disk-freshness check failed for session %s", sid, exc_info=True,
|
||||
)
|
||||
if not metadata_only and _inactive_cache_tail_needs_disk_check(cached):
|
||||
if not allow_full_load:
|
||||
raise _FullSessionResolveRequired
|
||||
try:
|
||||
disk_session = Session.load(sid)
|
||||
if _cache_has_stale_unsaved_user_tail(cached, disk_session):
|
||||
@@ -4759,6 +4802,8 @@ def _resolve_session(sid, metadata_only=False, *, promote_cache=True, cache_on_m
|
||||
if s:
|
||||
return s
|
||||
else:
|
||||
if not allow_full_load:
|
||||
raise _FullSessionResolveRequired
|
||||
s = Session.load(sid)
|
||||
if s:
|
||||
if cache_on_miss:
|
||||
@@ -4799,6 +4844,72 @@ def _resolve_session(sid, metadata_only=False, *, promote_cache=True, cache_on_m
|
||||
raise KeyError(sid)
|
||||
|
||||
|
||||
def _resolve_session(sid, metadata_only=False, *, promote_cache=True, cache_on_miss=True):
|
||||
"""Resolve a session while single-flighting heavyweight full sidecar loads.
|
||||
|
||||
Metadata-only reads and full sessions that remain current in the cache take
|
||||
the lock-free path. A cache miss or stale cache entry elects one leader per
|
||||
session; waiters retry the canonical resolver after that leader publishes its
|
||||
result. Leaders for different sessions share a small global slot budget so
|
||||
concurrent JSON parses cannot multiply a large sidecar's transient memory.
|
||||
"""
|
||||
if metadata_only:
|
||||
return _resolve_session_once(
|
||||
sid,
|
||||
metadata_only=True,
|
||||
promote_cache=promote_cache,
|
||||
cache_on_miss=cache_on_miss,
|
||||
)
|
||||
|
||||
session_id = str(sid)
|
||||
while True:
|
||||
try:
|
||||
return _resolve_session_once(
|
||||
sid,
|
||||
metadata_only=False,
|
||||
promote_cache=promote_cache,
|
||||
cache_on_miss=cache_on_miss,
|
||||
)
|
||||
except _FullSessionResolveRequired:
|
||||
pass
|
||||
|
||||
active: set[str] = set(
|
||||
getattr(_FULL_SESSION_RESOLVE_LOCAL, "active", ()) or ()
|
||||
)
|
||||
if active:
|
||||
# Nested resolution already owns one global slot. Re-enter directly
|
||||
# instead of waiting on this thread's own flight or consuming a
|
||||
# second slot; the canonical resolver still owns all cache checks.
|
||||
return _resolve_session_once(
|
||||
sid,
|
||||
metadata_only=False,
|
||||
promote_cache=promote_cache,
|
||||
cache_on_miss=cache_on_miss,
|
||||
allow_full_load=True,
|
||||
)
|
||||
|
||||
leader, event = _claim_full_session_resolve(session_id)
|
||||
if not leader:
|
||||
event.wait()
|
||||
continue
|
||||
|
||||
active.add(session_id)
|
||||
_FULL_SESSION_RESOLVE_LOCAL.active = active
|
||||
try:
|
||||
with _FULL_SESSION_RESOLVE_SLOTS:
|
||||
return _resolve_session_once(
|
||||
sid,
|
||||
metadata_only=False,
|
||||
promote_cache=promote_cache,
|
||||
cache_on_miss=cache_on_miss,
|
||||
allow_full_load=True,
|
||||
)
|
||||
finally:
|
||||
active.discard(session_id)
|
||||
_FULL_SESSION_RESOLVE_LOCAL.active = active
|
||||
_finish_full_session_resolve(session_id, event)
|
||||
|
||||
|
||||
def get_session(sid, metadata_only=False):
|
||||
"""Load a session, optionally with metadata only (skipping messages)."""
|
||||
return _resolve_session(sid, metadata_only=metadata_only)
|
||||
|
||||
Reference in new issue
Block a user