fix(archive): preserve prepared sessions across restarts
This commit is contained in:
@@ -45,9 +45,7 @@ SAFE_SOURCE_ID = re.compile(r"^[A-Za-z0-9][A-Za-z0-9._:-]{0,255}$")
|
||||
SAFE_SHA256 = re.compile(r"^[a-f0-9]{64}$")
|
||||
MAX_SAFE_INTEGER = 9_007_199_254_740_991
|
||||
REVALIDATED_RECORDING_CACHE_CONTROL = "private, no-cache, no-transform"
|
||||
IMMUTABLE_RECORDING_CACHE_CONTROL = (
|
||||
"private, max-age=31536000, immutable, no-transform"
|
||||
)
|
||||
IMMUTABLE_RECORDING_CACHE_CONTROL = "private, max-age=31536000, immutable, no-transform"
|
||||
|
||||
|
||||
class _ReleasingFileResponse(FileResponse):
|
||||
@@ -321,13 +319,17 @@ def build_session_router(
|
||||
|
||||
if recording_preparation_manager is not None:
|
||||
try:
|
||||
# Enqueue performs only catalog identity/lstat checks. A cold
|
||||
# RRD cache and every camera index are validated exclusively
|
||||
# by the process-owned worker.
|
||||
snapshot = recording_preparation_manager.enqueue(
|
||||
command,
|
||||
retry_failed=True,
|
||||
)
|
||||
snapshot = recording_preparation_manager.status(command.session_id)
|
||||
if snapshot is None:
|
||||
snapshot = await run_in_threadpool(
|
||||
recording_preparation_manager.restore_published,
|
||||
command,
|
||||
)
|
||||
if snapshot is None:
|
||||
snapshot = recording_preparation_manager.enqueue(
|
||||
command,
|
||||
retry_failed=True,
|
||||
)
|
||||
except RecordingPreparationQueueFull as exc:
|
||||
raise HTTPException(
|
||||
status_code=503,
|
||||
@@ -504,7 +506,12 @@ def build_session_router(
|
||||
False,
|
||||
False,
|
||||
)
|
||||
snapshot = recording_preparation_manager.enqueue(command)
|
||||
snapshot = await run_in_threadpool(
|
||||
recording_preparation_manager.restore_published,
|
||||
command,
|
||||
)
|
||||
if snapshot is None:
|
||||
snapshot = recording_preparation_manager.enqueue(command)
|
||||
except SessionNotFoundError as exc:
|
||||
raise HTTPException(status_code=404, detail=str(exc)) from exc
|
||||
except (SessionNotReplayableError, SessionIntegrityError) as exc:
|
||||
@@ -1036,15 +1043,16 @@ def _catalog_preparation_document(
|
||||
snapshot = manager.status(session_id)
|
||||
if snapshot is None:
|
||||
try:
|
||||
snapshot = manager.enqueue(store.prepare_replay(session_id))
|
||||
snapshot = manager.restore_published(store.prepare_replay(session_id))
|
||||
except (
|
||||
RecordingPreparationQueueFull,
|
||||
SessionNotFoundError,
|
||||
SessionNotReplayableError,
|
||||
SessionIntegrityError,
|
||||
ValueError,
|
||||
):
|
||||
return None
|
||||
if snapshot is None:
|
||||
return None
|
||||
document: dict[str, Any] = {
|
||||
"preparation_id": snapshot.preparation_id,
|
||||
"state": snapshot.state,
|
||||
@@ -1165,10 +1173,7 @@ def _recorded_media_manifest_document(
|
||||
"segments": [
|
||||
{
|
||||
"sequence": segment.sequence,
|
||||
"url": (
|
||||
f"{base}/epochs/{epoch.ordinal}/segments/"
|
||||
f"{segment.sequence}.m4s"
|
||||
),
|
||||
"url": (f"{base}/epochs/{epoch.ordinal}/segments/{segment.sequence}.m4s"),
|
||||
"byte_length": segment.byte_length,
|
||||
"sha256": segment.sha256,
|
||||
}
|
||||
@@ -1198,19 +1203,13 @@ def _resolve_recorded_media_manifest(
|
||||
detail="Некорректный идентификатор записанного медиаканала.",
|
||||
) from exc
|
||||
snapshot = manager.status(session_id)
|
||||
if (
|
||||
snapshot is None
|
||||
or snapshot.state != "ready"
|
||||
or snapshot.recorded_media is None
|
||||
):
|
||||
if snapshot is None or snapshot.state != "ready" or snapshot.recorded_media is None:
|
||||
raise HTTPException(
|
||||
status_code=409,
|
||||
detail="Медиаканал ещё не подготовлен.",
|
||||
)
|
||||
matches = tuple(
|
||||
manifest
|
||||
for manifest in snapshot.recorded_media
|
||||
if manifest.artifact_id == artifact_id
|
||||
manifest for manifest in snapshot.recorded_media if manifest.artifact_id == artifact_id
|
||||
)
|
||||
if len(matches) != 1:
|
||||
raise HTTPException(status_code=404, detail="Записанный медиаканал не найден.")
|
||||
|
||||
Reference in New Issue
Block a user