Monorepo: consolidate 7 repos into one
All checks were successful
Build and Deploy / build-and-deploy (push) Successful in 1m5s
All checks were successful
Build and Deploy / build-and-deploy (push) Successful in 1m5s
Combines shared, blog, market, cart, events, federation, and account into a single repository. Eliminates submodule sync, sibling model copying at build time, and per-app CI orchestration. Changes: - Remove per-app .git, .gitmodules, .gitea, submodule shared/ dirs - Remove stale sibling model copies from each app - Update all 6 Dockerfiles for monorepo build context (root = .) - Add build directives to docker-compose.yml - Add single .gitea/workflows/ci.yml with change detection - Add .dockerignore for monorepo build context - Create __init__.py for federation and account (cross-app imports)
This commit is contained in:
0
shared/db/__init__.py
Normal file
0
shared/db/__init__.py
Normal file
4
shared/db/base.py
Normal file
4
shared/db/base.py
Normal file
@@ -0,0 +1,4 @@
|
||||
from __future__ import annotations
|
||||
from sqlalchemy.orm import declarative_base
|
||||
|
||||
Base = declarative_base()
|
||||
82
shared/db/session.py
Normal file
82
shared/db/session.py
Normal file
@@ -0,0 +1,82 @@
|
||||
from __future__ import annotations
|
||||
import os
|
||||
from contextlib import asynccontextmanager
|
||||
from sqlalchemy.ext.asyncio import create_async_engine, async_sessionmaker, AsyncSession
|
||||
from quart import Quart, g
|
||||
|
||||
DATABASE_URL = (
|
||||
os.getenv("DATABASE_URL_ASYNC")
|
||||
or os.getenv("DATABASE_URL")
|
||||
or "postgresql+asyncpg://localhost/blog"
|
||||
)
|
||||
|
||||
_engine = create_async_engine(
|
||||
DATABASE_URL,
|
||||
future=True,
|
||||
echo=False,
|
||||
pool_pre_ping=True,
|
||||
pool_size=5,
|
||||
max_overflow=10,
|
||||
)
|
||||
|
||||
_Session = async_sessionmaker(
|
||||
bind=_engine,
|
||||
class_=AsyncSession,
|
||||
expire_on_commit=False,
|
||||
)
|
||||
|
||||
@asynccontextmanager
|
||||
async def get_session():
|
||||
"""Always create a fresh AsyncSession for this block."""
|
||||
sess = _Session()
|
||||
try:
|
||||
yield sess
|
||||
finally:
|
||||
await sess.close()
|
||||
|
||||
|
||||
def register_db(app: Quart):
|
||||
|
||||
@app.before_request
|
||||
async def open_session():
|
||||
g.s = _Session()
|
||||
g.tx = await g.s.begin()
|
||||
g.had_error = False
|
||||
|
||||
@app.after_request
|
||||
async def maybe_commit(response):
|
||||
# Runs BEFORE bytes are sent.
|
||||
if not g.had_error and 200 <= response.status_code < 400:
|
||||
try:
|
||||
if hasattr(g, "tx"):
|
||||
await g.tx.commit()
|
||||
except Exception as e:
|
||||
print(f'commit failed {e}')
|
||||
if hasattr(g, "tx"):
|
||||
await g.tx.rollback()
|
||||
from quart import make_response
|
||||
return await make_response("Commit failed", 500)
|
||||
return response
|
||||
|
||||
@app.teardown_request
|
||||
async def finish(exc):
|
||||
try:
|
||||
# If an exception occurred OR we didn't commit (still in txn), roll back.
|
||||
if hasattr(g, "s"):
|
||||
if exc is not None or g.s.in_transaction():
|
||||
if hasattr(g, "tx") and g.tx.is_active:
|
||||
try:
|
||||
await g.tx.rollback()
|
||||
except Exception:
|
||||
pass
|
||||
finally:
|
||||
if hasattr(g, "s"):
|
||||
try:
|
||||
await g.s.close()
|
||||
except Exception:
|
||||
pass
|
||||
|
||||
@app.errorhandler(Exception)
|
||||
async def mark_error(e):
|
||||
g.had_error = True
|
||||
raise
|
||||
Reference in New Issue
Block a user