fix: always close services (to avoid mem leaks)

This commit is contained in:
Chetan Sarva
2026-01-30 10:03:44 -05:00
parent 663950eeaf
commit 37d1256efc
3 changed files with 128 additions and 115 deletions

View File

@@ -784,6 +784,9 @@ def get_user_info(credentials: Credentials) -> Optional[Dict[str, Any]]:
except Exception as e: except Exception as e:
logger.error(f"Unexpected error fetching user info: {e}") logger.error(f"Unexpected error fetching user info: {e}")
return None return None
finally:
if service:
service.close()
# --- Centralized Google Service Authentication --- # --- Centralized Google Service Authentication ---

View File

@@ -4,6 +4,7 @@ import logging
import re import re
from functools import wraps from functools import wraps
from typing import Dict, List, Optional, Any, Callable, Union, Tuple from typing import Dict, List, Optional, Any, Callable, Union, Tuple
from contextlib import ExitStack
from google.auth.exceptions import RefreshError from google.auth.exceptions import RefreshError
from googleapiclient.discovery import build from googleapiclient.discovery import build
@@ -681,6 +682,9 @@ def require_google_service(
e, actual_user_email, service_name e, actual_user_email, service_name
) )
raise GoogleAuthenticationError(error_message) raise GoogleAuthenticationError(error_message)
finally:
if service:
service.close()
# Set the wrapper's signature to the one without 'service' # Set the wrapper's signature to the one without 'service'
wrapper.__signature__ = wrapper_sig wrapper.__signature__ = wrapper_sig
@@ -751,6 +755,7 @@ def require_multiple_services(service_configs: List[Dict[str, Any]]):
) )
# Authenticate all services # Authenticate all services
with ExitStack() as stack:
for config in service_configs: for config in service_configs:
service_type = config["service_type"] service_type = config["service_type"]
scopes = config["scopes"] scopes = config["scopes"]
@@ -798,6 +803,7 @@ def require_multiple_services(service_configs: List[Dict[str, Any]]):
# Inject service with specified parameter name # Inject service with specified parameter name
kwargs[param_name] = service kwargs[param_name] = service
stack.callback(service.close)
except GoogleAuthenticationError as e: except GoogleAuthenticationError as e:
logger.error( logger.error(

View File

@@ -670,6 +670,7 @@ async def create_event(
# Accept both file URLs and file IDs. If a URL, extract the fileId. # Accept both file URLs and file IDs. If a URL, extract the fileId.
event_body["attachments"] = [] event_body["attachments"] = []
drive_service = None drive_service = None
try:
try: try:
drive_service = service._http and build("drive", "v3", http=service._http) drive_service = service._http and build("drive", "v3", http=service._http)
except Exception as e: except Exception as e:
@@ -726,6 +727,9 @@ async def create_event(
"mimeType": mime_type, "mimeType": mime_type,
} }
) )
finally:
if drive_service:
drive_service.close()
created_event = await asyncio.to_thread( created_event = await asyncio.to_thread(
lambda: service.events() lambda: service.events()
.insert( .insert(