Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add Yjs plugin configuration #442

Merged
merged 1 commit into from
Oct 2, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 6 additions & 1 deletion jupyverse_api/jupyverse_api/yjs/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@

from fastapi import APIRouter, Depends, Request, Response

from jupyverse_api import Router
from jupyverse_api import Config, Router

from ..app import App
from ..auth import Auth, User
Expand Down Expand Up @@ -61,3 +61,8 @@ def get_document(
document_id: str,
):
...


class YjsConfig(Config):
document_cleanup_delay: float = 60
document_save_delay: float = 1
9 changes: 7 additions & 2 deletions plugins/yjs/fps_yjs/main.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,22 +8,27 @@
from jupyverse_api.app import App
from jupyverse_api.auth import Auth
from jupyverse_api.contents import Contents
from jupyverse_api.yjs import Yjs
from jupyverse_api.yjs import Yjs, YjsConfig

from .routes import _Yjs


class YjsComponent(Component):
def __init__(self, **kwargs):
self.yjs_config = YjsConfig(**kwargs)

@context_teardown
async def start(
self,
ctx: Context,
) -> AsyncGenerator[None, Optional[BaseException]]:
ctx.add_resource(self.yjs_config, types=YjsConfig)

app = await ctx.request_resource(App)
auth = await ctx.request_resource(Auth) # type: ignore
contents = await ctx.request_resource(Contents) # type: ignore

yjs = _Yjs(app, auth, contents)
yjs = _Yjs(app, self.yjs_config, auth, contents)
ctx.add_resource(yjs, types=Yjs)

# start indexing in the background
Expand Down
14 changes: 8 additions & 6 deletions plugins/yjs/fps_yjs/routes.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@
from jupyverse_api.app import App
from jupyverse_api.auth import Auth, User
from jupyverse_api.contents import Contents
from jupyverse_api.yjs import Yjs
from jupyverse_api.yjs import Yjs, YjsConfig
from jupyverse_api.yjs.models import CreateDocumentSession

from .ydocs import ydocs as YDOCS
Expand All @@ -44,12 +44,13 @@ class _Yjs(Yjs):
def __init__(
self,
app: App,
yjs_config: YjsConfig,
auth: Auth,
contents: Contents,
) -> None:
super().__init__(app=app, auth=auth)
self.contents = contents
self.room_manager = RoomManager(contents)
self.room_manager = RoomManager(contents, yjs_config)
if Widgets is None:
self.widgets = None
else:
Expand Down Expand Up @@ -148,8 +149,9 @@ class RoomManager:
websocket_server: JupyterWebsocketServer
lock: asyncio.Lock

def __init__(self, contents: Contents):
def __init__(self, contents: Contents, yjs_config: YjsConfig):
self.contents = contents
self.yjs_config = yjs_config
self.documents = {} # a dictionary of room_name:document
self.watchers = {} # a dictionary of file_id:task
self.savers = {} # a dictionary of file_id:task
Expand Down Expand Up @@ -314,7 +316,7 @@ async def maybe_save_document(
self, file_id: str, file_type: str, file_format: str, document: YBaseDoc
) -> None:
# save after 1 second of inactivity to prevent too frequent saving
await asyncio.sleep(1) # FIXME: pass in config
await asyncio.sleep(self.yjs_config.document_save_delay)
# if the room cannot be found, don't save
try:
file_path = await self.get_file_path(file_id, document)
Expand Down Expand Up @@ -349,12 +351,12 @@ async def maybe_save_document(
del self.savers[file_id]

async def maybe_clean_room(self, room, ws_path: str) -> None:
file_id = ws_path.split(":", 2)[2]
# keep the document for a while in case someone reconnects
await asyncio.sleep(60) # FIXME: pass in config
await asyncio.sleep(self.yjs_config.document_cleanup_delay)
document = self.documents[ws_path]
document.unobserve()
del self.documents[ws_path]
file_id = ws_path.split(":", 2)[2]
documents = [v for k, v in self.documents.items() if k.split(":", 2)[2] == file_id]
if not documents:
self.watchers[file_id].cancel()
Expand Down
Loading