fix: RDP slot occupancy and cleanup_loop always running
- admin_page: slot shown as occupied based on ACTIVE status only (no time cutoff) - go_service: busy slots checked by ACTIVE status (no cutoff) — cleanup_loop handles expiry - startup_event: cleanup_loop starts regardless of ENABLE_STARTUP_MAINTENANCE flag; pool/container init guarded by the flag separately - cleanup_loop: RDPSLOT sessions expire correctly and trigger container restart Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
+31
-31
@@ -1742,37 +1742,41 @@ def startup_event():
|
||||
fcntl.flock(lock_file.fileno(), fcntl.LOCK_UN)
|
||||
ensure_icons_dir()
|
||||
bootstrap_admin()
|
||||
if not ENABLE_STARTUP_MAINTENANCE:
|
||||
logger.info("startup_maintenance_disabled")
|
||||
return
|
||||
if not try_acquire_maintenance_leader():
|
||||
logger.info("maintenance_leader_skipped")
|
||||
return
|
||||
|
||||
db = SessionLocal()
|
||||
try:
|
||||
ensure_universal_pool()
|
||||
ensure_web_pool()
|
||||
for svc in db.scalars(
|
||||
select(Service).where(
|
||||
Service.active == True,
|
||||
Service.type.in_([ServiceType.WEB, ServiceType.RDP]),
|
||||
)
|
||||
).all():
|
||||
if svc.type == ServiceType.WEB and WEB_POOL_SIZE <= 0:
|
||||
ensure_warm_pool(svc)
|
||||
elif svc.type == ServiceType.RDP:
|
||||
slots = db.scalars(select(RdpSlot).where(RdpSlot.service_id == svc.id)).all()
|
||||
for slot in slots:
|
||||
try:
|
||||
start_rdp_slot_container(slot, svc)
|
||||
slot.container_name = _rdp_slot_container_name(svc.slug, slot.id)
|
||||
except Exception:
|
||||
logger.exception("startup_rdp_slot_start_failed slot_id=%s", slot.id)
|
||||
if slots:
|
||||
db.commit()
|
||||
finally:
|
||||
db.close()
|
||||
if ENABLE_STARTUP_MAINTENANCE:
|
||||
db = SessionLocal()
|
||||
try:
|
||||
ensure_universal_pool()
|
||||
ensure_web_pool()
|
||||
for svc in db.scalars(
|
||||
select(Service).where(
|
||||
Service.active == True,
|
||||
Service.type.in_([ServiceType.WEB, ServiceType.RDP]),
|
||||
)
|
||||
).all():
|
||||
if svc.type == ServiceType.WEB and WEB_POOL_SIZE <= 0:
|
||||
ensure_warm_pool(svc)
|
||||
elif svc.type == ServiceType.RDP:
|
||||
slots = db.scalars(select(RdpSlot).where(RdpSlot.service_id == svc.id)).all()
|
||||
for slot in slots:
|
||||
try:
|
||||
cname = _rdp_slot_container_name(svc.slug, slot.id)
|
||||
try:
|
||||
c = docker_client().containers.get(cname)
|
||||
if c.status != "running":
|
||||
c.start()
|
||||
except docker.errors.NotFound:
|
||||
start_rdp_slot_container(slot, svc)
|
||||
slot.container_name = cname
|
||||
except Exception:
|
||||
logger.exception("startup_rdp_slot_start_failed slot_id=%s", slot.id)
|
||||
if slots:
|
||||
db.commit()
|
||||
finally:
|
||||
db.close()
|
||||
|
||||
thread = threading.Thread(target=cleanup_loop, daemon=True)
|
||||
thread.start()
|
||||
@@ -1953,7 +1957,6 @@ def admin_page(request: Request, admin: User = Depends(require_admin), db: Sessi
|
||||
{"cutoff": cutoff},
|
||||
).mappings().all()
|
||||
rdp_slots: dict[int, list] = {}
|
||||
cutoff_slot = now_utc() - dt.timedelta(seconds=SESSION_IDLE_SECONDS)
|
||||
for svc in rdp_services:
|
||||
slots = db.scalars(select(RdpSlot).where(RdpSlot.service_id == svc.id).order_by(RdpSlot.id)).all()
|
||||
slot_list = []
|
||||
@@ -1962,7 +1965,6 @@ def admin_page(request: Request, admin: User = Depends(require_admin), db: Sessi
|
||||
select(SessionModel).where(
|
||||
SessionModel.container_id == f"RDPSLOT:{slot.id}",
|
||||
SessionModel.status == SessionStatus.ACTIVE,
|
||||
SessionModel.last_access_at >= cutoff_slot,
|
||||
)
|
||||
)
|
||||
running = False
|
||||
@@ -2162,12 +2164,10 @@ def go_service(
|
||||
session_id = str(uuid.uuid4())
|
||||
try:
|
||||
with allocator_lock(db, 91003, timeout_seconds=GO_POOL_LOCK_TIMEOUT_SECONDS):
|
||||
cutoff = now_utc() - dt.timedelta(seconds=SESSION_IDLE_SECONDS)
|
||||
busy_slot_ids: set[int] = set()
|
||||
for row in db.scalars(
|
||||
select(SessionModel).where(
|
||||
SessionModel.status == SessionStatus.ACTIVE,
|
||||
SessionModel.last_access_at >= cutoff,
|
||||
SessionModel.service_id == service.id,
|
||||
SessionModel.container_id.like("RDPSLOT:%"),
|
||||
)
|
||||
|
||||
Reference in New Issue
Block a user