Harden 1C saved-state writes and cache consistency

This commit is contained in:
2026-07-26 16:44:53 +03:00
parent aed134d817
commit 9fd4e1ff99
3 changed files with 440 additions and 16 deletions
+69 -1
View File
@@ -26043,7 +26043,7 @@ def test_saved_state_apply_blocks_unsafe_form_payload_rewrite() -> None:
def test_saved_state_apply_updates_single_part_with_backup(monkeypatch: pytest.MonkeyPatch, tmp_path: Path) -> None:
original = b"old-payload"
replacement = b"new-payload"
state = {"data": original, "committed": False, "rolled_back": False}
state = {"data": original, "committed": False, "rolled_back": False, "sql": []}
class FakeCursor:
rowcount = 0
@@ -26052,6 +26052,7 @@ def test_saved_state_apply_updates_single_part_with_backup(monkeypatch: pytest.M
self.store = store
def execute(self, sql: str, params: tuple[Any, ...]) -> None:
self.store["sql"].append(sql)
if sql.strip().upper().startswith("SELECT"):
self.rowcount = 1
return
@@ -26088,6 +26089,11 @@ def test_saved_state_apply_updates_single_part_with_backup(monkeypatch: pytest.M
"read_storage_file_bytes",
lambda *args, **kwargs: (state["data"], {"database": "upo_test"}, None),
)
monkeypatch.setattr(
adapter_server,
"invalidate_adapter_caches_after_saved_state_change",
lambda base_id, *, reason: {"status": "ok", "base_id": base_id, "reason": reason},
)
proposal = {
"schema": "onec_change_proposal.v1",
@@ -26111,11 +26117,73 @@ def test_saved_state_apply_updates_single_part_with_backup(monkeypatch: pytest.M
assert state["data"] == replacement
assert state["committed"] is True
assert state["rolled_back"] is False
assert "WITH (UPDLOCK, HOLDLOCK)" in state["sql"][0]
assert result["cache_invalidation"]["reason"] == "saved_state_payload_apply"
assert Path(result["backup"]["path"]).exists()
backup = json.loads(Path(result["backup"]["path"]).read_text(encoding="utf-8"))
assert backup["original"]["payload_hex"] == original.hex()
def test_saved_state_cache_invalidation_clears_persistent_and_runtime_views(monkeypatch: pytest.MonkeyPatch) -> None:
base_id = "upo_test"
other_base_id = "other"
data_key = adapter_server.data_schema_cache_key(
{"base_id": base_id, "ref": "Catalog.Номенклатура"}
)
other_data_key = adapter_server.data_schema_cache_key(
{"base_id": other_base_id, "ref": "Catalog.Номенклатура"}
)
monkeypatch.setattr(
adapter_server,
"metadata_cache_invalidate",
lambda payload: {
"status": "ok",
"counts": {"deleted": 7},
"base_id": payload["base_id"],
},
)
monkeypatch.setattr(
adapter_server,
"BASE_ROOT_METADATA_CACHE",
{
(base_id, "Config"): {"cached_at": 1},
(other_base_id, "Config"): {"cached_at": 1},
},
)
monkeypatch.setattr(
adapter_server,
"DATA_SCHEMA_CACHE",
{
data_key: {"cached_at": 1},
other_data_key: {"cached_at": 1},
},
)
monkeypatch.setattr(
adapter_server,
"EXTENSION_MANIFEST_CACHE",
{
(base_id, "root-a"): {"status": "ok"},
(other_base_id, "root-b"): {"status": "ok"},
},
)
result = adapter_server.invalidate_adapter_caches_after_saved_state_change(
base_id,
reason="test",
)
assert result["status"] == "ok"
assert result["persistent"]["deleted"] == 7
assert result["runtime"] == {
"base_root_metadata": 1,
"data_schema": 1,
"extension_manifests": 1,
}
assert list(adapter_server.BASE_ROOT_METADATA_CACHE) == [(other_base_id, "Config")]
assert list(adapter_server.DATA_SCHEMA_CACHE) == [other_data_key]
assert list(adapter_server.EXTENSION_MANIFEST_CACHE) == [(other_base_id, "root-b")]
def test_saved_state_apply_runs_form_element_semantic_verification(monkeypatch: pytest.MonkeyPatch, tmp_path: Path) -> None:
original = b"old-payload"
replacement = b"new-payload"