creating tables

This commit is contained in:
Doctor Delpy 2025-12-11 19:12:05 +03:00
parent b0055e174f
commit 1def6e3512
3 changed files with 31 additions and 33 deletions

View File

@ -25,7 +25,32 @@ if int(os.getenv("SANIC_MAINTENANCE", '0')) == 1:
while True:
time.sleep(1)
from app.core.models import Memory
def init_db_schema_sync() -> None:
"""Initialise all SQLAlchemy models in the database before services start.
This ensures that every table defined on AlchemyBase.metadata (including
newer ones like DHT and service_config) exists before any component
accesses the database.
"""
try:
from sqlalchemy import create_engine
from app.core.models import AlchemyBase # imports all models and populates metadata
db_url = os.environ.get('DATABASE_URL')
if not db_url:
raise RuntimeError('DATABASE_URL is not set')
# Normalise DSN to sync driver for schema creation
if '+asyncpg' in db_url:
db_url_sync = db_url.replace('+asyncpg', '+psycopg2')
else:
db_url_sync = db_url
sync_engine = create_engine(db_url_sync, pool_pre_ping=True)
AlchemyBase.metadata.create_all(sync_engine)
except Exception as e:
make_log('Startup', f'DB sync init failed: {e}', level='error')
async def queue_daemon(app):
@ -78,27 +103,15 @@ async def execute_queue(app):
if __name__ == '__main__':
# Ensure DB schema is fully initialised for all models
init_db_schema_sync()
from app.core.models import Memory
main_memory = Memory()
if startup_target == '__main__':
# Defer heavy imports to avoid side effects in background services
# Mark this process as the primary node for seeding/config init
os.environ.setdefault('NODE_ROLE', 'primary')
# Create DB tables synchronously before importing HTTP app to satisfy _secrets
try:
from sqlalchemy import create_engine
from app.core.models import AlchemyBase # imports all models
db_url = os.environ.get('DATABASE_URL')
if not db_url:
raise RuntimeError('DATABASE_URL is not set')
# Normalize to sync driver
if '+asyncpg' in db_url:
db_url_sync = db_url.replace('+asyncpg', '+psycopg2')
else:
db_url_sync = db_url
sync_engine = create_engine(db_url_sync, pool_pre_ping=True)
AlchemyBase.metadata.create_all(sync_engine)
except Exception as e:
make_log('Startup', f'DB sync init failed: {e}', level='error')
from app.api import app
# Delay aiogram dispatcher creation until loop is running
from app.core._config import SANIC_PORT, PROJECT_HOST, DATABASE_URL

View File

@ -32,22 +32,6 @@ def _init_seed_via_db() -> bytes:
engine = create_engine(DATABASE_URL, pool_pre_ping=True)
role = os.getenv("NODE_ROLE", "worker").lower()
# Best-effort: ensure service_config table exists before waiting on it.
# This complements the synchronous init in app.__main__ and protects
# against ordering issues where _secrets is imported before that init runs.
try:
from sqlalchemy.exc import SQLAlchemyError
with engine.begin() as conn:
inspector = inspect(conn)
if not inspector.has_table('service_config'):
ServiceConfigValue.__table__.create(bind=conn, checkfirst=True)
except SQLAlchemyError as exc:
make_log("HotWallet", f"Failed to ensure service_config table: {exc}", level="error")
except Exception:
# Avoid failing hard here; the fallback waiter below may still succeed
pass
def db_ready(conn) -> bool:
try:
inspector = inspect(conn)

View File

@ -61,6 +61,7 @@ class DHTStore:
try:
from sqlalchemy import create_engine
from sqlalchemy.orm import sessionmaker
from app.core._config import DATABASE_URL
from app.core.models.dht import DHTRecordRow