Repository: sanic-org/sanic-ext
Pull request #228 (2023-09-14 05:41:08)

Fix late dependency registration
Fixes the issue where an early request before `after_server_start` is complete a dependency injection will fail.

Requires: https://github.com/sanic-org/sanic-routing/pull/76
Requires: https://github.com/sanic-org/sanic/pull/2822


Patch:
diff --git a/sanic_ext/config.py b/sanic_ext/config.py
index e690162..2fb99eb 100644
--- a/sanic_ext/config.py
+++ b/sanic_ext/config.py
@@ -10,6 +10,9 @@ from sanic.exceptions import SanicException
 from sanic.signals import Event
 
 
+PRIORITY = 100_000_000
+
+
 class Config(SanicConfig):
     def __init__(
         self,
@@ -37,6 +40,7 @@ class Config(SanicConfig):
         http_auto_options: bool = True,
         http_auto_trace: bool = False,
         injection_signal: Union[str, Event] = Event.HTTP_ROUTING_AFTER,
+        injection_priority: int = PRIORITY,
         injection_load_custom_constants: bool = False,
         logging: bool = False,
         logging_queue_max_size: int = 4096,
@@ -94,6 +98,7 @@ class Config(SanicConfig):
         self.HTTP_AUTO_OPTIONS = http_auto_options
         self.HTTP_AUTO_TRACE = http_auto_trace
         self.INJECTION_SIGNAL = injection_signal
+        self.INJECTION_PRIORITY = injection_priority
         self.INJECTION_LOAD_CUSTOM_CONSTANTS = injection_load_custom_constants
         self.LOGGING = logging
         self.LOGGING_QUEUE_MAX_SIZE = logging_queue_max_size
diff --git a/sanic_ext/extensions/http/methods.py b/sanic_ext/extensions/http/methods.py
index 19ffbc4..e0fbf5d 100644
--- a/sanic_ext/extensions/http/methods.py
+++ b/sanic_ext/extensions/http/methods.py
@@ -8,8 +8,9 @@ from sanic.constants import HTTPMethod
 from sanic.exceptions import SanicException
 from sanic.response import empty, raw
 
-from ...utils.route import clean_route_name
-from ..openapi import openapi
+from sanic_ext.config import PRIORITY
+from sanic_ext.extensions.openapi import openapi
+from sanic_ext.utils.route import clean_route_name
 
 
 def add_http_methods(
@@ -66,7 +67,7 @@ def add_auto_handlers(
         )
         return raw(message, content_type="message/http")
 
-    @app.before_server_start
+    @app.before_server_start(priority=PRIORITY + 1)
     def _add_handlers(app, _):
         nonlocal auto_head
         nonlocal auto_options
diff --git a/sanic_ext/extensions/injection/injector.py b/sanic_ext/extensions/injection/injector.py
index 1cc8112..24ce171 100644
--- a/sanic_ext/extensions/injection/injector.py
+++ b/sanic_ext/extensions/injection/injector.py
@@ -7,6 +7,7 @@ from typing import Any, Callable, Dict, Optional, Tuple, Type, get_type_hints
 from sanic import Sanic
 from sanic.constants import HTTP_METHODS
 
+from sanic_ext.config import PRIORITY
 from sanic_ext.extensions.injection.constructor import gather_args
 
 from .registry import ConstantRegistry, InjectionRegistry, SignatureRegistry
@@ -21,7 +22,7 @@ def add_injection(
         app, injection_registry, constant_registry
     )
 
-    @app.after_server_start
+    @app.listener("before_server_start", priority=PRIORITY)
     async def finalize_injections(app: Sanic, _):
         router_converters = set(
             allowed[0] for allowed in app.router.regex_types.values()
@@ -37,8 +38,9 @@ def add_injection(
         injection_registry.finalize(app, constant_registry, router_types)
 
     injection_signal = app.ext.config.INJECTION_SIGNAL
+    injection_priority = app.ext.config.INJECTION_PRIORITY
 
-    @app.signal(injection_signal)
+    @app.signal(injection_signal, priority=injection_priority)
     async def inject_kwargs(request, **_):
         nonlocal signature_registry
 
@@ -72,7 +74,7 @@ def _setup_signature_registry(
 ) -> SignatureRegistry:
     registry = SignatureRegistry()
 
-    @app.after_server_start
+    @app.listener("before_server_start", priority=PRIORITY)
     async def setup_signatures(app, _):
         nonlocal registry
 


Test patch:
diff --git a/tests/extensions/injection/test_injection_config.py b/tests/extensions/injection/test_injection_config.py
index 526a6e9..2c3385b 100644
--- a/tests/extensions/injection/test_injection_config.py
+++ b/tests/extensions/injection/test_injection_config.py
@@ -35,6 +35,7 @@ def test_add_injection_uses_signal_config():
 
     app.signal = Mock(return_value=Mock())
     app.ext.config.INJECTION_SIGNAL = "random_string"
+    app.ext.config.INJECTION_PRIORITY = 99999
     add_injection(app, Mock(), Mock())
 
-    app.signal.assert_called_once_with("random_string")
+    app.signal.assert_called_once_with("random_string", priority=99999)