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,

Reply via email to