src.scripts.db_recover
Восстановление БД из дампа
1"""Восстановление БД из дампа""" 2 3import asyncio 4import logging 5import logging.config 6import os 7import platform 8import sys 9from typing import Literal 10 11sys.path.insert(1, os.path.dirname(sys.path[0])) 12 13 14from core.config import Base, settings 15from core.path import PATH 16from db import models as _ # COMMENT TRIGGER 17from db.database import async_engine 18 19logging.config.fileConfig("log.ini", disable_existing_loggers=False) 20logging.getLogger("sqlalchemy.engine.Engine").setLevel(logging.INFO) 21logger = logging.getLogger() 22 23 24DUMPNAME = "dump_12_11_2024-16_20.sql" 25PLATFORM: Literal["Windows", "Linux"] = platform.system() 26 27 28async def postgresql_recover_tables(): 29 """Восстанавливает таблицы PostgreSQL из дампа. 30 31 Эта функция выполняет последовательные команды для завершения всех подключений к базе данных, 32 удаления существующей базы данных, создания новой базы данных и восстановления данных из дампа. 33 34 Raises: 35 Exception: Если возникла ошибка при выполнении команд. 36 """ 37 terminate = ( 38 f"psql -U {settings.DB_USER} " 39 f"-h {settings.DB_HOST} " 40 "-d nullbase " 41 f"-c \"SELECT pg_terminate_backend(pid) FROM pg_stat_activity WHERE datname = '{settings.DB_NAME}';\"" 42 ) 43 drop = ( 44 f"psql -U {settings.DB_USER} " 45 f"-h {settings.DB_HOST} " 46 "-d nullbase " 47 f'-c "DROP DATABASE IF EXISTS {settings.DB_NAME};"' 48 ) 49 50 create = ( 51 f"psql -U {settings.DB_USER} " 52 f"-h {settings.DB_HOST} " 53 "-d nullbase " 54 f"""-c \"CREATE DATABASE {settings.DB_NAME} 55 WITH 56 OWNER = {settings.DB_USER} 57 ENCODING = 'UTF8' 58 LC_COLLATE = 'en_US.utf8' 59 LC_CTYPE = 'en_US.utf8' 60 TABLESPACE = pg_default 61 CONNECTION LIMIT = -1 62 IS_TEMPLATE = False;\" 63 """ 64 ) 65 66 recover = ( 67 f"psql -U {settings.DB_USER} " 68 f"-h {settings.DB_HOST} " 69 f"-d {settings.DB_NAME} " 70 f'-f {os.path.join(PATH, "src", "db", "dumps", DUMPNAME)}' 71 ) 72 if PLATFORM == "Windows": 73 logger.error( 74 "ЭТА ПЛАТФОРМА НЕ ПОДДЕРЖИВАЕТСЯ", 75 ) 76 return 77 78 elif PLATFORM == "Linux": 79 login = f"export PGPASSWORD={settings.DB_PASS.get_secret_value()}" 80 81 for cmd in (terminate, drop, create, recover): 82 cmd = f"{login} && {cmd}" 83 84 logger.info(f"Executing command: {cmd}") 85 86 proc = await asyncio.create_subprocess_shell( 87 cmd, stdout=asyncio.subprocess.PIPE, stderr=asyncio.subprocess.PIPE 88 ) 89 stdout, stderr = await proc.communicate() 90 91 logger.info(f"pg_dump exited with {proc.returncode}") 92 93 if proc.returncode != 0: 94 error_message = stderr.decode("utf-8", errors="ignore") 95 logger.error(f"Ошибка создания дампа БД: {error_message}") 96 97 else: 98 print(stdout.decode("utf-8", errors="ignore")) 99 100 101async def create_new_tables(): 102 """Создает новые таблицы в базе данных. 103 104 Эта функция создает все таблицы, определенные в метаданных базы данных, 105 если они еще не существуют. 106 107 Raises: 108 Exception: Если возникла ошибка при создании таблиц. 109 """ 110 async with async_engine.connect() as conn: 111 async_engine.echo = True 112 await conn.run_sync(Base.metadata.create_all) 113 await conn.commit() 114 115 116if __name__ == "__main__": 117 118 async def start(): 119 """Запускает процесс восстановления таблиц и их создания. 120 121 Эта функция собирает задачи для восстановления таблиц и создания новых, 122 обрабатывает возможные исключения и ведет журнал. 123 124 Raises: 125 Exception: Если возникла ошибка при подключении к БД. 126 """ 127 bases = await asyncio.gather( 128 *(postgresql_recover_tables(),), 129 return_exceptions=True, 130 ) 131 132 for base in bases: 133 try: 134 if isinstance(base, Exception): 135 raise base 136 except Exception: 137 logger.exception("Возникло исключение при подключении к БД") 138 raise 139 140 await create_new_tables() 141 142 loop = asyncio.get_event_loop() 143 loop.run_until_complete(start())
logger =
<RootLogger root (DEBUG)>
DUMPNAME =
'dump_12_11_2024-16_20.sql'
PLATFORM: Literal['Windows', 'Linux'] =
'Linux'
async def
postgresql_recover_tables():
29async def postgresql_recover_tables(): 30 """Восстанавливает таблицы PostgreSQL из дампа. 31 32 Эта функция выполняет последовательные команды для завершения всех подключений к базе данных, 33 удаления существующей базы данных, создания новой базы данных и восстановления данных из дампа. 34 35 Raises: 36 Exception: Если возникла ошибка при выполнении команд. 37 """ 38 terminate = ( 39 f"psql -U {settings.DB_USER} " 40 f"-h {settings.DB_HOST} " 41 "-d nullbase " 42 f"-c \"SELECT pg_terminate_backend(pid) FROM pg_stat_activity WHERE datname = '{settings.DB_NAME}';\"" 43 ) 44 drop = ( 45 f"psql -U {settings.DB_USER} " 46 f"-h {settings.DB_HOST} " 47 "-d nullbase " 48 f'-c "DROP DATABASE IF EXISTS {settings.DB_NAME};"' 49 ) 50 51 create = ( 52 f"psql -U {settings.DB_USER} " 53 f"-h {settings.DB_HOST} " 54 "-d nullbase " 55 f"""-c \"CREATE DATABASE {settings.DB_NAME} 56 WITH 57 OWNER = {settings.DB_USER} 58 ENCODING = 'UTF8' 59 LC_COLLATE = 'en_US.utf8' 60 LC_CTYPE = 'en_US.utf8' 61 TABLESPACE = pg_default 62 CONNECTION LIMIT = -1 63 IS_TEMPLATE = False;\" 64 """ 65 ) 66 67 recover = ( 68 f"psql -U {settings.DB_USER} " 69 f"-h {settings.DB_HOST} " 70 f"-d {settings.DB_NAME} " 71 f'-f {os.path.join(PATH, "src", "db", "dumps", DUMPNAME)}' 72 ) 73 if PLATFORM == "Windows": 74 logger.error( 75 "ЭТА ПЛАТФОРМА НЕ ПОДДЕРЖИВАЕТСЯ", 76 ) 77 return 78 79 elif PLATFORM == "Linux": 80 login = f"export PGPASSWORD={settings.DB_PASS.get_secret_value()}" 81 82 for cmd in (terminate, drop, create, recover): 83 cmd = f"{login} && {cmd}" 84 85 logger.info(f"Executing command: {cmd}") 86 87 proc = await asyncio.create_subprocess_shell( 88 cmd, stdout=asyncio.subprocess.PIPE, stderr=asyncio.subprocess.PIPE 89 ) 90 stdout, stderr = await proc.communicate() 91 92 logger.info(f"pg_dump exited with {proc.returncode}") 93 94 if proc.returncode != 0: 95 error_message = stderr.decode("utf-8", errors="ignore") 96 logger.error(f"Ошибка создания дампа БД: {error_message}") 97 98 else: 99 print(stdout.decode("utf-8", errors="ignore"))
Восстанавливает таблицы PostgreSQL из дампа.
Эта функция выполняет последовательные команды для завершения всех подключений к базе данных, удаления существующей базы данных, создания новой базы данных и восстановления данных из дампа.
Raises:
- Exception: Если возникла ошибка при выполнении команд.
async def
create_new_tables():
102async def create_new_tables(): 103 """Создает новые таблицы в базе данных. 104 105 Эта функция создает все таблицы, определенные в метаданных базы данных, 106 если они еще не существуют. 107 108 Raises: 109 Exception: Если возникла ошибка при создании таблиц. 110 """ 111 async with async_engine.connect() as conn: 112 async_engine.echo = True 113 await conn.run_sync(Base.metadata.create_all) 114 await conn.commit()
Создает новые таблицы в базе данных.
Эта функция создает все таблицы, определенные в метаданных базы данных, если они еще не существуют.
Raises:
- Exception: Если возникла ошибка при создании таблиц.