Skip to content

Commit

Permalink
Add fork title and description
Browse files Browse the repository at this point in the history
  • Loading branch information
davidbrochart committed Oct 30, 2024
1 parent 0827663 commit 849b70c
Show file tree
Hide file tree
Showing 4 changed files with 90 additions and 34 deletions.
32 changes: 27 additions & 5 deletions projects/jupyter-server-ydoc/jupyter_server_ydoc/events/fork.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -7,19 +7,41 @@ description: |
Fork events emitted from server-side during a collaborative session.
type: object
required:
- root_roomid
- fork_roomid
- fork_info
- username
- action
properties:
root_roomid:
type: string
description: |
Root room ID. Usually composed by the file type, format and ID.
fork_roomid:
type: string
description: |
Fork root room ID.
fork_info:
type: object
description: |
Fork root room information.
required:
- root_roomid
- synchronize
- title
- description
properties:
root_roomid:
type: string
description: |
Root room ID. Usually composed by the file type, format and ID.
synchronize:
type: boolean
description: |
Whether the fork is kept in sync with the root.
title:
type: string
description: |
The title of the fork.
description:
type: string
description: |
The description of the fork.
username:
type: string
description: |
Expand Down
36 changes: 21 additions & 15 deletions projects/jupyter-server-ydoc/jupyter_server_ydoc/handlers.py
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@

SERVER_SESSION = str(uuid.uuid4())
FORK_DOCUMENTS = {}
FORK_ROOMS: dict[str, str] = {}
FORK_ROOMS: dict[str, dict[str, str]] = {}


