This is an automated email from the ASF dual-hosted git repository. lahirujayathilake pushed a commit to branch main in repository https://gitbox.apache.org/repos/asf/airavata-portals.git
commit 3738cb417e2826ce74dad1863426549c9e300123 Author: lahiruj <[email protected]> AuthorDate: Thu Jul 24 16:46:28 2025 -0400 Replace buggy Thrift pool with custom implementation The thrift_connector library was causing a critical deserialization bug with Thrift enums after the upgrade to Thrift 0.22.0. --- .../django_airavata/middleware.py | 13 ++--- airavata-django-portal/django_airavata/utils.py | 57 ++++++++++++++++++++-- 2 files changed, 58 insertions(+), 12 deletions(-) diff --git a/airavata-django-portal/django_airavata/middleware.py b/airavata-django-portal/django_airavata/middleware.py index 8670839ac..a20460f97 100644 --- a/airavata-django-portal/django_airavata/middleware.py +++ b/airavata-django-portal/django_airavata/middleware.py @@ -1,4 +1,3 @@ - import logging import thrift @@ -9,21 +8,19 @@ from . import utils logger = logging.getLogger(__name__) -# TODO: use the pooled clients in the airavata-python-sdk directly instead of -# these request attributes class AiravataClientMiddleware: def __init__(self, get_response): self.get_response = get_response def __call__(self, request): - request.airavata_client = utils.airavata_api_client_pool - response = self.get_response(request) + with utils.airavata_api_client_pool.connection() as airavata_client: + request.airavata_client = airavata_client + response = self.get_response(request) return response def process_exception(self, request, exception): - if isinstance(exception, - thrift.transport.TTransport.TTransportException): + if isinstance(exception, thrift.transport.TTransport.TTransportException): return render( request, 'django_airavata/error_page.html', @@ -42,8 +39,8 @@ def profile_service_client(get_response): request.profile_service['group_manager'].getGroup( request.authz_token, groupId) """ - def middleware(request): + def middleware(request): request.profile_service = { 'group_manager': utils.group_manager_client_pool, 'iam_admin': utils.iamadmin_client_pool, diff --git a/airavata-django-portal/django_airavata/utils.py b/airavata-django-portal/django_airavata/utils.py index 343cea952..49edc8f29 100644 --- a/airavata-django-portal/django_airavata/utils.py +++ b/airavata-django-portal/django_airavata/utils.py @@ -1,5 +1,6 @@ import logging import ssl +import queue from django.conf import settings from contextlib import contextmanager @@ -173,6 +174,56 @@ def get_thrift_client(host, port, is_secure, client_generator): raise ThriftConnectionException(msg) from e +@contextmanager +def simple_thrift_connection(pool): + """Context manager for borrowing a connection from the pool.""" + conn = pool.get_connection() + try: + yield conn['client'] + finally: + pool.return_connection(conn) + + +class SimpleThriftPool: + """ + A thread-safe Thrift connection pool that uses raw Thrift and the TBufferedTransport. + """ + + def __init__(self, service, host, port, size=5): + self._service = service + self._host = host + self._port = port + self._size = size + self._pool = queue.Queue(maxsize=size) + self._initialize_pool() + + def _initialize_pool(self): + for _ in range(self._size): + self._pool.put(self._create_connection()) + + def _create_connection(self): + transport = TSocket.TSocket(host=self._host, port=self._port) + transport = TTransport.TBufferedTransport(transport) + protocol = TBinaryProtocol.TBinaryProtocol(transport) + client = self._service.Client(protocol) + transport.open() + return {'client': client, 'transport': transport} + + def get_connection(self): + return self._pool.get() + + def return_connection(self, conn): + try: + if conn['transport'].isOpen(): + conn['transport'].close() + except Exception: + pass + self._pool.put(self._create_connection()) + + def connection(self): + return simple_thrift_connection(self) + + class CustomThriftClient(connection_pool.ThriftClient): secure = False validate = False @@ -240,12 +291,10 @@ class UserProfileServiceThriftClient(MultiplexThriftClientMixin, secure = settings.PROFILE_SERVICE_SECURE -airavata_api_client_pool = connection_pool.ClientPool( +airavata_api_client_pool = SimpleThriftPool( Airavata, settings.AIRAVATA_API_HOST, - settings.AIRAVATA_API_PORT, - connection_class=AiravataAPIThriftClient, - keepalive=settings.THRIFT_CLIENT_POOL_KEEPALIVE + settings.AIRAVATA_API_PORT ) group_manager_client_pool = connection_pool.ClientPool( GroupManagerService,
