Skip to content

Commit d063763

Browse files
committed
fix: ensure main client closes even if child close fails, add moderation test
Wrap child client closing in try/finally so super().aclose() always runs. Use child.aclose() instead of child.client.aclose() to keep close semantics encapsulated. Add test for moderation client closure.
1 parent 74fde39 commit d063763

2 files changed

Lines changed: 15 additions & 5 deletions

File tree

getstream/stream.py

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -209,11 +209,13 @@ def moderation(self) -> AsyncModerationClient:
209209

210210
async def aclose(self):
211211
"""Close all child clients and the main HTTPX client."""
212-
for attr in ("video", "chat", "moderation"):
213-
child = self.__dict__.get(attr)
214-
if child is not None and hasattr(child, "client"):
215-
await child.client.aclose()
216-
await super().aclose()
212+
try:
213+
for attr in ("video", "chat", "moderation"):
214+
child = self.__dict__.get(attr)
215+
if child is not None and hasattr(child, "aclose"):
216+
await child.aclose()
217+
finally:
218+
await super().aclose()
217219

218220
@cached_property
219221
def feeds(self):

tests/test_async_stream_close.py

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,14 @@ async def test_aclose_closes_chat_client(self):
2828
await client.aclose()
2929
assert client.chat.client.is_closed is True
3030

31+
async def test_aclose_closes_moderation_client(self):
32+
client = AsyncStream(api_key="fake", api_secret="fake")
33+
_ = client.moderation
34+
35+
assert client.moderation.client.is_closed is False
36+
await client.aclose()
37+
assert client.moderation.client.is_closed is True
38+
3139
async def test_aclose_without_child_clients(self):
3240
"""aclose() should work even if video/chat were never accessed."""
3341
client = AsyncStream(api_key="fake", api_secret="fake")

0 commit comments

Comments
 (0)