avoid instantiating User object wrapper in user_model

This commit is contained in:
Min RK
2023-06-28 15:32:50 +02:00
parent e12a317e7a
commit 1734b75d47
2 changed files with 31 additions and 9 deletions

View File

@@ -268,9 +268,30 @@ class APIHandler(BaseHandler):
return self._include_stopped_servers
def user_model(self, user):
"""Get the JSON model for a User object"""
"""Get the JSON model for a User object
User may be either a high-level User wrapper,
or a low-level orm.User.
"""
is_orm = False
if isinstance(user, orm.User):
user = self.users[user.id]
if user.id in self.users:
# if it's an 'active' user, it's in the users dict,
# get the wrapper so we can get 'pending' state, etc.
user = self.users[user.id]
else:
# don't create wrapper of low-level orm object
is_orm = True
if is_orm:
# if it's not in the users dict,
# we know it has no running servers
running = False
spawners = {}
if not is_orm:
running = user.running
spawners = user.spawners
include_stopped_servers = self.include_stopped_servers
# TODO: we shouldn't fetch fields we can't read and then filter them out,
# which may be wasted database queries
@@ -283,7 +304,7 @@ class APIHandler(BaseHandler):
'admin': user.admin,
'roles': [r.name for r in user.roles],
'groups': [g.name for g in user.groups],
'server': user.url if user.running else None,
'server': user.url if running else None,
'pending': None,
'created': isoformat(user.created),
'last_activity': isoformat(user.last_activity),
@@ -313,12 +334,12 @@ class APIHandler(BaseHandler):
model, access_map, user, kind='user', keys=allowed_keys
)
if model:
if '' in user.spawners and 'pending' in allowed_keys:
model['pending'] = user.spawners[''].pending
if '' in spawners and 'pending' in allowed_keys:
model['pending'] = spawners[''].pending
servers = {}
scope_filter = self.get_scope_filter('read:servers')
for name, spawner in user.spawners.items():
for name, spawner in spawners.items():
# include 'active' servers, not just ready
# (this includes pending events)
if (spawner.active or include_stopped_servers) and scope_filter(

View File

@@ -9,7 +9,7 @@ from datetime import datetime, timedelta, timezone
from async_generator import aclosing
from dateutil.parser import parse as parse_date
from sqlalchemy import func, or_
from sqlalchemy.orm import raiseload, selectinload
from sqlalchemy.orm import joinedload, raiseload, selectinload
from tornado import web
from tornado.iostream import StreamClosedError
@@ -132,10 +132,11 @@ class UserListAPIHandler(APIHandler):
orm.Server, orm.Spawner.server
)
# apply joinedload options
# apply eager load options
query = query.options(
selectinload(orm.User.roles),
selectinload(orm.User.groups),
selectinload(orm.User._orm_spawners),
joinedload(orm.User._orm_spawners),
)
# if testing, add raiseload to prevent lazy loading of anything we didn't ask for
if True: