fix(api): replace threading.Lock with asyncio.Lock for hydration guard
await inside a threading.Lock yields to the event loop while the OS thread still holds the lock — potential deadlock under FastAPI thread pool dispatch. asyncio.Lock is the correct primitive for async critical sections. Also fixed stale diurnal.py docstring that had the delegation direction backwards.
This commit is contained in:
@@ -38,7 +38,7 @@ def _parse_window(window: str) -> tuple[int, int, int, int] | None:
|
||||
|
||||
Returns ``None`` for malformed input — callers treat that as
|
||||
"always-on" so a single config typo never silences the whole fleet
|
||||
(mirrors :func:`decnet.realism.personas.in_active_hours` semantics).
|
||||
(:func:`decnet.realism.personas.in_active_hours` delegates here).
|
||||
"""
|
||||
try:
|
||||
start_s, end_s = window.split("-")
|
||||
|
||||
@@ -16,8 +16,8 @@ waiting for the orchestrator's next refresh tick.
|
||||
"""
|
||||
from __future__ import annotations
|
||||
|
||||
import asyncio
|
||||
import json
|
||||
import threading
|
||||
from typing import Any
|
||||
|
||||
from fastapi import APIRouter, Depends, HTTPException
|
||||
@@ -32,7 +32,7 @@ log = get_logger("api.realism.config")
|
||||
|
||||
_CONFIG_KEY = "weights"
|
||||
_hydrated = False
|
||||
_hydrate_lock = threading.Lock()
|
||||
_hydrate_lock = asyncio.Lock()
|
||||
|
||||
|
||||
@router.get(
|
||||
@@ -56,7 +56,7 @@ async def get_config(
|
||||
"""
|
||||
global _hydrated
|
||||
if not _hydrated:
|
||||
with _hydrate_lock:
|
||||
async with _hydrate_lock:
|
||||
if not _hydrated:
|
||||
row = await repo.get_realism_config(_CONFIG_KEY)
|
||||
if row is not None:
|
||||
|
||||
Reference in New Issue
Block a user