You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@airflow.apache.org by ur...@apache.org on 2023/03/10 07:24:06 UTC

[airflow] branch main updated: Use custom Connexion resolver to load lazily (#29992)

This is an automated email from the ASF dual-hosted git repository.

uranusjr pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/airflow.git


The following commit(s) were added to refs/heads/main by this push:
     new 7d6afc5857 Use custom Connexion resolver to load lazily (#29992)
7d6afc5857 is described below

commit 7d6afc5857540023a85fb05600c6ce8329492c53
Author: Tzu-ping Chung <ur...@gmail.com>
AuthorDate: Fri Mar 10 15:23:56 2023 +0800

    Use custom Connexion resolver to load lazily (#29992)
---
 airflow/www/extensions/init_views.py | 35 ++++++++++++++++++++++++++++++++++-
 1 file changed, 34 insertions(+), 1 deletion(-)

diff --git a/airflow/www/extensions/init_views.py b/airflow/www/extensions/init_views.py
index 7d32f26959..41408942e4 100644
--- a/airflow/www/extensions/init_views.py
+++ b/airflow/www/extensions/init_views.py
@@ -20,10 +20,11 @@ import logging
 import warnings
 from os import path
 
-from connexion import FlaskApi, ProblemException
+from connexion import FlaskApi, ProblemException, Resolver
 from flask import Flask, request
 
 from airflow.api_connexion.exceptions import common_error_handler
+from airflow.compat.functools import cached_property
 from airflow.configuration import conf
 from airflow.exceptions import RemovedInAirflow3Warning
 from airflow.security import permissions
@@ -177,6 +178,37 @@ def set_cors_headers_on_response(response):
     return response
 
 
+class _LazyResolution:
+    """OpenAPI endpoint that lazily resolves the function on first use.
+
+    This is a stand-in replacement for ``connexion.Resolution`` that implements
+    its public attributes ``function`` and ``operation_id``, but the function
+    is only resolved when it is first accessed.
+    """
+
+    def __init__(self, resolve_func, operation_id):
+        self._resolve_func = resolve_func
+        self.operation_id = operation_id
+
+    @cached_property
+    def function(self):
+        return self._resolve_func(self.operation_id)
+
+
+class _LazyResolver(Resolver):
+    """OpenAPI endpoint resolver that loads lazily on first use.
+
+    This re-implements ``connexion.Resolver.resolve()`` to not eagerly resolve
+    the endpoint function (and thus avoid importing it in the process), but only
+    return a placeholder that will be actually resolved when the contained
+    function is accessed.
+    """
+
+    def resolve(self, operation):
+        operation_id = self.resolve_operation_id(operation)
+        return _LazyResolution(self.resolve_function_from_operation_id, operation_id)
+
+
 def init_api_connexion(app: Flask) -> None:
     """Initialize Stable API"""
     base_path = "/api/v1"
@@ -205,6 +237,7 @@ def init_api_connexion(app: Flask) -> None:
         specification = safe_load(f)
     api_bp = FlaskApi(
         specification=specification,
+        resolver=_LazyResolver(),
         base_path=base_path,
         options={
             "swagger_ui": conf.getboolean("webserver", "enable_swagger_ui", fallback=True),