Skip to content

Commit

Permalink
Backport PR #108 on branch 0.8.x (Creates document session) (#113)
Browse files Browse the repository at this point in the history
* Creates document session (#108)

* Creates document session

* Uses translator

* Update jupyter_collaboration/handlers.py

* Create a new endpoint for document sessions, changes tranlator property and deprecates old endpoints

---------

Co-authored-by: David Brochart <[email protected]>

* Deprecate endpoints

* Fixes version, pre-commit, and runs pre-commit

* Apply suggestions from code review

* Update jupyter_server_ydoc/__init__.py

---------

Co-authored-by: David Brochart <[email protected]>
Co-authored-by: Frédéric Collonval <[email protected]>
  • Loading branch information
3 people authored Mar 5, 2023
1 parent c42c27e commit a1c2411
Show file tree
Hide file tree
Showing 4 changed files with 57 additions and 3 deletions.
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.7.0"


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),
]
)
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)

0 comments on commit a1c2411

Please sign in to comment.