@@ -92,6 +92,12 @@ def _resolve_event_type(payload: "dict[str, Any]", metadata: "dict[str, Any] | N
9292
9393
9494_POSTGRES_ADAPTERS = frozenset ({"asyncpg" , "psycopg" , "psqlpy" })
95+ _EVENT_BACKENDS = frozenset ({"notify" , "notify_queue" , "poll_queue" , "aq" , "txeventq" })
96+ _RETIRED_EVENT_BACKENDS = {
97+ "listen_notify" : "notify" ,
98+ "listen_notify_durable" : "notify_queue" ,
99+ "table_queue" : "poll_queue" ,
100+ }
95101
96102
97103def _get_default_backend (adapter_name : "str | None" ) -> str :
@@ -101,6 +107,26 @@ def _get_default_backend(adapter_name: "str | None") -> str:
101107 return "poll_queue"
102108
103109
110+ def _resolve_backend_name (config : Any , extension_settings : "dict[str, Any]" , adapter_name : "str | None" ) -> str :
111+ """Resolve and validate event backend configuration."""
112+ backend_name = extension_settings .get ("backend" )
113+ if backend_name is None :
114+ driver_features = getattr (config , "driver_features" , {})
115+ if isinstance (driver_features , dict ):
116+ backend_name = driver_features .get ("events_backend" )
117+ if backend_name is None :
118+ return _get_default_backend (adapter_name )
119+ if backend_name in _RETIRED_EVENT_BACKENDS :
120+ replacement = _RETIRED_EVENT_BACKENDS [backend_name ]
121+ msg = f"Event backend { backend_name !r} was removed; use { replacement !r} "
122+ raise ImproperConfigurationError (msg )
123+ if backend_name not in _EVENT_BACKENDS :
124+ valid = ", " .join (sorted (_EVENT_BACKENDS ))
125+ msg = f"Unknown event backend { backend_name !r} ; expected one of: { valid } "
126+ raise ImproperConfigurationError (msg )
127+ return cast ("str" , backend_name )
128+
129+
104130def load_native_backend (
105131 config : Any , backend_name : str | None , extension_settings : "dict[str, Any]" , adapter_name : "str | None" = None
106132) -> Any | None :
@@ -363,7 +389,7 @@ def __init__(self, config: "SyncDatabaseConfig[Any, Any, Any]") -> None:
363389 hints = get_runtime_hints (self ._adapter_name , config )
364390 self ._poll_interval_default = float (extension_settings .get ("poll_interval" ) or hints .poll_interval )
365391 queue_backend = build_queue_backend (config , extension_settings , adapter_name = self ._adapter_name , hints = hints )
366- backend_name = extension_settings . get ( "backend" ) or _get_default_backend ( self ._adapter_name )
392+ backend_name = _resolve_backend_name ( config , extension_settings , self ._adapter_name )
367393 native_backend = load_native_backend (config , backend_name , extension_settings , adapter_name = self ._adapter_name )
368394 if native_backend is None :
369395 if backend_name not in {None , "poll_queue" }:
@@ -591,7 +617,7 @@ def __init__(self, config: "AsyncDatabaseConfig[Any, Any, Any]") -> None:
591617 hints = get_runtime_hints (self ._adapter_name , config )
592618 self ._poll_interval_default = float (extension_settings .get ("poll_interval" ) or hints .poll_interval )
593619 queue_backend = build_queue_backend (config , extension_settings , adapter_name = self ._adapter_name , hints = hints )
594- backend_name = extension_settings . get ( "backend" ) or _get_default_backend ( self ._adapter_name )
620+ backend_name = _resolve_backend_name ( config , extension_settings , self ._adapter_name )
595621 native_backend = load_native_backend (config , backend_name , extension_settings , adapter_name = self ._adapter_name )
596622 if native_backend is None :
597623 if backend_name not in {None , "poll_queue" }:
0 commit comments