Skip to content

Commit

Permalink
improve exception handling on request
Browse files Browse the repository at this point in the history
  • Loading branch information
livioribeiro committed Apr 22, 2024
1 parent cbf4c83 commit afea855
Show file tree
Hide file tree
Showing 6 changed files with 52 additions and 24 deletions.
4 changes: 3 additions & 1 deletion src/selva/ext/data/memcached/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,9 @@

async def selva_extension(container: Container, settings: Settings):
if find_spec("emcache") is None:
raise ModuleNotFoundError("Missing 'emcache'. Install 'selva' with 'memcached' extra.")
raise ModuleNotFoundError(
"Missing 'emcache'. Install 'selva' with 'memcached' extra."
)

for name in settings.data.memcached:
service_name = name if name != "default" else None
Expand Down
11 changes: 8 additions & 3 deletions src/selva/ext/data/memcached/service.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,8 @@

from selva.configuration.settings import Settings
from selva.di.container import Container
from selva.di.decorator import service as service_decorator, DI_ATTRIBUTE_SERVICE
from selva.di.decorator import DI_ATTRIBUTE_SERVICE
from selva.di.decorator import service as service_decorator

from .settings import MemcachedSettings

Expand Down Expand Up @@ -39,9 +40,13 @@ async def memcached_service(
if not di.has(cluster_events, name=name):
di.register(cluster_events)

cluster_events_service_name = getattr(cluster_events, DI_ATTRIBUTE_SERVICE).name
cluster_events_service_name = getattr(
cluster_events, DI_ATTRIBUTE_SERVICE
).name

memcached_options["cluster_events"] = await di.get(cluster_events, name=cluster_events_service_name)
memcached_options["cluster_events"] = await di.get(
cluster_events, name=cluster_events_service_name
)

else:
memcached_options = {}
Expand Down
4 changes: 3 additions & 1 deletion src/selva/ext/data/redis/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,9 @@

def selva_extension(container: Container, settings: Settings):
if find_spec("redis") is None:
raise ModuleNotFoundError("Missing 'redis'. Install 'selva' with 'redis' extra.")
raise ModuleNotFoundError(
"Missing 'redis'. Install 'selva' with 'redis' extra."
)

for name in settings.data.redis:
service_name = name if name != "default" else None
Expand Down
4 changes: 3 additions & 1 deletion src/selva/ext/data/sqlalchemy/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,9 @@

def selva_extension(container: Container, settings: Settings):
if find_spec("sqlalchemy") is None:
raise ModuleNotFoundError("Missing 'sqlalchemy'. Install 'selva' with 'sqlalchemy' extra.")
raise ModuleNotFoundError(
"Missing 'sqlalchemy'. Install 'selva' with 'sqlalchemy' extra."
)

for name in settings.data.sqlalchemy.connections:
service_name = name if name != "default" else None
Expand Down
4 changes: 3 additions & 1 deletion src/selva/ext/templates/jinja/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,9 @@

async def selva_extension(container: Container, settings: Settings):
if find_spec("jinja2") is None:
raise ModuleNotFoundError("Missing 'jinja2'. Install 'selva' with 'jinja' extra.")
raise ModuleNotFoundError(
"Missing 'jinja2'. Install 'selva' with 'jinja' extra."
)

backend = settings.templates.backend

Expand Down
49 changes: 32 additions & 17 deletions src/selva/web/application.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import functools
import inspect
import traceback
import typing
from http import HTTPStatus
from typing import Any
Expand Down Expand Up @@ -178,39 +179,53 @@ async def _handle_request(self, scope, receive, send):
if handler := await self.di.get(
ExceptionHandler[type(err)], optional=True
):
logger.trace(
logger.debug(
"Handling exception with handler {}.{}",
handler.__class__.__module__,
handler.__class__.__qualname__,
)
await handler.handle_exception(request, err)
else:
raise
except WebSocketException as err:
await request.websocket.close(err.code, err.reason)
except (WebSocketDisconnectError, WebSocketError):
logger.exception("WebSocket error")
await request.websocket.close()
except WebSocketException as err:
await request.websocket.close(err.code, err.reason)
except HTTPException as err:
if websocket := request.websocket:
logger.error("WebSocket request raise HTTPException")
logger.exception("WebSocket request raised HTTPException")
await websocket.close()
return

response = request.response

if cause := err.__cause__:
logger.exception(cause)
stack_trace = "".join(traceback.format_exception(cause))
else:
response = request.response
if response.is_started:
logger.error("Response has already started")
await response.end()
return

if response.is_finished:
logger.error("Response is finished")
return

await respond_text(response, str(err), status=err.status)
except Exception as err:
stack_trace = None

if response.is_started:
logger.error("Response has already started")
await response.end()
return

if response.is_finished:
logger.error("Response is finished")
return

if stack_trace:
await respond_text(response, stack_trace, status=err.status)
else:
await respond_status(response, status=err.status)
except Exception:
logger.exception("Error processing request")

await respond_text(
request.response, str(err), status=HTTPStatus.INTERNAL_SERVER_ERROR
request.response,
traceback.format_exc(),
status=HTTPStatus.INTERNAL_SERVER_ERROR,
)

async def _process_request(self, request: Request):
Expand Down

0 comments on commit afea855

Please sign in to comment.