feat: extend operational investigation workflows
Generic Container CI/CD / test-build-publish (push) Successful in 3m53s
Server CI/CD v2 / build-test-publish-and-deploy (push) Successful in 3m52s

This commit is contained in:
2026-10-30 17:30:19 +08:00
parent 63af998045
commit 05183aff93
82 changed files with 4644 additions and 330 deletions
+8 -27
View File
@@ -46,22 +46,10 @@ class WorkerSettings:
@asynccontextmanager
async def queue_repository(project_id):
"""Resolve current routing from metadata, never from a job payload."""
from psycopg import AsyncConnection
from psycopg.rows import dict_row
from app.infra.db.metadb.database import SessionLocal
from app.infra.db.metadb.repositories.metadata_repository import MetadataRepository
from app.infra.db.postgresql.calculation_jobs import CalculationJobRepository
async with SessionLocal() as session:
metadata = MetadataRepository(session)
project = await metadata.get_project_by_id(UUID(str(project_id)))
if not project or project.status != 'active':
raise ValueError('Calculation project is not active')
routing = await metadata.get_project_db_routing(UUID(str(project_id)), 'biz_data')
if not routing or routing.db_type != 'postgresql':
raise ValueError('Project business PostgreSQL routing is unavailable')
await session.commit()
async with await AsyncConnection.connect(routing.dsn, row_factory=dict_row) as conn:
yield CalculationJobRepository(conn, project_id)
from app.infra.db.calculation_worker import queue_repository as open_repository
async with open_repository(project_id) as repository:
yield repository
@asynccontextmanager
@@ -246,15 +234,11 @@ class CalculationWorker:
await cleanup_job_resources(row, directory)
async def run(self):
from sqlalchemy import text
from app.infra.db.metadb.database import engine
from app.infra.db.calculation_worker import calculation_supervisor_lease
# Dedicated session-level metadata lock: independent API workers never
# participate; duplicate supervisors exit before claiming any jobs.
async with engine.connect() as lock:
acquired = await lock.scalar(text("SELECT pg_try_advisory_lock(1748531781, 2)"))
await lock.commit()
if not acquired:
raise RuntimeError('Another calculation supervisor is already active')
async with calculation_supervisor_lease() as lease:
tasks = set()
project_cursor = 0
try:
@@ -264,8 +248,7 @@ class CalculationWorker:
await recover_job_resources(self.settings.project_ids)
while True:
async with asyncio.timeout(self.settings.heartbeat_seconds):
await lock.execute(text('SELECT 1'))
await lock.commit()
await lease.ping()
for task in tuple(tasks):
if task.done():
tasks.remove(task)
@@ -286,8 +269,6 @@ class CalculationWorker:
for task in tasks:
task.cancel()
await asyncio.gather(*tasks, return_exceptions=True)
await lock.execute(text('SELECT pg_advisory_unlock(1748531781, 2)'))
await lock.commit()
async def guard_child(input_path, output_path):