87 lines
3.1 KiB
Python
87 lines
3.1 KiB
Python
from pathlib import Path
|
||
|
||
import aiosqlite
|
||
import structlog
|
||
|
||
from ..models import AppConfig
|
||
|
||
logger = structlog.get_logger()
|
||
|
||
|
||
class DatabaseService:
|
||
def __init__(self, config: AppConfig) -> None:
|
||
self.config = config
|
||
self.logger = structlog.get_logger().bind(service="database")
|
||
|
||
async def initialize_database(self) -> None:
|
||
db_path = Path(self.config.db_path)
|
||
db_path.parent.mkdir(parents=True, exist_ok=True)
|
||
|
||
self.logger.info("Создание схемы базы данных", db_path=self.config.db_path)
|
||
|
||
async with aiosqlite.connect(self.config.db_path) as conn:
|
||
await conn.execute("""
|
||
CREATE TABLE IF NOT EXISTS articles (
|
||
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||
url TEXT NOT NULL UNIQUE,
|
||
title TEXT NOT NULL,
|
||
raw_text TEXT NOT NULL,
|
||
simplified_text TEXT,
|
||
status TEXT NOT NULL DEFAULT 'pending',
|
||
error_message TEXT,
|
||
token_count_raw INTEGER,
|
||
token_count_simplified INTEGER,
|
||
processing_time_seconds REAL,
|
||
created_at TEXT NOT NULL,
|
||
updated_at TEXT
|
||
)
|
||
""")
|
||
|
||
await conn.execute("""
|
||
CREATE INDEX IF NOT EXISTS idx_articles_url ON articles(url)
|
||
""")
|
||
|
||
await conn.execute("""
|
||
CREATE INDEX IF NOT EXISTS idx_articles_status ON articles(status)
|
||
""")
|
||
|
||
await conn.commit()
|
||
|
||
await self._configure_sqlite()
|
||
|
||
self.logger.info("База данных инициализирована", db_path=self.config.db_path)
|
||
|
||
async def _configure_sqlite(self) -> None:
|
||
async with aiosqlite.connect(self.config.db_path) as conn:
|
||
await conn.execute("PRAGMA journal_mode=WAL")
|
||
|
||
await conn.execute("PRAGMA cache_size=10000")
|
||
|
||
await conn.execute("PRAGMA synchronous=NORMAL")
|
||
|
||
await conn.execute("PRAGMA busy_timeout=30000")
|
||
|
||
await conn.commit()
|
||
self.logger.info("SQLite настроен для оптимальной производительности")
|
||
|
||
async def get_connection(self) -> aiosqlite.Connection:
|
||
self.logger.info("Открытие соединения с базой данных")
|
||
return aiosqlite.connect(
|
||
self.config.db_path,
|
||
timeout=30.0,
|
||
)
|
||
|
||
async def health_check(self) -> bool:
|
||
try:
|
||
async with await self.get_connection() as connection:
|
||
self.logger.info("Вошли в async context manager")
|
||
self.logger.info("Выполняем SELECT 1...")
|
||
await connection.execute("SELECT 1")
|
||
self.logger.info("SELECT 1 выполнен успешно")
|
||
return True
|
||
except Exception as e:
|
||
self.logger.error("Database health check failed", error=str(e))
|
||
import traceback
|
||
self.logger.error("Traceback", traceback=traceback.format_exc())
|
||
return False
|