From 079358a29f93b5975e7c7498f3af0ff9c6877429 Mon Sep 17 00:00:00 2001 From: Vasek Sraier Date: Sat, 17 Jul 2021 10:39:48 +0200 Subject: [PATCH] manager: human-readable numerical IDs (instead of uuids used previously) --- manager/knot_resolver_manager/kres_manager.py | 54 ++++++++++++++++--- .../kresd_controller/interface.py | 2 +- .../kresd_controller/supervisord/__init__.py | 6 +-- .../kresd_controller/supervisord/config.py | 2 +- .../kresd_controller/systemd/__init__.py | 4 +- 5 files changed, 53 insertions(+), 15 deletions(-) diff --git a/manager/knot_resolver_manager/kres_manager.py b/manager/knot_resolver_manager/kres_manager.py index a1820a797..f369d05a0 100644 --- a/manager/knot_resolver_manager/kres_manager.py +++ b/manager/knot_resolver_manager/kres_manager.py @@ -1,8 +1,9 @@ import asyncio +import itertools import logging +import weakref from subprocess import SubprocessError -from typing import List, Optional, Set, Type -from uuid import uuid4 +from typing import List, Optional, Type from knot_resolver_manager.constants import KRESD_CONFIG_FILE from knot_resolver_manager.exceptions import ValidationException @@ -15,14 +16,43 @@ from .datamodel import KresConfig logger = logging.getLogger(__name__) +class _PrettyID: + """ + ID object. Effectively only a wrapper around an int, so that the references + behave normally (bypassing integer interning and other optimizations) + """ + + def __init__(self, n: int): + self._id = n + + def __str__(self): + return str(self._id) + + def __hash__(self) -> int: + return self._id + + def __eq__(self, o: object) -> bool: + return isinstance(o, _PrettyID) and self._id == o._id + + class _PrettyIDAllocator: + """ + Pretty numeric ID allocator. Keeps weak refences to the IDs it has + allocated. The IDs get recycled once the previously allocated ID + objects get garbage collected + """ + def __init__(self): - self._used: Set[int] = set() + self._used: "weakref.WeakSet[_PrettyID]" = weakref.WeakSet() - def free(self, n: int): - assert n in self._used - self._used.remove(n) + def alloc(self) -> _PrettyID: + for i in itertools.count(start=1): + val = _PrettyID(i) + if val not in self._used: + self._used.add(val) + return val + raise RuntimeError("Reached an end of an infinite loop. How?") class KresManager: @@ -53,13 +83,14 @@ class KresManager: self._manager_lock = asyncio.Lock() self._controller: SubprocessController self._last_used_config: Optional[KresConfig] = None + self._id_allocator = _PrettyIDAllocator() async def load_system_state(self): async with self._manager_lock: await self._collect_already_running_children() async def _spawn_new_worker(self): - subprocess = await self._controller.create_subprocess(SubprocessType.KRESD, str(uuid4())) + subprocess = await self._controller.create_subprocess(SubprocessType.KRESD, self._id_allocator.alloc()) await subprocess.start() self._workers.append(subprocess) @@ -71,7 +102,14 @@ class KresManager: await kresd.stop() async def _collect_already_running_children(self): - self._workers.extend(await self._controller.get_all_running_instances()) + for subp in await self._controller.get_all_running_instances(): + if subp.type == SubprocessType.KRESD: + self._workers.append(subp) + elif subp.type == SubprocessType.GC: + assert self._gc is None + self._gc = subp + else: + raise RuntimeError("unexpected subprocess type") async def _rolling_restart(self): for kresd in self._workers: diff --git a/manager/knot_resolver_manager/kresd_controller/interface.py b/manager/knot_resolver_manager/kresd_controller/interface.py index cadd0c44a..7a8784337 100644 --- a/manager/knot_resolver_manager/kresd_controller/interface.py +++ b/manager/knot_resolver_manager/kresd_controller/interface.py @@ -65,7 +65,7 @@ class SubprocessController: """ raise NotImplementedError() - async def create_subprocess(self, subprocess_type: SubprocessType, id_hint: str) -> Subprocess: + async def create_subprocess(self, subprocess_type: SubprocessType, id_hint: object) -> Subprocess: """ Return a Subprocess object which can be operated on. The subprocess is not started or in any way active after this call. That has to be performaed manually diff --git a/manager/knot_resolver_manager/kresd_controller/supervisord/__init__.py b/manager/knot_resolver_manager/kresd_controller/supervisord/__init__.py index ab88a3e05..383df85bb 100644 --- a/manager/knot_resolver_manager/kresd_controller/supervisord/__init__.py +++ b/manager/knot_resolver_manager/kresd_controller/supervisord/__init__.py @@ -22,9 +22,9 @@ logger = logging.getLogger(__name__) class SupervisordSubprocess(Subprocess): - def __init__(self, controller: "SupervisordSubprocessController", id_: str, type_: SubprocessType): + def __init__(self, controller: "SupervisordSubprocessController", id_: object, type_: SubprocessType): self._controller: "SupervisordSubprocessController" = controller - self._id: str = id_ + self._id = id_ self._type: SubprocessType = type_ @property @@ -103,5 +103,5 @@ class SupervisordSubprocessController(SubprocessController): assert subprocess in self._running_instances await restart(subprocess.id) - async def create_subprocess(self, subprocess_type: SubprocessType, id_hint: str) -> Subprocess: + async def create_subprocess(self, subprocess_type: SubprocessType, id_hint: object) -> Subprocess: return SupervisordSubprocess(self, id_hint, subprocess_type) diff --git a/manager/knot_resolver_manager/kresd_controller/supervisord/config.py b/manager/knot_resolver_manager/kresd_controller/supervisord/config.py index 0572cde82..ae77b729c 100644 --- a/manager/knot_resolver_manager/kresd_controller/supervisord/config.py +++ b/manager/knot_resolver_manager/kresd_controller/supervisord/config.py @@ -131,7 +131,7 @@ def list_fatal_subprocesses_ids() -> List[str]: return [pr["name"] for pr in processes if pr["statename"] == "FATAL"] -def create_id(type_name: SubprocessType, id_: str) -> str: +def create_id(type_name: SubprocessType, id_: object) -> str: return f"{type_name.name}_{id_}" diff --git a/manager/knot_resolver_manager/kresd_controller/systemd/__init__.py b/manager/knot_resolver_manager/kresd_controller/systemd/__init__.py index 9aaaefab0..98a0e3707 100644 --- a/manager/knot_resolver_manager/kresd_controller/systemd/__init__.py +++ b/manager/knot_resolver_manager/kresd_controller/systemd/__init__.py @@ -21,7 +21,7 @@ class SystemdSubprocess(Subprocess): def __init__( self, type_: SubprocessType, - id_: str, + id_: object, systemd_type: systemd.SystemdType, persistance_type: SystemdPersistanceType = SystemdPersistanceType.PERSISTENT, ): @@ -128,5 +128,5 @@ class SystemdSubprocessController(SubprocessController): async def shutdown_controller(self) -> None: pass - async def create_subprocess(self, subprocess_type: SubprocessType, id_hint: str) -> Subprocess: + async def create_subprocess(self, subprocess_type: SubprocessType, id_hint: object) -> Subprocess: return SystemdSubprocess(subprocess_type, id_hint, self._systemd_type, self._persistance_type) -- 2.47.3