Skip to content

Commit dcf8a50

Browse files
authored
Cleanup and add validation to new adaptive saving strategy (#169)
* remove unused _last_save_duration attr * remove poll_interval trait, init with min_poll_interval * add validation for new adaptive timing traits * fix ui-tests/ NPM resolutions
1 parent 63e25bb commit dcf8a50

File tree

3 files changed

+5193
-23
lines changed

3 files changed

+5193
-23
lines changed

jupyter_server_documents/rooms/yroom_file_api.py

Lines changed: 27 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
import logging
99
from tornado.web import HTTPError
1010
from traitlets.config import LoggingConfigurable
11-
from traitlets import Float
11+
from traitlets import Float, validate
1212

1313
if TYPE_CHECKING:
1414
from typing import Any, Coroutine, Literal
@@ -17,6 +17,8 @@
1717
from jupyter_server.services.contents.manager import ContentsManager
1818
from ..outputs.manager import OutputsManager
1919

20+
DEFAULT_MIN_POLL_INTERVAL = 0.5
21+
DEFAULT_POLL_INTERVAL_MULTIPLIER = 5.0
2022
class YRoomFileAPI(LoggingConfigurable):
2123
"""Provides an API to interact with a single file for a YRoom.
2224
@@ -45,23 +47,15 @@ class YRoomFileAPI(LoggingConfigurable):
4547
file_id: The unique identifier for this file.
4648
"""
4749

48-
poll_interval = Float(
49-
default_value=0.5,
50-
help="Sets the initial interval for saving the YDoc & checking the file "
51-
"for changes. This serves as the starting value before adaptive timing "
52-
"takes effect. Defaults to 0.5 seconds.",
53-
config=True,
54-
)
55-
5650
min_poll_interval = Float(
57-
default_value=0.5,
51+
default_value=DEFAULT_MIN_POLL_INTERVAL,
5852
help="Minimum autosave interval in seconds. The adaptive timing will "
5953
"never go below this value. Defaults to 0.5 seconds.",
6054
config=True,
6155
)
6256

6357
poll_interval_multiplier = Float(
64-
default_value=5.0,
58+
default_value=DEFAULT_POLL_INTERVAL_MULTIPLIER,
6559
help="Multiplier applied to save duration to calculate the next poll "
6660
"interval. For example, if a save takes 1 second and the multiplier is "
6761
"5.0, the next poll interval will be 5 seconds (bounded by min/max). "
@@ -126,12 +120,6 @@ class YRoomFileAPI(LoggingConfigurable):
126120
dual-writes or dirty-reads.
127121
"""
128122

129-
_last_save_duration: float | None
130-
"""
131-
The duration in seconds of the last save operation. Used to calculate the
132-
adaptive poll interval.
133-
"""
134-
135123
_adaptive_poll_interval: float
136124
"""
137125
The current adaptive poll interval in seconds, calculated based on the last
@@ -165,8 +153,26 @@ def __init__(self, *args, **kwargs):
165153
self._content_lock = asyncio.Lock()
166154

167155
# Initialize adaptive timing attributes
168-
self._last_save_duration = None
169-
self._adaptive_poll_interval = self.poll_interval
156+
self._adaptive_poll_interval = self.min_poll_interval
157+
158+
@validate("min_poll_interval", "poll_interval_multiplier")
159+
def _validate_adaptive_timing_traits(self, proposal):
160+
trait_name = proposal['trait'].name
161+
value = proposal['value']
162+
163+
if trait_name == "min_poll_interval":
164+
default_value = DEFAULT_MIN_POLL_INTERVAL
165+
else:
166+
default_value = DEFAULT_POLL_INTERVAL_MULTIPLIER
167+
168+
if value <= 0:
169+
self.log.warning(
170+
f"`YRoomFileAPI.{trait_name}` must be >0. Received: {value}. "
171+
f"Reverting to default value {default_value}."
172+
)
173+
return default_value
174+
175+
return proposal["value"]
170176

171177

172178
def get_path(self) -> str | None:
@@ -547,9 +553,8 @@ async def save(self, jupyter_ydoc: YBaseDoc):
547553
# JupyterLab tab for this YDoc in the frontend.
548554
jupyter_ydoc.dirty = False
549555

550-
# Calculate save duration and update adaptive poll interval
556+
# Calculate save duration
551557
save_duration = time.perf_counter() - start_time
552-
self._last_save_duration = save_duration
553558

554559
# Calculate new adaptive interval
555560
old_interval = self._adaptive_poll_interval
@@ -619,8 +624,7 @@ def restart(self) -> None:
619624
self._last_path = None
620625

621626
# Reset adaptive timing attributes
622-
self._last_save_duration = None
623-
self._adaptive_poll_interval = self.poll_interval
627+
self._adaptive_poll_interval = self.min_poll_interval
624628

625629
self.log.info(f"Restarted FileAPI for room '{self.room_id}'.")
626630

ui-tests/package.json

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,5 +11,13 @@
1111
"devDependencies": {
1212
"@jupyterlab/galata": "^5.0.5",
1313
"@playwright/test": "^1.37.0"
14+
},
15+
"resolutions": {
16+
"vega-util": "^1.17.3",
17+
"vega-dataflow": "^5.7.7",
18+
"vega-selections": "5.6.0",
19+
"vega-scale": "^7.4.2",
20+
"vega-scenegraph": "^4.13.1",
21+
"vega-time": "^2.1.3"
1422
}
1523
}

0 commit comments

Comments
 (0)