The periodic security download ran blocking HTTP on the reactor thread, so a dead selfcare server stalled RPTPING handling well past PING_TIME * MAX_MISSED and every peer was timed out and forced to reconnect. Move the security and alias downloads to the thread pool, bound the DNS and HTTP timeouts below that budget, and skip a cycle when the previous one is still in flight. Also drop the redundant interval guard that silently stretched the real retry period to a multiple of the loop interval, restore the process-wide socket timeout after a failed DNS lookup, keep existing files and cached passwords when a download returns an empty or invalid payload, and remove the inherited 50Mb cap on subscriber_ids that production was already close to tripping. PASS_SECURITY is no longer written to the log.pull/69/head
parent
c2bd1c89af
commit
49114feee9
@ -0,0 +1,58 @@
|
||||
# ADN DMR Peer Server - alias reload resilience when selfcare download fails
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
import json
|
||||
from pathlib import Path
|
||||
|
||||
from adn_server.infrastructure.persistence.alias_loader import DefaultAliasLoader, try_download
|
||||
|
||||
|
||||
def _write_subscriber_file(path: Path, file_name: str, rid: int, callsign: str) -> None:
|
||||
data = {"subscribers": [{"id": rid, "callsign": callsign}]}
|
||||
(path / file_name).write_text(json.dumps(data), encoding="utf-8")
|
||||
|
||||
|
||||
def test_try_download_failure_does_not_erase_existing_file(tmp_path: Path) -> None:
|
||||
file_name = "subscriber_ids.json"
|
||||
full = tmp_path / file_name
|
||||
full.write_bytes(b'{"subscribers":[{"id":7300391,"callsign":"CE5RPY"}]}')
|
||||
# stale_sec=0 forces download attempt; bad URL simulates selfcare down
|
||||
result = try_download(tmp_path, file_name, "http://127.0.0.1:1/nope.json", stale_sec=0)
|
||||
assert "could not be downloaded" in result or "IOError" in result
|
||||
assert full.read_bytes().startswith(b"{")
|
||||
|
||||
|
||||
def test_merge_reload_keeps_previous_sub_ids_on_empty_reload() -> None:
|
||||
loader = DefaultAliasLoader()
|
||||
config = {
|
||||
"_SUB_IDS": {7300391: "CE5RPY"},
|
||||
"_PEER_IDS": {730039101: "CE5RPY"},
|
||||
"ALIASES": {"PATH": "."},
|
||||
}
|
||||
DefaultAliasLoader.merge_reload_into_config(
|
||||
config,
|
||||
loader,
|
||||
{},
|
||||
{},
|
||||
{},
|
||||
{},
|
||||
{},
|
||||
{},
|
||||
)
|
||||
assert config["_SUB_IDS"] == {7300391: "CE5RPY"}
|
||||
assert config["_PEER_IDS"] == {730039101: "CE5RPY"}
|
||||
|
||||
|
||||
def test_load_id_dict_with_backup_uses_bak_on_checksum_mismatch(tmp_path: Path) -> None:
|
||||
loader = DefaultAliasLoader()
|
||||
file_name = "subscriber_ids.json"
|
||||
_write_subscriber_file(tmp_path, file_name, 1111111, "BAD")
|
||||
_write_subscriber_file(tmp_path, f"{file_name}.bak", 7300391, "GOOD")
|
||||
loaded = loader._load_id_dict_with_backup(
|
||||
tmp_path,
|
||||
file_name,
|
||||
"deadbeef",
|
||||
"subscriber_ids",
|
||||
)
|
||||
assert loaded.get(7300391) == "GOOD"
|
||||
@ -0,0 +1,27 @@
|
||||
# ADN DMR Peer Server - user passwords loader keeps cache on bad reload
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
import json
|
||||
from pathlib import Path
|
||||
|
||||
from adn_server.infrastructure.security.user_passwords_loader import UserPasswordsLoader
|
||||
|
||||
|
||||
def test_load_keeps_cached_passwords_when_file_becomes_invalid(tmp_path: Path) -> None:
|
||||
data_dir = tmp_path / "data"
|
||||
data_dir.mkdir()
|
||||
pw_file = data_dir / "user_passwords.json"
|
||||
pw_file.write_text(
|
||||
json.dumps({"passwords": {"7300391": "enc"}}),
|
||||
encoding="utf-8",
|
||||
)
|
||||
loader = UserPasswordsLoader(str(tmp_path))
|
||||
config = {
|
||||
"ALIASES": {"PATH": "data/"},
|
||||
"GLOBAL": {"USERS_PASS": "user_passwords.json", "CONFIG_PATH": "config"},
|
||||
}
|
||||
loader._passwords = {"7300391": "secret"}
|
||||
pw_file.write_text("not json", encoding="utf-8")
|
||||
result = loader.load(config)
|
||||
assert result == {"7300391": "secret"}
|
||||
Loading…
Reference in new issue