Rework how services are started/stopped #24
Merged
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Description
pycrdt-websocket
provides these 4 services:WebsocketServer
: a WebSocket server.WebsocketProvider
: a WebSocker provider (a client to aWebsocketServer
).YStore
: a store for persisting Y updates.YRoom
: a room where clients collaborate on a Y document.These services are asynchronous, and have to be started (for initialization) and stopped (for teardown). For instance, initialization could include connecting to a database, and teardown could disconnect from the database.
They provide 2 common APIs to be started and stopped:
start()
andstop()
async methods.The async context manager API looks like this:
And the start/stop API looks like this (using AnyIO):
In an environment where it is not possible to use AnyIO task groups, once can use
asyncio
like this:While it is advised to use the async context manager API, it is not always possible to do so, hence the manual start/stop methods.
Improvements
The way services are started and stopped now uses an
anyio.Lock
, instead of a boolean attribute_starting
, to handle concurrent calls. Also,__aenter__()
callsstart()
under the hood, and__aexit__()
callsstop()
, instead of copying code. This ensures that both ways are equivalent. Thestart()
method is passed a parameterfrom_context_manager=True
if called from__aenter__()
, in order to not create a new task group, since it was already created in__aenter__()
.Tests have also been reworked, so that both APIs (context manager and start/stop methods) of every service are tested. Also, since #22 both
asyncio
andtrio
backends are tested.Breaking changes
This PR has the following breaking changes:
stop()
methods are now async. It didn't make a lot of sense to havestart()
async and notstop()
, and teardown could have async logic in general.WebsocketServer.delete_room()
is now async, since it may stop a room, and stopping a room is async.