File size: 3,106 Bytes
02a8414 0a9438f 02a8414 0a9438f | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 | from __future__ import annotations
from sqlalchemy.orm import Session, joinedload
from app.models import Admin, Submission, Task
from app.services.presence import is_online
from app.web import local_now
def online_admins(db: Session) -> list[Admin]:
now = local_now()
admins = db.query(Admin).filter(Admin.is_active.is_(True)).order_by(Admin.id.asc()).all()
return [admin for admin in admins if is_online(admin.last_seen_at, now)]
def rebalance_pending_reviews(db: Session, activity_id: int | None = None) -> list[Submission]:
pending_query = (
db.query(Submission)
.options(
joinedload(Submission.user),
joinedload(Submission.group),
joinedload(Submission.task).joinedload(Task.activity),
joinedload(Submission.assigned_admin),
joinedload(Submission.reviewed_by),
)
.filter(Submission.status == "pending")
.order_by(Submission.created_at.asc(), Submission.id.asc())
)
if activity_id is not None:
pending_query = pending_query.join(Submission.task).filter(Task.activity_id == activity_id)
pending_submissions = pending_query.all()
admins = online_admins(db)
if not admins:
changed = False
for submission in pending_submissions:
if submission.assigned_admin_id is None and submission.assigned_at is None:
continue
submission.assigned_admin_id = None
submission.assigned_at = None
changed = True
if changed:
db.commit()
pending_submissions = pending_query.all()
return pending_submissions
now = local_now()
active_ids = {admin.id for admin in admins}
buckets: dict[int, list[Submission]] = {admin.id: [] for admin in admins}
changed = False
for submission in pending_submissions:
if submission.assigned_admin_id in active_ids:
buckets[submission.assigned_admin_id].append(submission)
for submission in pending_submissions:
if submission.assigned_admin_id in active_ids:
continue
target_admin = min(admins, key=lambda item: (len(buckets[item.id]), item.id))
submission.assigned_admin_id = target_admin.id
submission.assigned_at = now
buckets[target_admin.id].append(submission)
changed = True
while True:
source_admin = max(admins, key=lambda item: (len(buckets[item.id]), -item.id))
target_admin = min(admins, key=lambda item: (len(buckets[item.id]), item.id))
if len(buckets[source_admin.id]) - len(buckets[target_admin.id]) <= 1:
break
buckets[source_admin.id].sort(key=lambda item: (item.created_at, item.id))
moved_submission = buckets[source_admin.id].pop()
moved_submission.assigned_admin_id = target_admin.id
moved_submission.assigned_at = now
buckets[target_admin.id].append(moved_submission)
changed = True
if changed:
db.commit()
pending_submissions = pending_query.all()
return pending_submissions
|