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

Attempt to cleanup server resources on shutdown #729

Merged
merged 3 commits into from
Feb 10, 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
3 changes: 3 additions & 0 deletions lib/esbonio/esbonio/server/feature.py
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,9 @@ def initialize(self, params: types.InitializeParams):
def initialized(self, params: types.InitializedParams):
"""Called when the ``initialized`` notification is received."""

def shutdown(self, params: None):
"""Called when the server is instructed to ``shutdown`` by the client."""

def document_change(self, params: types.DidChangeTextDocumentParams):
"""Called when a text document is changed."""

Expand Down
15 changes: 15 additions & 0 deletions lib/esbonio/esbonio/server/features/preview_manager/__init__.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import asyncio
import logging
import sys
from http.server import HTTPServer
from http.server import SimpleHTTPRequestHandler
from typing import Any
Expand Down Expand Up @@ -92,6 +93,20 @@ def __init__(self, server: EsbonioLanguageServer, sphinx: SphinxManager):
self._ws_server: Optional[WebviewServer] = None
self._ws_task: Optional[asyncio.Task] = None

def shutdown(self, params: None):
"""Called when the client instructs the server to ``shutdown``."""
args = {}
if sys.version_info.minor > 8:
args["msg"] = "Server is shutting down."

if self._http_server:
self.logger.debug("Shutting down preview HTTP server")
self._http_server.shutdown()

if self._ws_task:
self.logger.debug("Shutting down preview WebSocket server")
self._ws_task.cancel(**args)

@property
def preview_active(self) -> bool:
"""Return true if the preview is active.
Expand Down
23 changes: 22 additions & 1 deletion lib/esbonio/esbonio/server/features/sphinx_manager/manager.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

import asyncio
import inspect
import sys
import typing
import uuid
from typing import Callable
Expand Down Expand Up @@ -86,6 +87,26 @@ async def document_save(self, params: lsp.DidSaveTextDocumentParams):

await self.trigger_build(uri)

async def shutdown(self, params: None):
"""Called when the server is instructed to ``shutdown``."""

# Stop creating any new clients.
if self._client_creating and not self._client_creating.done():
args = {}
if sys.version_info.minor > 8:
args["msg"] = "Server is shutting down"

self.logger.debug("Aborting client creation")
self._client_creating.cancel(**args)

# Stop any existing clients.
tasks = []
for client in self.clients.values():
self.logger.debug("Stopping SphinxClient: %s", client)
tasks.append(asyncio.create_task(client.stop()))

await asyncio.gather(*tasks)

async def trigger_build_after(self, uri: Uri, app_id: str, delay: float):
"""Trigger a build for the given uri after the given delay."""
await asyncio.sleep(delay)
Expand Down Expand Up @@ -217,7 +238,7 @@ async def start_progress(self, client: SphinxClient):
return

token = str(uuid.uuid4())
self.logger.error("Starting progress: '%s'", token)
self.logger.debug("Starting progress: '%s'", token)

try:
await self.server.progress.create_async(token)
Expand Down
3 changes: 3 additions & 0 deletions lib/esbonio/esbonio/server/server.py
Original file line number Diff line number Diff line change
Expand Up @@ -123,6 +123,9 @@ async def initialized(self, params: types.InitializedParams):
)
self._ready.set_result(True)

def lsp_shutdown(self, params: None):
"""Called when the server is instructed to ``shutdown`` by the client."""

def load_extension(self, name: str, setup: Callable):
"""Load the given setup function as an extension.

Expand Down
5 changes: 5 additions & 0 deletions lib/esbonio/esbonio/server/setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,11 @@ async def on_initialized(
await ls.initialized(params)
await call_features(ls, "initialized", params)

@server.feature(types.SHUTDOWN)
async def on_shutdown(ls: EsbonioLanguageServer, params: None):
ls.lsp_shutdown(params)
await call_features(ls, "shutdown", params)

@server.feature(types.TEXT_DOCUMENT_DID_CHANGE)
async def on_document_change(
ls: EsbonioLanguageServer, params: types.DidChangeTextDocumentParams
Expand Down
7 changes: 7 additions & 0 deletions lib/esbonio/pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,13 @@ mypy_path = "$MYPY_CONFIG_FILE_DIR"
explicit_package_bases = true
check_untyped_defs = true

[tool.pyright]
venv = ".env"
include = ["esbonio"]

pythonVersion = "3.8"
pythonPlatform = "All"

[tool.towncrier]
filename = "CHANGES.md"
directory = "changes/"
Expand Down
3 changes: 0 additions & 3 deletions lib/esbonio/pyrightconfig.json

This file was deleted.