From e4544294670bf2fcc87ef0d219f7752cee9e8f94 Mon Sep 17 00:00:00 2001 From: maxim Date: Fri, 2 Oct 2026 17:51:36 +0300 Subject: [PATCH] return old versions --- api/src/app.py | 141 ++++++++++++++++++----------------------- api/src/core/config.py | 16 +++-- 2 files changed, 71 insertions(+), 86 deletions(-) diff --git a/api/src/app.py b/api/src/app.py index 4f1edbb..28920b6 100644 --- a/api/src/app.py +++ b/api/src/app.py @@ -24,8 +24,8 @@ from src.core.clients import S3Storage, PollWorker from src.core.async_cache import AsyncInMemoryCache # from src.core.logger import setup_logger from nats.aio.client import Client as NATS -import nkeys import base64 +import nkeys from loguru import logger import os @@ -42,20 +42,6 @@ VERSION = "1.0.0" UP_TIME = datetime.now(timezone.utc) -kp = nkeys.from_seed(settings.OPENBAO.NATS.NATS_SEED.encode('utf-8')) - - -def jwt_cb(): - return settings.OPENBAO.NATS.NATS_JWT.encode('utf-8') - - -def sig_cb(nonce): - if (isinstance(nonce, str)): - nonce = nonce.encode('utf-8') - signed = kp.sign(nonce) - return base64.b64encode(signed) - - async def sub_cb(msg): return None @@ -94,80 +80,75 @@ async def lifespan(app): app.state.nats_subs = [] app.state.storage = None app.state.nats = None + app.state.poller = None + app.state.pdf_poller = None + s3_client = None + smb_registered = False try: - smbclient.register_session(settings.OPENBAO.SMB.SMB_HOST, settings.OPENBAO.SMB.SMB_LOGIN, settings.OPENBAO.SMB.SMB_PASSWORD) - except: - logger.exception("Ошибка при регистрации сессии SMB") - s3_client = Minio(settings.OPENBAO.MINIO.MINIO_URL, access_key=settings.OPENBAO.MINIO.MINIO_ADMIN_LOGIN, secret_key=settings.OPENBAO.MINIO.MINIO_ADMIN_PASSWORD, cert_check=False) - try: - bucket_exists = await s3_client.bucket_exists(settings.OPENBAO.MINIO.MINIO_BUCKET) - logger.info("Бакет проверен. bucket_exists={bucket_exists}", bucket_exists=bucket_exists) - except Exception as exc: - logger.exception( - "Не удалось проверить наличие бакетa. error_category=s3_error, error_type={error_type}, error={error}", - error_type=type(exc).__name__, - error=repr(exc), - ) - return - storage = S3Storage(client=s3_client, bucket_name=settings.OPENBAO.MINIO.MINIO_BUCKET) - app.state.storage = storage - cache = AsyncInMemoryCache() - nc = NATS() - if not settings.DEBUG: - try: - await nc.connect(settings.OPENBAO.NATS.NATS_URL, user_jwt_cb=jwt_cb, signature_cb=sig_cb, - max_reconnect_attempts=2) - logger.info("Подключение к NATS произошло") - except Exception as exc: - logger.exception( - "Не удалось проверить наличие бакетa. error_category=nats_error, error_type={error_type}, error={error}", - error_type=type(exc).__name__, - error=repr(exc), + minio = settings.OPENBAO.MINIO + if minio is not None: + s3_client = Minio( + minio.MINIO_URL, + access_key=minio.MINIO_ADMIN_LOGIN, + secret_key=minio.MINIO_ADMIN_PASSWORD, + secure=minio.MINIO_SECURE, ) - return - poller = PollWorker(nc, cache, storage) - await poller.start() - pdf_poller = PDFPollWorker(cache, storage) - await pdf_poller.start() - app.state.nats = nc - app.state.poller = poller - app.state.pdf_poller = pdf_poller - if not settings.DEBUG: - handler_cb = build_file_handler(nc, storage) + if not await s3_client.bucket_exists(minio.MINIO_BUCKET): + raise RuntimeError(f"Бакет MinIO {minio.MINIO_BUCKET!r} не создан") + app.state.storage = S3Storage(s3_client, minio.MINIO_BUCKET) + logger.info("MinIO подключён, бакет: {}", minio.MINIO_BUCKET) + + smb = settings.OPENBAO.SMB + if smb is not None: + smbclient.register_session(smb.SMB_HOST, smb.SMB_LOGIN, smb.SMB_PASSWORD, + port=smb.SMB_PORT) + smb_registered = True + logger.info("SMB подключён") + + nats_settings = settings.OPENBAO.NATS + if nats_settings is not None: + nc = NATS() + app.state.nats = nc + if not settings.DEBUG: + keypair = nkeys.from_seed(nats_settings.NATS_SEED.encode("utf-8")) + + def user_jwt_cb(): + return nats_settings.NATS_JWT.encode("utf-8") + + def signature_cb(nonce): + return base64.b64encode(keypair.sign(nonce.encode("utf-8"))) + + await nc.connect(nats_settings.NATS_URL, user_jwt_cb=user_jwt_cb, + signature_cb=signature_cb, max_reconnect_attempts=2) + logger.info("NATS подключён") + + missing = [name for name in ("MINIO", "NATS", "SMB") + if getattr(settings.OPENBAO, name) is None] + if missing: + logger.info("Распознавание файлов отключено: не настроены {}", ", ".join(missing)) + else: + cache = AsyncInMemoryCache() + app.state.poller = PollWorker(nc, cache, app.state.storage) + await app.state.poller.start() + app.state.pdf_poller = PDFPollWorker(cache, app.state.storage) + await app.state.pdf_poller.start() - try: - # sub_xls = await nc.subscribe('files.tabular_parsed', cb=handler_cb) - # sub_img = await nc.subscribe('files.img_parsed', cb=handler_cb) - # - # app.state.nats_subs = [sub_xls, sub_img] - logger.info("Подписка на топики завершена") - except Exception as exc: - logger.warning( - "Не удалось подписаться на тему. error_category=nats_error, error_type={error_type}, error={error}", - error_type=type(exc).__name__, - error=repr(exc), - ) - try: logger.info("Приложение запущено") yield - except Exception as exc: - logger.exception("ОШИБКА ПРИ РАБОТЕ С СЕКРЕТАМИ error={error}", error=repr(exc)) finally: - logger.info("Приложение закрывается") - smbclient.reset_connection_cache() + for worker in (app.state.poller, app.state.pdf_poller): + if worker is not None: + await worker.stop() if not settings.DEBUG: for sub in app.state.nats_subs: - logger.info("Отписываемся от топика") await sub.unsubscribe() - if app.state.nats: + if app.state.nats is not None: await app.state.nats.close() - if app.state.poller: - await app.state.poller.stop() - if app.state.storage: - await app.state.storage.client.close_session() - if app.state.pdf_poller: - await app.state.pdf_poller.stop() - logger.info("CLOSING APP AT ALL") + if s3_client is not None: + await s3_client.close_session() + if smb_registered: + smbclient.reset_connection_cache() + logger.info("Приложение закрывается") app = FastAPI( title="Fast API", @@ -247,4 +228,4 @@ class SPAStaticFiles(StaticFiles): app.mount("/", SPAStaticFiles(directory="web", html=True), name="web") -app.mount("/", StaticFiles(directory="web", html=True), name="web") \ No newline at end of file +app.mount("/", StaticFiles(directory="web", html=True), name="web") diff --git a/api/src/core/config.py b/api/src/core/config.py index c87a231..f5d21d6 100644 --- a/api/src/core/config.py +++ b/api/src/core/config.py @@ -1,4 +1,5 @@ from pydantic_settings import BaseSettings, SettingsConfigDict +from pydantic import Field class DBSettings(BaseSettings): @@ -10,23 +11,25 @@ class MinioSettings(BaseSettings): MINIO_ADMIN_LOGIN: str MINIO_ADMIN_PASSWORD: str MINIO_BUCKET: str + MINIO_SECURE: bool = True class NATSSettings(BaseSettings): NATS_URL: str - NATS_SEED: str - NATS_JWT: str + NATS_JWT: str = Field(min_length=1) + NATS_SEED: str = Field(min_length=1) class SMBSettings(BaseSettings): SMB_HOST: str + SMB_PORT: int = 445 SMB_PATH: str SMB_LOGIN: str SMB_PASSWORD: str class OpenBAOSettings(BaseSettings): DATABASE: DBSettings - MINIO: MinioSettings - NATS: NATSSettings - SMB: SMBSettings + MINIO: MinioSettings | None = None + NATS: NATSSettings | None = None + SMB: SMBSettings | None = None class ServerSettings(BaseSettings): HOST: str = "0.0.0.0" @@ -40,6 +43,7 @@ class Settings(BaseSettings): VERSION: str = '1.0.0' class Config: + case_sensitive = True extra = "ignore" env_file = ".env" env_nested_delimiter = "__" @@ -48,4 +52,4 @@ class Settings(BaseSettings): def get_settings() -> Settings: return Settings() -settings = get_settings() \ No newline at end of file +settings = get_settings()