mirror of
https://github.com/mealie-recipes/mealie.git
synced 2025-12-02 00:24:13 -05:00
* Creating postgres migration script and starting to set up to detect database * non-working placeholders for postgres pg_tgrm * First draft of some indexes * non-working commit of postgres indexing * Further non-working edits to db-centric fuzzy search * update alembic for extensions * More non-working setup * Move db type check to init_db * fix typo in db name check * Add sqlite token search and postgres full text search * reorder search to hit exact matches faster * Add settings and docs for POSTGRES_LANGUAGE (full text search) * Use user-specified POSTGRES_LANGUAGE in search * fix fuzzy search typo * Remove full text search and instead order by trigram match * cleaner adding of indices, remove fulltext * Cleanup old import of getting app settings * Fix typo in index * Fix some alembic fuzzy typos * Remove diagnostic printing from alembic migration * Fix mixed up commutator for trigram operator and relax criteria * forgot to remove query debug * sort only on name * token and fuzzy search tests * Refactor recipe search test to avoid rare random string cross-matches. * Add ability to quote parts of search for exact match * Remove internal punctuation, unless it's quoted for literal search * Add tests for special character removal and literal search * Remove the outer double quotes from searches, but leave internal single quotes alone. * Update tests to avoid intra-test name collisions * Fixing leftovers highlighted by lint * cleanup linting and mypy errors * Fix test cross-matching on dirty db (leftovers from bulk import) * forgot to cleanup something when debugging mypy errors * re-order pg_trgm loading in postgres * address comments
111 lines
3.3 KiB
Python
111 lines
3.3 KiB
Python
from collections.abc import Callable
|
|
from pathlib import Path
|
|
from time import sleep
|
|
|
|
from sqlalchemy import engine, orm, text
|
|
|
|
from alembic import command, config, script
|
|
from alembic.config import Config
|
|
from alembic.runtime import migration
|
|
from mealie.core import root_logger
|
|
from mealie.core.config import get_app_settings
|
|
from mealie.db.db_setup import session_context
|
|
from mealie.db.fixes.fix_slug_foods import fix_slug_food_names
|
|
from mealie.repos.all_repositories import get_repositories
|
|
from mealie.repos.repository_factory import AllRepositories
|
|
from mealie.repos.seed.init_users import default_user_init
|
|
from mealie.schema.user.user import GroupBase
|
|
from mealie.services.group_services.group_service import GroupService
|
|
|
|
PROJECT_DIR = Path(__file__).parent.parent.parent
|
|
|
|
logger = root_logger.get_logger("init_db")
|
|
|
|
|
|
def init_db(db: AllRepositories) -> None:
|
|
default_group_init(db)
|
|
default_user_init(db)
|
|
|
|
|
|
def default_group_init(db: AllRepositories):
|
|
settings = get_app_settings()
|
|
|
|
logger.info("Generating Default Group")
|
|
|
|
GroupService.create_group(db, GroupBase(name=settings.DEFAULT_GROUP))
|
|
|
|
|
|
# Adapted from https://alembic.sqlalchemy.org/en/latest/cookbook.html#test-current-database-revision-is-at-head-s
|
|
def db_is_at_head(alembic_cfg: config.Config) -> bool:
|
|
settings = get_app_settings()
|
|
url = settings.DB_URL
|
|
|
|
if not url:
|
|
raise ValueError("No database url found")
|
|
|
|
connectable = engine.create_engine(url)
|
|
directory = script.ScriptDirectory.from_config(alembic_cfg)
|
|
with connectable.begin() as connection:
|
|
context = migration.MigrationContext.configure(connection)
|
|
return set(context.get_current_heads()) == set(directory.get_heads())
|
|
|
|
|
|
def safe_try(func: Callable):
|
|
try:
|
|
func()
|
|
except Exception as e:
|
|
logger.error(f"Error calling '{func.__name__}': {e}")
|
|
|
|
|
|
def connect(session: orm.Session) -> bool:
|
|
try:
|
|
session.execute(text("SELECT 1"))
|
|
return True
|
|
except Exception as e:
|
|
logger.error(f"Error connecting to database: {e}")
|
|
return False
|
|
|
|
|
|
def main():
|
|
# Wait for database to connect
|
|
max_retry = 10
|
|
wait_seconds = 1
|
|
|
|
with session_context() as session:
|
|
while True:
|
|
if connect(session):
|
|
logger.info("Database connection established.")
|
|
break
|
|
|
|
logger.error(f"Database connection failed. Retrying in {wait_seconds} seconds...")
|
|
max_retry -= 1
|
|
|
|
sleep(wait_seconds)
|
|
|
|
if max_retry == 0:
|
|
raise ConnectionError("Database connection failed - exiting application.")
|
|
|
|
alembic_cfg = Config(str(PROJECT_DIR / "alembic.ini"))
|
|
if db_is_at_head(alembic_cfg):
|
|
logger.debug("Migration not needed.")
|
|
else:
|
|
logger.info("Migration needed. Performing migration...")
|
|
command.upgrade(alembic_cfg, "head")
|
|
|
|
if session.get_bind().name == "postgresql": # needed for fuzzy search and fast GIN text indices
|
|
session.execute(text("CREATE EXTENSION IF NOT EXISTS pg_trgm;"))
|
|
|
|
db = get_repositories(session)
|
|
|
|
if db.users.get_all():
|
|
logger.debug("Database exists")
|
|
else:
|
|
logger.info("Database contains no users, initializing...")
|
|
init_db(db)
|
|
|
|
safe_try(lambda: fix_slug_food_names(db))
|
|
|
|
|
|
if __name__ == "__main__":
|
|
main()
|