class YDocWebSocketHandler(WebSocketHandler, JupyterHandler):
Expand Down Expand Up @@ -624,15 +624,13 @@ def initialize(
@authorized
async def get(self, root_roomid):
"""
Returns a dictionary of given root room ID to the root's fork room IDs.
Returns a dictionary of fork room ID to fork room information for the given root room ID.
"""
self.write(
{
root_roomid: [
fork_roomid
for fork_roomid, _root_roomid in FORK_ROOMS.items()
if _root_roomid == root_roomid
]
fork_roomid: fork_info
for fork_roomid, fork_info in FORK_ROOMS.items()
if fork_info["root_roomid"] == root_roomid
}
)

Expand All @@ -644,22 +642,29 @@ async def put(self, root_roomid):
Optionally keeps the fork in sync with the root.
"""
fork_roomid = uuid4().hex
FORK_ROOMS[fork_roomid] = root_roomid
root_room = await self._websocket_server.get_room(root_roomid)
update = root_room.ydoc.get_update()
fork_ydoc = Doc()
fork_ydoc.apply_update(update)
model = self.get_json_body()
if model.get("sync"):
synchronize = model.get("synchronize", False)
if synchronize:
root_room.ydoc.observe(lambda event: fork_ydoc.apply_update(event.update))
FORK_ROOMS[fork_roomid] = fork_info = {
"root_roomid": root_roomid,
"synchronize": synchronize,
"title": model.get("title", ""),
"description": model.get("description", "")
}
fork_room = YRoom(ydoc=fork_ydoc)
self._websocket_server.rooms[fork_roomid] = fork_room
await self._websocket_server.start_room(fork_room)
self._emit_fork_event(self.current_user.username, root_roomid, fork_roomid, "create")
self._emit_fork_event(self.current_user.username, fork_roomid, fork_info, "create")
data = json.dumps(
{
"sessionId": SERVER_SESSION,
"roomId": fork_roomid,
"fork_roomid": fork_roomid,
"fork_info": fork_info,
}
)
self.set_status(201)
Expand All @@ -671,7 +676,8 @@ async def delete(self, fork_roomid):
"""
Deletes a forked document, and optionally merges it back in the root document.
"""
root_roomid = FORK_ROOMS[fork_roomid]
fork_info = FORK_ROOMS[fork_roomid]
root_roomid = fork_info["root_roomid"]
del FORK_ROOMS[fork_roomid]
if self.get_query_argument("merge") == "true":
root_room = await self._websocket_server.get_room(root_roomid)
Expand All @@ -681,16 +687,16 @@ async def delete(self, fork_roomid):
fork_update = fork_ydoc.get_update()
root_ydoc.apply_update(fork_update)
await self._websocket_server.delete_room(name=fork_roomid)
self._emit_fork_event(self.current_user.username, root_roomid, fork_roomid, "delete")
self._emit_fork_event(self.current_user.username, fork_roomid, fork_info, "delete")
self.set_status(200)

def _emit_fork_event(
self, username: str, root_roomid: str, fork_roomid: str, action: str
self, username: str, fork_roomid: str, fork_info: dict[str, str], action: str
) -> None:
data = {
"username": username,
"root_roomid": root_roomid,
"fork_roomid": fork_roomid,
"fork_info": fork_info,
"action": action,
}
self.event_logger.emit(schema_id=JUPYTER_COLLABORATION_FORK_EVENTS_URI, data=data)
15 changes: 13 additions & 2 deletions projects/jupyter-server-ydoc/jupyter_server_ydoc/pytest_plugin.py
Original file line number Diff line number Diff line change
Expand Up @@ -169,12 +169,23 @@ async def _inner(root_roomid: str) -> Any:

@pytest.fixture
def rtc_create_fork_client(jp_fetch):
async def _inner(root_roomid: str, sync: bool) -> Any:
async def _inner(
root_roomid: str,
synchronize: bool,
title: str | None = None,
description: str | None = None,
) -> Any:
return await jp_fetch(
"/api/collaboration/fork",
root_roomid,
method="PUT",
body=json.dumps({"sync": sync}),
body=json.dumps(
{
"synchronize": synchronize,
"title": title,
"description": description,
}
),
)

return _inner
Expand Down
41 changes: 29 additions & 12 deletions tests/test_handlers.py
Original file line number Diff line number Diff line change
Expand Up @@ -261,36 +261,53 @@ def _on_root_change(topic: str, event: Any) -> None:
):
await root_connect_event.wait()

resp = await rtc_create_fork_client(root_roomid, False)
resp = await rtc_create_fork_client(root_roomid, False, "my fork0", "is awesome0")
data = json.loads(resp.body.decode("utf-8"))
fork_roomid0 = data["roomId"]
fork_roomid0 = data["fork_roomid"]

resp = await rtc_get_forks_client(root_roomid)
data = json.loads(resp.body.decode("utf-8"))
assert data == {root_roomid: [fork_roomid0]}
expected_data0 = {
fork_roomid0: {
"root_roomid": root_roomid,
"synchronize": False,
"title": "my fork0",
"description": "is awesome0",
}
}
assert data == expected_data0

assert collected_data == [
{
"username": IsStr(),
"root_roomid": root_roomid,
"fork_roomid": fork_roomid0,
"fork_info": expected_data0[fork_roomid0],
"action": "create",
}
]

resp = await rtc_create_fork_client(root_roomid, True)
resp = await rtc_create_fork_client(root_roomid, True, "my fork1", "is awesome1")
data = json.loads(resp.body.decode("utf-8"))
fork_roomid1 = data["roomId"]
fork_roomid1 = data["fork_roomid"]

resp = await rtc_get_forks_client(root_roomid)
data = json.loads(resp.body.decode("utf-8"))
assert data == {root_roomid: [fork_roomid0, fork_roomid1]}
expected_data1 = {
fork_roomid1: {
"root_roomid": root_roomid,
"synchronize": True,
"title": "my fork1",
"description": "is awesome1",
}
}
expected_data = dict(**expected_data0, **expected_data1)
assert data == expected_data

assert len(collected_data) == 2
assert collected_data[1] == {
"username": IsStr(),
"root_roomid": root_roomid,
"fork_roomid": fork_roomid1,
"fork_info": expected_data[fork_roomid1],
"action": "create",
}

Expand Down Expand Up @@ -322,12 +339,12 @@ def _on_fork_change(topic: str, event: Any) -> None:
assert str(root_text) == "Hello, World!"
resp = await rtc_get_forks_client(root_roomid)
data = json.loads(resp.body.decode("utf-8"))
assert data == {root_roomid: [fork_roomid1]}
assert data == expected_data1
assert len(collected_data) == 3
assert collected_data[2] == {
"username": IsStr(),
"root_roomid": root_roomid,
"fork_roomid": fork_roomid0,
"fork_info": expected_data[fork_roomid0],
"action": "delete",
}

Expand All @@ -336,11 +353,11 @@ def _on_fork_change(topic: str, event: Any) -> None:
assert str(root_text) == "Hello, World! Hi!"
resp = await rtc_get_forks_client(root_roomid)
data = json.loads(resp.body.decode("utf-8"))
assert data == {root_roomid: []}
assert data == {}
assert len(collected_data) == 4
assert collected_data[3] == {
"username": IsStr(),
"root_roomid": root_roomid,
"fork_roomid": fork_roomid1,
"fork_info": expected_data[fork_roomid1],
"action": "delete",
}

0 comments on commit 849b70c

Please sign in to comment.