Files
devplacepy/devplacepy/lifespan.py
T
retoor 7274cc1840
DevPlace CI / test (push) Failing after 45m54s
Party Hardy
2026-10-17 07:33:08 +02:00

155 lines
5.0 KiB
Python

# retoor <retoor@molodetz.nl>
import fcntl
import logging
import os
from contextlib import asynccontextmanager, contextmanager
from fastapi import FastAPI
from devplacepy.config import (
INIT_LOCK_FILE,
PORT,
SERVICE_LOCK_FILE,
ensure_data_dirs,
)
from devplacepy.database import init_db
from devplacepy.services.acceptance.service import AcceptanceService
from devplacepy.services.audit import AuditService
from devplacepy.services.backup import BackupService
from devplacepy.services.background import background
from devplacepy.services.bot import BotsService
from devplacepy.services.community.service import CommunityService
from devplacepy.services.containers.service import ContainerService
from devplacepy.services.containers.workspace_service import WorkspaceService
from devplacepy.services.dbapi.service import DbApiJobService
from devplacepy.services.devii import DeviiService
from devplacepy.services.gitea.service import IssueTrackerService
from devplacepy.services.jobs.award_service import AwardService
from devplacepy.services.jobs.deepsearch.service import DeepsearchService
from devplacepy.services.jobs.fork_service import ForkService
from devplacepy.services.jobs.issue_create_service import IssueCreateService
from devplacepy.services.jobs.isslop.service import IsslopService
from devplacepy.services.jobs.planning_service import PlanningReportService
from devplacepy.services.jobs.seo.service import SeoService
from devplacepy.services.jobs.seo_meta_service import SeoMetaService
from devplacepy.services.jobs.zip_service import ZipService
from devplacepy.services.live_view_relay import LiveViewRelayService
from devplacepy.services.manager import service_manager
from devplacepy.services.moderation.service import ModerationService
from devplacepy.services.news import NewsService
from devplacepy.services.nodes.service import NodesService
from devplacepy.services.notification_relay import NotificationRelayService
from devplacepy.services.openai_gateway import GatewayService
from devplacepy.services.opinionwar.service import OpinionWarService
from devplacepy.services.presence_relay import PresenceRelayService
from devplacepy.services.pubsub import PubSubService
from devplacepy.services.push import PushService
from devplacepy.services.telegram import TelegramService
from devplacepy.services.telegram.outbox_service import TelegramOutboxService
from devplacepy.services.xmlrpc import XmlrpcService
logger = logging.getLogger(__name__)
SERVICE_CLASSES = [
NewsService,
BotsService,
GatewayService,
DeviiService,
ZipService,
ForkService,
SeoService,
SeoMetaService,
AwardService,
BackupService,
DbApiJobService,
PubSubService,
NotificationRelayService,
OpinionWarService,
LiveViewRelayService,
PresenceRelayService,
DeepsearchService,
IsslopService,
IssueCreateService,
PlanningReportService,
IssueTrackerService,
ContainerService,
WorkspaceService,
XmlrpcService,
AuditService,
ModerationService,
AcceptanceService,
CommunityService,
NodesService,
PushService,
TelegramService,
TelegramOutboxService,
]
_service_lock_handle = None
@contextmanager
def init_lock():
handle = open(INIT_LOCK_FILE, "w")
try:
fcntl.flock(handle, fcntl.LOCK_EX)
yield
finally:
fcntl.flock(handle, fcntl.LOCK_UN)
handle.close()
def acquire_service_lock() -> bool:
global _service_lock_handle
handle = open(SERVICE_LOCK_FILE, "w")
try:
fcntl.flock(handle, fcntl.LOCK_EX | fcntl.LOCK_NB)
except OSError:
handle.close()
return False
_service_lock_handle = handle
return True
@asynccontextmanager
async def lifespan(app: FastAPI):
ensure_data_dirs()
with init_lock():
init_db()
from devplacepy.push import ensure_certificates
ensure_certificates()
from devplacepy.services.openai_gateway import model_health
model_health.seed_from_ledger()
for service_cls in SERVICE_CLASSES:
service_manager.register(service_cls())
if not os.environ.get("DEVPLACE_DISABLE_SERVICES"):
await background.start()
if acquire_service_lock():
service_manager.set_lock_owner(True)
service_manager.supervise()
logger.info(f"Background services started in worker pid {os.getpid()}")
else:
logger.info(
f"Worker pid {os.getpid()} declined service lock; another worker owns background services"
)
from devplacepy.services.statistics.tracking import start_visit_flusher
start_visit_flusher()
logger.info(f"DevPlace started on port {PORT}")
yield
logger.info("Shutting down services...")
from devplacepy.services.statistics.tracking import flush_visits
flush_visits()
await service_manager.shutdown_all()
await background.stop()
from devplacepy.services.containers import forward
await forward.close_client()
from devplacepy import push
await push.shutdown_providers()