forked from retoor/devplacepy
155 lines
5.0 KiB
Python
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()
|