moving config storage to mongo
This commit is contained in:
1 parent
9bc34d4dc9
commit
7d070dec40
2 files changed
+43
-30
No files matched your search
+29
-19
@@ -1,11 +1,16 @@
|
|||||||
"""Config loading and mode helpers shared across monitors and the bot."""
|
"""Config loading and mode helpers shared across monitors and the bot."""
|
||||||
|
|
||||||
import json
|
|
||||||
import logging
|
import logging
|
||||||
import pathlib
|
|
||||||
from enum import Enum
|
from enum import Enum
|
||||||
|
|
||||||
from monitor_utils.constants import LOGGERS
|
from monitor_utils.constants import LOGGERS
|
||||||
|
from monitor_utils.database import get_collection
|
||||||
|
|
||||||
|
CONFIGS_COLLECTION_NAME = "configs"
|
||||||
|
|
||||||
|
|
||||||
|
class ConfigNotFoundError(Exception):
|
||||||
|
"""Raised when a monitor has no config document in Mongo."""
|
||||||
|
|
||||||
|
|
||||||
class DevelopmentMode(str, Enum):
|
class DevelopmentMode(str, Enum):
|
||||||
@@ -21,29 +26,34 @@ def is_production(development_mode: DevelopmentMode) -> bool:
|
|||||||
return development_mode == DevelopmentMode.PRODUCTION
|
return development_mode == DevelopmentMode.PRODUCTION
|
||||||
|
|
||||||
|
|
||||||
def get_config(
|
async def get_config(monitor_name: str, use_production: bool = False) -> dict:
|
||||||
monitor_name: str,
|
"""Load a monitor's config document from Mongo.
|
||||||
config_dir: str | pathlib.Path = "configs",
|
|
||||||
test_config_dir: str | pathlib.Path = "tests/configs",
|
Reads the configs collection in production and configs_testing in
|
||||||
use_production_path: bool = False,
|
development, so a dev run never reads production routing.
|
||||||
) -> tuple[dict, pathlib.Path]:
|
|
||||||
"""Load a monitor's JSON config from the production or test directory.
|
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
monitor_name: Monitor name with or without a .json suffix.
|
monitor_name: Monitor identifier (the config document _id).
|
||||||
config_dir: Directory holding production configs.
|
use_production: Read the production configs collection instead of
|
||||||
test_config_dir: Directory holding test configs.
|
configs_testing.
|
||||||
use_production_path: Load from config_dir instead of test_config_dir.
|
|
||||||
|
|
||||||
Returns:
|
Returns:
|
||||||
Tuple of the parsed config dict and the resolved config path.
|
The config document, including its categories and channels.
|
||||||
|
|
||||||
|
Raises:
|
||||||
|
ConfigNotFoundError: When no document exists for the monitor.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
monitor_name = monitor_name.replace(".json", "")
|
collection_name = (
|
||||||
base = config_dir if use_production_path else test_config_dir
|
CONFIGS_COLLECTION_NAME
|
||||||
config_path = pathlib.Path(base) / f"{monitor_name}.json"
|
if use_production
|
||||||
with open(config_path) as f:
|
else f"{CONFIGS_COLLECTION_NAME}_testing"
|
||||||
return json.load(f), config_path
|
)
|
||||||
|
config = await get_collection(collection_name).find_one({"_id": monitor_name})
|
||||||
|
if config is None:
|
||||||
|
raise ConfigNotFoundError(monitor_name)
|
||||||
|
|
||||||
|
return config
|
||||||
|
|
||||||
|
|
||||||
def set_logger_levels(loggers: list[str] = LOGGERS, level: int = logging.WARNING):
|
def set_logger_levels(loggers: list[str] = LOGGERS, level: int = logging.WARNING):
|
||||||
|
|||||||
+14
-11
@@ -28,18 +28,20 @@ from monitor_utils.sessions import get_base_session, get_tls_session
|
|||||||
LOGGER = logging.getLogger(__name__)
|
LOGGER = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
|
||||||
def init_monitor(
|
async def init_monitor(
|
||||||
monitor_name: str,
|
monitor_name: str,
|
||||||
development_mode: DevelopmentMode,
|
development_mode: DevelopmentMode,
|
||||||
production_proxy_path: str = "proxies.txt",
|
production_proxy_path: str = "proxies.txt",
|
||||||
testing_proxy_path: str = "configs/proxies.txt",
|
testing_proxy_path: str = "configs/proxies.txt",
|
||||||
logging_level=LOGGING_LEVEL,
|
logging_level=LOGGING_LEVEL,
|
||||||
) -> tuple[list[str], AsyncIOMotorCollection, AioProxies]:
|
) -> tuple[list[str] | dict[str, str], AsyncIOMotorCollection, AioProxies]:
|
||||||
"""Run shared monitor startup and return categories, collection, and proxies.
|
"""Run shared monitor startup and return categories, collection, and proxies.
|
||||||
|
|
||||||
Configures JSON logging under the monitor's name, applies logger levels,
|
Configures JSON logging under the monitor's name, applies logger levels,
|
||||||
loads the monitor config and Mongo collection, and loads proxies from the
|
loads the monitor config and Mongo collection, and loads proxies from the
|
||||||
production or testing path based on development_mode.
|
production or testing path based on development_mode. Async because the
|
||||||
|
config now lives in Mongo; call it from inside the monitor's event loop
|
||||||
|
(in main), not at module import.
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
monitor_name: Monitor identifier used for logging and config lookup.
|
monitor_name: Monitor identifier used for logging and config lookup.
|
||||||
@@ -61,7 +63,7 @@ def init_monitor(
|
|||||||
output="json",
|
output="json",
|
||||||
)
|
)
|
||||||
set_logger_levels()
|
set_logger_levels()
|
||||||
category_names, _, collection = setup_config(
|
category_names, _, collection = await setup_config(
|
||||||
monitor_name=monitor_name, development_mode=development_mode
|
monitor_name=monitor_name, development_mode=development_mode
|
||||||
)
|
)
|
||||||
proxy_path = production_proxy_path if use_production else testing_proxy_path
|
proxy_path = production_proxy_path if use_production else testing_proxy_path
|
||||||
@@ -69,17 +71,18 @@ def init_monitor(
|
|||||||
return category_names, collection, proxies
|
return category_names, collection, proxies
|
||||||
|
|
||||||
|
|
||||||
def setup_config(
|
async def setup_config(
|
||||||
monitor_name: str, development_mode: DevelopmentMode
|
monitor_name: str, development_mode: DevelopmentMode
|
||||||
) -> tuple[list[str], dict[int], AsyncIOMotorCollection]:
|
) -> tuple[list[str] | dict[str, str], dict[str, str | list[str]], AsyncIOMotorCollection]:
|
||||||
"""Load monitor config and resolve the Mongo collection for the mode.
|
"""Load monitor config and resolve the Mongo collection for the mode.
|
||||||
|
|
||||||
Testing mode appends a _testing suffix to the collection name so
|
Testing mode reads the configs_testing collection and appends a _testing
|
||||||
production data is never touched during development.
|
suffix to the product collection name so production data is never touched
|
||||||
|
during development.
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
monitor_name: Monitor identifier used for config and collection lookup.
|
monitor_name: Monitor identifier used for config and collection lookup.
|
||||||
development_mode: Selects the production or testing config path and
|
development_mode: Selects the production or testing config and
|
||||||
collection.
|
collection.
|
||||||
|
|
||||||
Returns:
|
Returns:
|
||||||
@@ -87,9 +90,9 @@ def setup_config(
|
|||||||
"""
|
"""
|
||||||
|
|
||||||
use_production = is_production(development_mode)
|
use_production = is_production(development_mode)
|
||||||
config, _ = get_config(
|
config = await get_config(
|
||||||
monitor_name=monitor_name,
|
monitor_name=monitor_name,
|
||||||
use_production_path=use_production,
|
use_production=use_production,
|
||||||
)
|
)
|
||||||
|
|
||||||
category_names = config["categories"]
|
category_names = config["categories"]
|
||||||
|
|||||||
Reference in new issue
Block a user