Close repository requests with manual lock sessions

This commit is contained in:
2026-07-22 03:37:53 +03:00
parent 10224c6344
commit b8c62fa8fa
3 changed files with 35 additions and 5 deletions
+2 -1
View File
@@ -38,7 +38,8 @@ by default) and may be explicitly cancelled with
`repository.lock.request.cancel`. Manual confirmations expire after
`ONEC_REPOSITORY_CONFIRMATION_TTL_SECONDS` (2 hours by default). After the user
releases the objects in Configurator, `repository.lock.close` closes the
confirmation and immediately blocks further SQL writes through that session.
confirmation, marks its originating request as `closed`, and immediately blocks
further SQL writes through that session.
The adapter keeps a bounded audit trail of request creation, confirmation,
cancellation, and closure and exposes it to the administrative requests view.
+26 -4
View File
@@ -538,6 +538,7 @@ def confirm_manual_lock(payload: dict[str, Any]) -> dict[str, Any]:
"base_id": base_id, "layer": str(config.get("layer") or "base"), "backend": config.get("backend"),
"objects": plan["lock_objects"], "created_at": time.time(), "status": "manual_confirmed",
"verification": "user_confirmation_only", "automatically_verified": False,
**({"request_id": request_id} if request_id else {}),
}
if isinstance(request, dict):
request["status"] = "confirmed_by_user"
@@ -571,13 +572,34 @@ def close_manual_lock(payload: dict[str, Any]) -> dict[str, Any]:
session = (state.get("sessions") or {}).get(session_id)
if not isinstance(session, dict):
return {"schema": "onec_repository_lock_close.v1", "method": METHOD_CLOSE, "status": "not_found", "lock_session_id": session_id}
if session.get("status") != "manual_confirmed":
if session.get("status") not in {"manual_confirmed", "closed"}:
return {"schema": "onec_repository_lock_close.v1", "method": METHOD_CLOSE, "status": "blocked", "error": "manual_confirmation_not_active", "lock_session_id": session_id}
already_closed = session.get("status") == "closed"
session["status"] = "closed"
session["closed_at"] = time.time()
_audit(state, "manual_lock_closed", lock_session_id=session_id, base_id=session.get("base_id"), objects=session.get("objects"))
closed_at = float(session.get("closed_at") or time.time())
session["closed_at"] = closed_at
request_id = str(session.get("request_id") or "").strip()
request = (state.get("requests") or {}).get(request_id) if request_id else None
if not isinstance(request, dict):
request_id = next(
(
str(candidate_id)
for candidate_id, candidate in (state.get("requests") or {}).items()
if isinstance(candidate, dict) and candidate.get("lock_session_id") == session_id
),
"",
)
request = (state.get("requests") or {}).get(request_id) if request_id else None
if isinstance(request, dict):
request["status"] = "closed"
request["closed_at"] = closed_at
if not already_closed:
_audit(state, "manual_lock_closed", request_id=request_id or None, lock_session_id=session_id, base_id=session.get("base_id"), objects=session.get("objects"))
_write_state(state)
return {"schema": "onec_repository_lock_close.v1", "method": METHOD_CLOSE, "status": "closed", "lock_session_id": session_id}
return {
"schema": "onec_repository_lock_close.v1", "method": METHOD_CLOSE, "status": "closed",
"lock_session_id": session_id, "request_id": request_id or None,
}
def write_gate(payload: dict[str, Any]) -> dict[str, Any]:
+7
View File
@@ -104,6 +104,13 @@ def test_manual_lock_request_stays_pending_until_user_confirms_exact_saved_scope
closed = repository_control.close_manual_lock({"lock_session_id": confirmed["lock_session_id"], "user_confirmed_released": True})
assert closed["status"] == "closed"
assert closed["request_id"] == requested["request_id"]
completed = repository_control.lock_request_status({"request_id": requested["request_id"]})
assert completed["status"] == "closed"
assert completed["request"]["closed_at"] > completed["request"]["confirmed_at"]
closed_again = repository_control.close_manual_lock({"lock_session_id": confirmed["lock_session_id"], "user_confirmed_released": True})
assert closed_again["status"] == "closed"
assert closed_again["request_id"] == requested["request_id"]
assert repository_control.write_gate({"base_id": "base", "lock_session_id": confirmed["lock_session_id"], "repository_object": "РегистрСведений.Настройки"})["allowed"] is False