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

Backport PR #108 on branch 0.8.x (Creates document session) #113

Merged
merged 5 commits into from
Mar 5, 2023
Merged
Show file tree
Hide file tree
Changes from 3 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
2 changes: 1 addition & 1 deletion .pre-commit-config.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ repos:
args: ["--line-length", "100"]

- repo: https://github.com/PyCQA/isort
rev: 5.11.4
rev: 5.12.0
hooks:
- id: isort
files: \.py$
Expand Down
2 changes: 1 addition & 1 deletion jupyter_server_ydoc/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

from .app import YDocExtension

__version__ = "0.6.1"
__version__ = "0.6.2"
fcollonval marked this conversation as resolved.
Show resolved Hide resolved


def _jupyter_server_extension_points() -> List[Dict[str, Any]]:
Expand Down
11 changes: 10 additions & 1 deletion jupyter_server_ydoc/app.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,12 @@
from traitlets import Float, Int, Type
from ypy_websocket.ystore import BaseYStore # type: ignore

from .handlers import SQLiteYStore, YDocRoomIdHandler, YDocWebSocketHandler
from .handlers import (
DocSessionHandler,
SQLiteYStore,
YDocRoomIdHandler,
YDocWebSocketHandler,
)


class YDocExtension(ExtensionApp):
Expand Down Expand Up @@ -62,7 +67,11 @@ def initialize_settings(self):
def initialize_handlers(self):
self.handlers.extend(
[
# Deprecated - to remove for 1.0.0
(r"/api/yjs/roomid/(.*)", YDocRoomIdHandler),
# Deprecated - to remove for 1.0.0
(r"/api/yjs/session/(.*)", DocSessionHandler),
# Deprecated - to remove for 1.0.0
(r"/api/yjs/(.*)", YDocWebSocketHandler),
fcollonval marked this conversation as resolved.
Show resolved Hide resolved
]
)
45 changes: 45 additions & 0 deletions jupyter_server_ydoc/handlers.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@

import asyncio
import json
import uuid
from logging import Logger
from pathlib import Path
from typing import Any, Dict, Optional, Tuple
Expand All @@ -24,6 +25,8 @@

YFILE = YDOCS["file"]

SERVER_SESSION = str(uuid.uuid4())


class TempFileYStore(_TempFileYStore):
prefix_dir = "jupyter_ystore_"
Expand Down Expand Up @@ -195,6 +198,11 @@ async def open(self, path):
self.saving_document = None
asyncio.create_task(self.websocket_server.serve(self))

# Close the connection if the document session expired
session_id = self.get_query_argument("sessionId", "")
if isinstance(self.room, DocumentRoom) and SERVER_SESSION != session_id:
self.close(1003, f"Document session {session_id} expired")

# cancel the deletion of the room if it was scheduled
if isinstance(self.room, DocumentRoom) and self.room.cleaner is not None:
self.room.cleaner.cancel()
Expand All @@ -221,6 +229,7 @@ async def open(self, path):
# if YStore updates and source file are out-of-sync, resync updates with source
if self.room.document.source != model["content"]:
read_from_source = True

if read_from_source:
self.room.document.source = model["content"]
if self.room.ystore:
Expand Down Expand Up @@ -405,3 +414,39 @@ async def put(self, path):
ws_url += str(idx)
self.log.info("Request for Y document '%s' with room ID: %s", path, ws_url)
return self.finish(ws_url)


class DocSessionHandler(APIHandler):
auth_resource = "contents"

@web.authenticated
@authorized
async def put(self, path):
body = json.loads(self.request.body)
format = body["format"]
content_type = body["type"]
file_id_manager = self.settings["file_id_manager"]

idx = file_id_manager.get_id(path)
if idx is not None:
# index already exists
self.log.info("Request for Y document '%s' with room ID: %s", path, idx)
data = json.dumps(
{"format": format, "type": content_type, "fileId": idx, "sessionId": SERVER_SESSION}
)
self.set_status(200)
return self.finish(data)

# try indexing
idx = file_id_manager.index(path)
if idx is None:
# file does not exists
raise web.HTTPError(404, f"File {path!r} does not exist")

# index successfully created
self.log.info("Request for Y document '%s' with room ID: %s", path, idx)
data = json.dumps(
{"format": format, "type": content_type, "fileId": idx, "sessionId": SERVER_SESSION}
)
self.set_status(201)
return self.finish(data)