0d34867a69
- New `features/doc-service` FastAPI microservice: PDF upload, async text extraction (pdfplumber), AI classification via Anthropic/Ollama/ LM Studio, per-user categories, file download - Alembic migration isolated with `alembic_version_doc_service` table - Main backend: httpx proxy routers for /api/documents/* and /api/documents/categories/*, admin settings API at /api/settings/* - Runtime config in /config/doc_service_config.json (shared Docker volume); api_key masking on reads; atomic write with os.replace() - Frontend: DocumentsPage, DocumentAdminSettingsPage, updated AppsPage launcher hub, simplified Nav (removed Settings link), new routes - docker-compose: doc-service service, doc_data + app_config volumes, removed internal:true from backend-net for outbound AI API calls - Fix pre-commit hook: probe Docker socket path so git subprocess picks up Docker Desktop on macOS - Fix security_check.py: use sys.executable for bandit so venv python is used instead of system python Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
56 lines
1.5 KiB
Python
56 lines
1.5 KiB
Python
import asyncio
|
|
from logging.config import fileConfig
|
|
|
|
from alembic import context
|
|
from sqlalchemy.ext.asyncio import create_async_engine
|
|
|
|
from app.core.config import settings
|
|
from app.database import Base
|
|
import app.models # noqa: F401 — registers Document, DocumentCategory, CategoryAssignment
|
|
|
|
config = context.config
|
|
config.set_main_option("sqlalchemy.url", settings.DATABASE_URL)
|
|
|
|
if config.config_file_name:
|
|
fileConfig(config.config_file_name)
|
|
|
|
target_metadata = Base.metadata
|
|
|
|
# Separate version table — must not collide with the main backend's alembic_version table.
|
|
VERSION_TABLE = "alembic_version_doc_service"
|
|
|
|
|
|
def run_migrations_offline():
|
|
context.configure(
|
|
url=settings.DATABASE_URL,
|
|
target_metadata=target_metadata,
|
|
literal_binds=True,
|
|
dialect_opts={"paramstyle": "named"},
|
|
version_table=VERSION_TABLE,
|
|
)
|
|
with context.begin_transaction():
|
|
context.run_migrations()
|
|
|
|
|
|
def do_run_migrations(connection):
|
|
context.configure(
|
|
connection=connection,
|
|
target_metadata=target_metadata,
|
|
version_table=VERSION_TABLE,
|
|
)
|
|
with context.begin_transaction():
|
|
context.run_migrations()
|
|
|
|
|
|
async def run_migrations_online():
|
|
engine = create_async_engine(settings.DATABASE_URL)
|
|
async with engine.connect() as conn:
|
|
await conn.run_sync(do_run_migrations)
|
|
await engine.dispose()
|
|
|
|
|
|
if context.is_offline_mode():
|
|
run_migrations_offline()
|
|
else:
|
|
asyncio.run(run_migrations_online())
|