Skip to content

Commit 7a33b92

Browse files
authored
Merge pull request #156 from Glimpse-Analytics/fix/session-management-cleanup
Fix unclosed aiohttp client session warnings in session management
2 parents e7bcbee + e15356c commit 7a33b92

File tree

3 files changed

+46
-5
lines changed

3 files changed

+46
-5
lines changed

findmy/reports/account.py

Lines changed: 16 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -375,6 +375,7 @@ def __init__(
375375

376376
self._http: HttpSession = HttpSession()
377377
self._reports: LocationReportsFetcher = LocationReportsFetcher(self)
378+
self._closed: bool = False
378379

379380
def _set_login_state(
380381
self,
@@ -473,8 +474,21 @@ async def close(self) -> None:
473474
474475
Should be called when the object will no longer be used.
475476
"""
476-
await self._anisette.close()
477-
await self._http.close()
477+
if self._closed:
478+
return # Already closed, make it idempotent
479+
480+
self._closed = True
481+
482+
# Close in proper order: anisette first, then HTTP session
483+
try:
484+
await self._anisette.close()
485+
except (RuntimeError, OSError, ConnectionError) as e:
486+
logger.warning("Error closing anisette provider: %s", e)
487+
488+
try:
489+
await self._http.close()
490+
except (RuntimeError, OSError, ConnectionError) as e:
491+
logger.warning("Error closing HTTP session: %s", e)
478492

479493
@require_login_state(LoginState.LOGGED_OUT)
480494
@override

findmy/reports/anisette.py

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -171,6 +171,7 @@ def __init__(self, server_url: str) -> None:
171171

172172
self._anisette_data: dict[str, str] | None = None
173173
self._anisette_data_expires_at: float = 0
174+
self._closed = False
174175

175176
@override
176177
def serialize(self) -> dict:
@@ -217,6 +218,10 @@ async def get_headers(
217218
with_client_info: bool = False,
218219
) -> dict[str, str]:
219220
"""See `BaseAnisetteProvider.get_headers`_."""
221+
if self._closed:
222+
msg = "RemoteAnisetteProvider has been closed and cannot be used"
223+
raise RuntimeError(msg)
224+
220225
if self._anisette_data is None or time.time() >= self._anisette_data_expires_at:
221226
logger.info("Fetching anisette data from %s", self._server_url)
222227

@@ -229,7 +234,15 @@ async def get_headers(
229234
@override
230235
async def close(self) -> None:
231236
"""See `AnisetteProvider.close`."""
232-
await self._http.close()
237+
if self._closed:
238+
return # Already closed, make it idempotent
239+
240+
self._closed = True
241+
242+
try:
243+
await self._http.close()
244+
except (RuntimeError, OSError, ConnectionError) as e:
245+
logger.warning("Error closing anisette HTTP session: %s", e)
233246

234247

235248
class LocalAnisetteProvider(BaseAnisetteProvider):

findmy/util/http.py

Lines changed: 16 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -75,8 +75,13 @@ def __init__(self) -> None: # noqa: D107
7575
super().__init__()
7676

7777
self._session: ClientSession | None = None
78+
self._closed: bool = False
7879

7980
async def _get_session(self) -> ClientSession:
81+
if self._closed:
82+
msg = "HttpSession has been closed and cannot be used"
83+
raise RuntimeError(msg)
84+
8085
if self._session is not None:
8186
return self._session
8287

@@ -87,10 +92,19 @@ async def _get_session(self) -> ClientSession:
8792
@override
8893
async def close(self) -> None:
8994
"""Close the underlying session. Should be called when session will no longer be used."""
95+
if self._closed:
96+
return # Already closed, make it idempotent
97+
98+
self._closed = True
99+
90100
if self._session is not None:
91101
logger.debug("Closing aiohttp session")
92-
await self._session.close()
93-
self._session = None
102+
try:
103+
await self._session.close()
104+
except (RuntimeError, OSError, ConnectionError) as e:
105+
logger.warning("Error closing aiohttp session: %s", e)
106+
finally:
107+
self._session = None
94108

95109
async def request(
96110
self,

0 commit comments

Comments
 (0)