mirror of
https://github.com/mofeng-git/One-KVM.git
synced 2026-03-17 00:16:50 +08:00
new events model
This commit is contained in:
@@ -20,6 +20,10 @@
|
||||
# ========================================================================== #
|
||||
|
||||
|
||||
import asyncio
|
||||
|
||||
from typing import AsyncGenerator
|
||||
|
||||
from ....yamlconf import Section
|
||||
|
||||
from .base import BaseInfoSubmanager
|
||||
@@ -34,17 +38,50 @@ from .fan import FanInfoSubmanager
|
||||
# =====
|
||||
class InfoManager:
|
||||
def __init__(self, config: Section) -> None:
|
||||
self.__subs = {
|
||||
self.__subs: dict[str, BaseInfoSubmanager] = {
|
||||
"system": SystemInfoSubmanager(config.kvmd.streamer.cmd),
|
||||
"auth": AuthInfoSubmanager(config.kvmd.auth.enabled),
|
||||
"meta": MetaInfoSubmanager(config.kvmd.info.meta),
|
||||
"auth": AuthInfoSubmanager(config.kvmd.auth.enabled),
|
||||
"meta": MetaInfoSubmanager(config.kvmd.info.meta),
|
||||
"extras": ExtrasInfoSubmanager(config),
|
||||
"hw": HwInfoSubmanager(**config.kvmd.info.hw._unpack()),
|
||||
"fan": FanInfoSubmanager(**config.kvmd.info.fan._unpack()),
|
||||
"hw": HwInfoSubmanager(**config.kvmd.info.hw._unpack()),
|
||||
"fan": FanInfoSubmanager(**config.kvmd.info.fan._unpack()),
|
||||
}
|
||||
self.__queue: "asyncio.Queue[tuple[str, (dict | None)]]" = asyncio.Queue()
|
||||
|
||||
def get_subs(self) -> set[str]:
|
||||
return set(self.__subs)
|
||||
|
||||
def get_submanager(self, name: str) -> BaseInfoSubmanager:
|
||||
return self.__subs[name]
|
||||
async def get_state(self, fields: (list[str] | None)=None) -> dict:
|
||||
fields = (fields or list(self.__subs))
|
||||
return dict(zip(fields, await asyncio.gather(*[
|
||||
self.__subs[field].get_state()
|
||||
for field in fields
|
||||
])))
|
||||
|
||||
async def trigger_state(self) -> None:
|
||||
await asyncio.gather(*[
|
||||
sub.trigger_state()
|
||||
for sub in self.__subs.values()
|
||||
])
|
||||
|
||||
async def poll_state(self) -> AsyncGenerator[dict, None]:
|
||||
while True:
|
||||
(field, value) = await self.__queue.get()
|
||||
yield {field: value}
|
||||
|
||||
async def systask(self) -> None:
|
||||
tasks = [
|
||||
asyncio.create_task(self.__poller(field))
|
||||
for field in self.__subs
|
||||
]
|
||||
try:
|
||||
await asyncio.gather(*tasks)
|
||||
except Exception:
|
||||
for task in tasks:
|
||||
task.cancel()
|
||||
await asyncio.gather(*tasks, return_exceptions=True)
|
||||
raise
|
||||
|
||||
async def __poller(self, field: str) -> None:
|
||||
async for state in self.__subs[field].poll_state():
|
||||
self.__queue.put_nowait((field, state))
|
||||
|
||||
@@ -20,6 +20,10 @@
|
||||
# ========================================================================== #
|
||||
|
||||
|
||||
from typing import AsyncGenerator
|
||||
|
||||
from .... import aiotools
|
||||
|
||||
from .base import BaseInfoSubmanager
|
||||
|
||||
|
||||
@@ -27,6 +31,15 @@ from .base import BaseInfoSubmanager
|
||||
class AuthInfoSubmanager(BaseInfoSubmanager):
|
||||
def __init__(self, enabled: bool) -> None:
|
||||
self.__enabled = enabled
|
||||
self.__notifier = aiotools.AioNotifier()
|
||||
|
||||
async def get_state(self) -> dict:
|
||||
return {"enabled": self.__enabled}
|
||||
|
||||
async def trigger_state(self) -> None:
|
||||
self.__notifier.notify()
|
||||
|
||||
async def poll_state(self) -> AsyncGenerator[(dict | None), None]:
|
||||
while True:
|
||||
await self.__notifier.wait()
|
||||
yield (await self.get_state())
|
||||
|
||||
@@ -20,7 +20,17 @@
|
||||
# ========================================================================== #
|
||||
|
||||
|
||||
from typing import AsyncGenerator
|
||||
|
||||
|
||||
# =====
|
||||
class BaseInfoSubmanager:
|
||||
async def get_state(self) -> (dict | None):
|
||||
raise NotImplementedError
|
||||
|
||||
async def trigger_state(self) -> None:
|
||||
raise NotImplementedError
|
||||
|
||||
async def poll_state(self) -> AsyncGenerator[(dict | None), None]:
|
||||
yield None
|
||||
raise NotImplementedError
|
||||
|
||||
@@ -24,6 +24,8 @@ import os
|
||||
import re
|
||||
import asyncio
|
||||
|
||||
from typing import AsyncGenerator
|
||||
|
||||
from ....logging import get_logger
|
||||
|
||||
from ....yamlconf import Section
|
||||
@@ -41,6 +43,7 @@ from .base import BaseInfoSubmanager
|
||||
class ExtrasInfoSubmanager(BaseInfoSubmanager):
|
||||
def __init__(self, global_config: Section) -> None:
|
||||
self.__global_config = global_config
|
||||
self.__notifier = aiotools.AioNotifier()
|
||||
|
||||
async def get_state(self) -> (dict | None):
|
||||
try:
|
||||
@@ -65,6 +68,14 @@ class ExtrasInfoSubmanager(BaseInfoSubmanager):
|
||||
if sui is not None:
|
||||
await aiotools.shield_fg(sui.close())
|
||||
|
||||
async def trigger_state(self) -> None:
|
||||
self.__notifier.notify()
|
||||
|
||||
async def poll_state(self) -> AsyncGenerator[(dict | None), None]:
|
||||
while True:
|
||||
await self.__notifier.wait()
|
||||
yield (await self.get_state())
|
||||
|
||||
def __get_extras_path(self, *parts: str) -> str:
|
||||
return os.path.join(self.__global_config.kvmd.info.extras, *parts)
|
||||
|
||||
|
||||
@@ -21,7 +21,6 @@
|
||||
|
||||
|
||||
import copy
|
||||
import asyncio
|
||||
|
||||
from typing import AsyncGenerator
|
||||
|
||||
@@ -53,6 +52,8 @@ class FanInfoSubmanager(BaseInfoSubmanager):
|
||||
self.__timeout = timeout
|
||||
self.__state_poll = state_poll
|
||||
|
||||
self.__notifier = aiotools.AioNotifier()
|
||||
|
||||
async def get_state(self) -> dict:
|
||||
monitored = await self.__get_monitored()
|
||||
return {
|
||||
@@ -60,24 +61,28 @@ class FanInfoSubmanager(BaseInfoSubmanager):
|
||||
"state": ((await self.__get_fan_state() if monitored else None)),
|
||||
}
|
||||
|
||||
async def poll_state(self) -> AsyncGenerator[dict, None]:
|
||||
prev_state: dict = {}
|
||||
async def trigger_state(self) -> None:
|
||||
self.__notifier.notify(1)
|
||||
|
||||
async def poll_state(self) -> AsyncGenerator[(dict | None), None]:
|
||||
prev: dict = {}
|
||||
while True:
|
||||
if self.__unix_path:
|
||||
pure = state = await self.get_state()
|
||||
if (await self.__notifier.wait(timeout=self.__state_poll)) > 0:
|
||||
prev = {}
|
||||
new = await self.get_state()
|
||||
pure = copy.deepcopy(new)
|
||||
if pure["state"] is not None:
|
||||
try:
|
||||
pure = copy.deepcopy(state)
|
||||
pure["state"]["service"]["now_ts"] = 0
|
||||
except Exception:
|
||||
pass
|
||||
if pure != prev_state:
|
||||
yield state
|
||||
prev_state = pure
|
||||
await asyncio.sleep(self.__state_poll)
|
||||
if pure != prev:
|
||||
prev = pure
|
||||
yield new
|
||||
else:
|
||||
await self.__notifier.wait()
|
||||
yield (await self.get_state())
|
||||
await aiotools.wait_infinite()
|
||||
|
||||
# =====
|
||||
|
||||
|
||||
@@ -22,6 +22,7 @@
|
||||
|
||||
import os
|
||||
import asyncio
|
||||
import copy
|
||||
|
||||
from typing import Callable
|
||||
from typing import AsyncGenerator
|
||||
@@ -60,6 +61,8 @@ class HwInfoSubmanager(BaseInfoSubmanager):
|
||||
|
||||
self.__dt_cache: dict[str, str] = {}
|
||||
|
||||
self.__notifier = aiotools.AioNotifier()
|
||||
|
||||
async def get_state(self) -> dict:
|
||||
(
|
||||
base,
|
||||
@@ -97,14 +100,18 @@ class HwInfoSubmanager(BaseInfoSubmanager):
|
||||
},
|
||||
}
|
||||
|
||||
async def trigger_state(self) -> None:
|
||||
self.__notifier.notify(1)
|
||||
|
||||
async def poll_state(self) -> AsyncGenerator[dict, None]:
|
||||
prev_state: dict = {}
|
||||
prev: dict = {}
|
||||
while True:
|
||||
state = await self.get_state()
|
||||
if state != prev_state:
|
||||
yield state
|
||||
prev_state = state
|
||||
await asyncio.sleep(self.__state_poll)
|
||||
if (await self.__notifier.wait(timeout=self.__state_poll)) > 0:
|
||||
prev = {}
|
||||
new = await self.get_state()
|
||||
if new != prev:
|
||||
prev = copy.deepcopy(new)
|
||||
yield new
|
||||
|
||||
# =====
|
||||
|
||||
|
||||
@@ -20,6 +20,8 @@
|
||||
# ========================================================================== #
|
||||
|
||||
|
||||
from typing import AsyncGenerator
|
||||
|
||||
from ....logging import get_logger
|
||||
|
||||
from ....yamlconf.loader import load_yaml_file
|
||||
@@ -33,6 +35,7 @@ from .base import BaseInfoSubmanager
|
||||
class MetaInfoSubmanager(BaseInfoSubmanager):
|
||||
def __init__(self, meta_path: str) -> None:
|
||||
self.__meta_path = meta_path
|
||||
self.__notifier = aiotools.AioNotifier()
|
||||
|
||||
async def get_state(self) -> (dict | None):
|
||||
try:
|
||||
@@ -40,3 +43,11 @@ class MetaInfoSubmanager(BaseInfoSubmanager):
|
||||
except Exception:
|
||||
get_logger(0).exception("Can't parse meta")
|
||||
return None
|
||||
|
||||
async def trigger_state(self) -> None:
|
||||
self.__notifier.notify()
|
||||
|
||||
async def poll_state(self) -> AsyncGenerator[(dict | None), None]:
|
||||
while True:
|
||||
await self.__notifier.wait()
|
||||
yield (await self.get_state())
|
||||
|
||||
@@ -24,8 +24,11 @@ import os
|
||||
import asyncio
|
||||
import platform
|
||||
|
||||
from typing import AsyncGenerator
|
||||
|
||||
from ....logging import get_logger
|
||||
|
||||
from .... import aiotools
|
||||
from .... import aioproc
|
||||
|
||||
from .... import __version__
|
||||
@@ -37,6 +40,7 @@ from .base import BaseInfoSubmanager
|
||||
class SystemInfoSubmanager(BaseInfoSubmanager):
|
||||
def __init__(self, streamer_cmd: list[str]) -> None:
|
||||
self.__streamer_cmd = streamer_cmd
|
||||
self.__notifier = aiotools.AioNotifier()
|
||||
|
||||
async def get_state(self) -> dict:
|
||||
streamer_info = await self.__get_streamer_info()
|
||||
@@ -50,6 +54,14 @@ class SystemInfoSubmanager(BaseInfoSubmanager):
|
||||
},
|
||||
}
|
||||
|
||||
async def trigger_state(self) -> None:
|
||||
self.__notifier.notify()
|
||||
|
||||
async def poll_state(self) -> AsyncGenerator[(dict | None), None]:
|
||||
while True:
|
||||
await self.__notifier.wait()
|
||||
yield (await self.get_state())
|
||||
|
||||
# =====
|
||||
|
||||
async def __get_streamer_info(self) -> dict:
|
||||
|
||||
Reference in New Issue
Block a user