mirror of
https://github.com/jupyterhub/jupyterhub.git
synced 2025-10-16 14:33:00 +00:00
@@ -325,6 +325,18 @@ class JupyterHub(Application):
|
|||||||
redirect_to_server = Bool(
|
redirect_to_server = Bool(
|
||||||
True, help="Redirect user to server (if running), instead of control panel."
|
True, help="Redirect user to server (if running), instead of control panel."
|
||||||
).tag(config=True)
|
).tag(config=True)
|
||||||
|
activity_resolution = Integer(
|
||||||
|
30,
|
||||||
|
help="""
|
||||||
|
Resolution (in seconds) for updating activity
|
||||||
|
|
||||||
|
If activity is registered that is less than activity_resolution seconds
|
||||||
|
more recent than the current value,
|
||||||
|
the new value will be ignored.
|
||||||
|
|
||||||
|
This avoids too many writes to the Hub database.
|
||||||
|
""",
|
||||||
|
).tag(config=True)
|
||||||
last_activity_interval = Integer(
|
last_activity_interval = Integer(
|
||||||
300, help="Interval (in seconds) at which to update last-activity timestamps."
|
300, help="Interval (in seconds) at which to update last-activity timestamps."
|
||||||
).tag(config=True)
|
).tag(config=True)
|
||||||
@@ -2011,6 +2023,7 @@ class JupyterHub(Application):
|
|||||||
db=self.db,
|
db=self.db,
|
||||||
proxy=self.proxy,
|
proxy=self.proxy,
|
||||||
hub=self.hub,
|
hub=self.hub,
|
||||||
|
activity_resolution=self.activity_resolution,
|
||||||
admin_users=self.authenticator.admin_users,
|
admin_users=self.authenticator.admin_users,
|
||||||
admin_access=self.admin_access,
|
admin_access=self.admin_access,
|
||||||
authenticator=self.authenticator,
|
authenticator=self.authenticator,
|
||||||
|
@@ -249,10 +249,40 @@ class BaseHandler(RequestHandler):
|
|||||||
orm_token = orm.OAuthAccessToken.find(self.db, token)
|
orm_token = orm.OAuthAccessToken.find(self.db, token)
|
||||||
if orm_token is None:
|
if orm_token is None:
|
||||||
return None
|
return None
|
||||||
orm_token.last_activity = orm_token.user.last_activity = datetime.utcnow()
|
|
||||||
self.db.commit()
|
now = datetime.utcnow()
|
||||||
|
recorded = self._record_activity(orm_token, now)
|
||||||
|
if self._record_activity(orm_token.user, now) or recorded:
|
||||||
|
self.db.commit()
|
||||||
return self._user_from_orm(orm_token.user)
|
return self._user_from_orm(orm_token.user)
|
||||||
|
|
||||||
|
def _record_activity(self, obj, timestamp=None):
|
||||||
|
"""record activity on an ORM object
|
||||||
|
|
||||||
|
If last_activity was more recent than self.activity_resolution seconds ago,
|
||||||
|
do nothing to avoid unnecessarily frequent database commits.
|
||||||
|
|
||||||
|
Args:
|
||||||
|
obj: an ORM object with a last_activity attribute
|
||||||
|
timestamp (datetime, optional): the timestamp of activity to register.
|
||||||
|
Returns:
|
||||||
|
recorded (bool): True if activity was recorded, False if not.
|
||||||
|
"""
|
||||||
|
if timestamp is None:
|
||||||
|
timestamp = datetime.utcnow()
|
||||||
|
resolution = self.settings.get("activity_resolution", 0)
|
||||||
|
if not obj.last_activity or resolution == 0:
|
||||||
|
self.log.debug("Recording first activity for %s", obj)
|
||||||
|
obj.last_activity = timestamp
|
||||||
|
return True
|
||||||
|
if (timestamp - obj.last_activity).total_seconds() > resolution:
|
||||||
|
# this debug line will happen just too often
|
||||||
|
# uncomment to debug last_activity updates
|
||||||
|
# self.log.debug("Recording activity for %s", obj)
|
||||||
|
obj.last_activity = timestamp
|
||||||
|
return True
|
||||||
|
return False
|
||||||
|
|
||||||
async def refresh_auth(self, user, force=False):
|
async def refresh_auth(self, user, force=False):
|
||||||
"""Refresh user authentication info
|
"""Refresh user authentication info
|
||||||
|
|
||||||
@@ -323,14 +353,15 @@ class BaseHandler(RequestHandler):
|
|||||||
|
|
||||||
# record token activity
|
# record token activity
|
||||||
now = datetime.utcnow()
|
now = datetime.utcnow()
|
||||||
orm_token.last_activity = now
|
recorded = self._record_activity(orm_token, now)
|
||||||
if orm_token.user:
|
if orm_token.user:
|
||||||
# FIXME: scopes should give us better control than this
|
# FIXME: scopes should give us better control than this
|
||||||
# don't consider API requests originating from a server
|
# don't consider API requests originating from a server
|
||||||
# to be activity from the user
|
# to be activity from the user
|
||||||
if not orm_token.note.startswith("Server at "):
|
if not orm_token.note.startswith("Server at "):
|
||||||
orm_token.user.last_activity = now
|
recorded = self._record_activity(orm_token.user, now) or recorded
|
||||||
self.db.commit()
|
if recorded:
|
||||||
|
self.db.commit()
|
||||||
|
|
||||||
if orm_token.service:
|
if orm_token.service:
|
||||||
return orm_token.service
|
return orm_token.service
|
||||||
@@ -360,8 +391,8 @@ class BaseHandler(RequestHandler):
|
|||||||
clear()
|
clear()
|
||||||
return
|
return
|
||||||
# update user activity
|
# update user activity
|
||||||
user.last_activity = datetime.utcnow()
|
if self._record_activity(user):
|
||||||
self.db.commit()
|
self.db.commit()
|
||||||
return user
|
return user
|
||||||
|
|
||||||
def _user_from_orm(self, orm_user):
|
def _user_from_orm(self, orm_user):
|
||||||
|
Reference in New Issue
Block a user