getstream 3.3.1__tar.gz → 3.3.3__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {getstream-3.3.1 → getstream-3.3.3}/PKG-INFO +1 -1
- {getstream-3.3.1 → getstream-3.3.3}/getstream/video/rtc/connection_manager.py +40 -1
- {getstream-3.3.1 → getstream-3.3.3}/getstream/video/rtc/reconnection.py +8 -2
- {getstream-3.3.1 → getstream-3.3.3}/getstream/video/rtc/signaling.py +56 -6
- {getstream-3.3.1 → getstream-3.3.3}/.cursor/worktrees.json +0 -0
- {getstream-3.3.1 → getstream-3.3.3}/.env.example +0 -0
- {getstream-3.3.1 → getstream-3.3.3}/.github/actions/python-uv-setup/action.yml +0 -0
- {getstream-3.3.1 → getstream-3.3.3}/.github/workflows/ci.yml +0 -0
- {getstream-3.3.1 → getstream-3.3.3}/.github/workflows/release.yml +0 -0
- {getstream-3.3.1 → getstream-3.3.3}/.github/workflows/run_tests.yml +0 -0
- {getstream-3.3.1 → getstream-3.3.3}/.github/workflows/stream-py.code-workspace +0 -0
- {getstream-3.3.1 → getstream-3.3.3}/.gitignore +0 -0
- {getstream-3.3.1 → getstream-3.3.3}/.gitmodules +0 -0
- {getstream-3.3.1 → getstream-3.3.3}/.pre-commit-config.yaml +0 -0
- {getstream-3.3.1 → getstream-3.3.3}/AGENTS.md +0 -0
- {getstream-3.3.1 → getstream-3.3.3}/CHANGELOG.md +0 -0
- {getstream-3.3.1 → getstream-3.3.3}/DEVELOPMENT.md +0 -0
- {getstream-3.3.1 → getstream-3.3.3}/LICENSE.md +0 -0
- {getstream-3.3.1 → getstream-3.3.3}/MIGRATION_v2_to_v3.md +0 -0
- {getstream-3.3.1 → getstream-3.3.3}/Makefile +0 -0
- {getstream-3.3.1 → getstream-3.3.3}/README.md +0 -0
- {getstream-3.3.1 → getstream-3.3.3}/dev.py +0 -0
- {getstream-3.3.1 → getstream-3.3.3}/docs/migration-from-stream-chat-python/01-setup-and-auth.md +0 -0
- {getstream-3.3.1 → getstream-3.3.3}/docs/migration-from-stream-chat-python/02-users.md +0 -0
- {getstream-3.3.1 → getstream-3.3.3}/docs/migration-from-stream-chat-python/03-channels.md +0 -0
- {getstream-3.3.1 → getstream-3.3.3}/docs/migration-from-stream-chat-python/04-messages-and-reactions.md +0 -0
- {getstream-3.3.1 → getstream-3.3.3}/docs/migration-from-stream-chat-python/05-moderation.md +0 -0
- {getstream-3.3.1 → getstream-3.3.3}/docs/migration-from-stream-chat-python/06-devices.md +0 -0
- {getstream-3.3.1 → getstream-3.3.3}/docs/migration-from-stream-chat-python/README.md +0 -0
- {getstream-3.3.1 → getstream-3.3.3}/generate.sh +0 -0
- {getstream-3.3.1 → getstream-3.3.3}/generate_webrtc.sh +0 -0
- {getstream-3.3.1 → getstream-3.3.3}/getstream/__init__.py +0 -0
- {getstream-3.3.1 → getstream-3.3.3}/getstream/base.py +0 -0
- {getstream-3.3.1 → getstream-3.3.3}/getstream/chat/__init__.py +0 -0
- {getstream-3.3.1 → getstream-3.3.3}/getstream/chat/async_channel.py +0 -0
- {getstream-3.3.1 → getstream-3.3.3}/getstream/chat/async_client.py +0 -0
- {getstream-3.3.1 → getstream-3.3.3}/getstream/chat/async_rest_client.py +0 -0
- {getstream-3.3.1 → getstream-3.3.3}/getstream/chat/channel.py +0 -0
- {getstream-3.3.1 → getstream-3.3.3}/getstream/chat/client.py +0 -0
- {getstream-3.3.1 → getstream-3.3.3}/getstream/chat/rest_client.py +0 -0
- {getstream-3.3.1 → getstream-3.3.3}/getstream/common/__init__.py +0 -0
- {getstream-3.3.1 → getstream-3.3.3}/getstream/common/async_client.py +0 -0
- {getstream-3.3.1 → getstream-3.3.3}/getstream/common/async_rest_client.py +0 -0
- {getstream-3.3.1 → getstream-3.3.3}/getstream/common/client.py +0 -0
- {getstream-3.3.1 → getstream-3.3.3}/getstream/common/rest_client.py +0 -0
- {getstream-3.3.1 → getstream-3.3.3}/getstream/common/telemetry.py +0 -0
- {getstream-3.3.1 → getstream-3.3.3}/getstream/config.py +0 -0
- {getstream-3.3.1 → getstream-3.3.3}/getstream/feeds/__init__.py +0 -0
- {getstream-3.3.1 → getstream-3.3.3}/getstream/feeds/client.py +0 -0
- {getstream-3.3.1 → getstream-3.3.3}/getstream/feeds/feeds.py +0 -0
- {getstream-3.3.1 → getstream-3.3.3}/getstream/feeds/rest_client.py +0 -0
- {getstream-3.3.1 → getstream-3.3.3}/getstream/generic.py +0 -0
- {getstream-3.3.1 → getstream-3.3.3}/getstream/meta.py +0 -0
- {getstream-3.3.1 → getstream-3.3.3}/getstream/models/__init__.py +0 -0
- {getstream-3.3.1 → getstream-3.3.3}/getstream/moderation/__init__.py +0 -0
- {getstream-3.3.1 → getstream-3.3.3}/getstream/moderation/async_client.py +0 -0
- {getstream-3.3.1 → getstream-3.3.3}/getstream/moderation/async_rest_client.py +0 -0
- {getstream-3.3.1 → getstream-3.3.3}/getstream/moderation/client.py +0 -0
- {getstream-3.3.1 → getstream-3.3.3}/getstream/moderation/rest_client.py +0 -0
- {getstream-3.3.1 → getstream-3.3.3}/getstream/rate_limit.py +0 -0
- {getstream-3.3.1 → getstream-3.3.3}/getstream/stream.py +0 -0
- {getstream-3.3.1 → getstream-3.3.3}/getstream/stream_response.py +0 -0
- {getstream-3.3.1 → getstream-3.3.3}/getstream/tests/test_webhook.py +0 -0
- {getstream-3.3.1 → getstream-3.3.3}/getstream/utils/__init__.py +0 -0
- {getstream-3.3.1 → getstream-3.3.3}/getstream/utils/event_emitter.py +0 -0
- {getstream-3.3.1 → getstream-3.3.3}/getstream/utils/retry.py +0 -0
- {getstream-3.3.1 → getstream-3.3.3}/getstream/version.py +0 -0
- {getstream-3.3.1 → getstream-3.3.3}/getstream/video/__init__.py +0 -0
- {getstream-3.3.1 → getstream-3.3.3}/getstream/video/async_call.py +0 -0
- {getstream-3.3.1 → getstream-3.3.3}/getstream/video/async_client.py +0 -0
- {getstream-3.3.1 → getstream-3.3.3}/getstream/video/async_rest_client.py +0 -0
- {getstream-3.3.1 → getstream-3.3.3}/getstream/video/call.py +0 -0
- {getstream-3.3.1 → getstream-3.3.3}/getstream/video/client.py +0 -0
- {getstream-3.3.1 → getstream-3.3.3}/getstream/video/openai.py +0 -0
- {getstream-3.3.1 → getstream-3.3.3}/getstream/video/rest_client.py +0 -0
- {getstream-3.3.1 → getstream-3.3.3}/getstream/video/rtc/README.md +0 -0
- {getstream-3.3.1 → getstream-3.3.3}/getstream/video/rtc/__init__.py +0 -0
- {getstream-3.3.1 → getstream-3.3.3}/getstream/video/rtc/audio_track.py +0 -0
- {getstream-3.3.1 → getstream-3.3.3}/getstream/video/rtc/connection_utils.py +0 -0
- {getstream-3.3.1 → getstream-3.3.3}/getstream/video/rtc/coordinator/__init__.py +0 -0
- {getstream-3.3.1 → getstream-3.3.3}/getstream/video/rtc/coordinator/backoff.py +0 -0
- {getstream-3.3.1 → getstream-3.3.3}/getstream/video/rtc/coordinator/errors.py +0 -0
- {getstream-3.3.1 → getstream-3.3.3}/getstream/video/rtc/coordinator/ws.py +0 -0
- {getstream-3.3.1 → getstream-3.3.3}/getstream/video/rtc/coordinator_api.py +0 -0
- {getstream-3.3.1 → getstream-3.3.3}/getstream/video/rtc/encoders_patches.py +0 -0
- {getstream-3.3.1 → getstream-3.3.3}/getstream/video/rtc/g711.py +0 -0
- {getstream-3.3.1 → getstream-3.3.3}/getstream/video/rtc/location_discovery.py +0 -0
- {getstream-3.3.1 → getstream-3.3.3}/getstream/video/rtc/models.py +0 -0
- {getstream-3.3.1 → getstream-3.3.3}/getstream/video/rtc/network_monitor.py +0 -0
- {getstream-3.3.1 → getstream-3.3.3}/getstream/video/rtc/participants.py +0 -0
- {getstream-3.3.1 → getstream-3.3.3}/getstream/video/rtc/pb/__init__.py +0 -0
- {getstream-3.3.1 → getstream-3.3.3}/getstream/video/rtc/pb/stream/__init__.py +0 -0
- {getstream-3.3.1 → getstream-3.3.3}/getstream/video/rtc/pb/stream/video/__init__.py +0 -0
- {getstream-3.3.1 → getstream-3.3.3}/getstream/video/rtc/pb/stream/video/sfu/__init__.py +0 -0
- {getstream-3.3.1 → getstream-3.3.3}/getstream/video/rtc/pb/stream/video/sfu/event/__init__.py +0 -0
- {getstream-3.3.1 → getstream-3.3.3}/getstream/video/rtc/pb/stream/video/sfu/event/events_pb2.py +0 -0
- {getstream-3.3.1 → getstream-3.3.3}/getstream/video/rtc/pb/stream/video/sfu/event/events_pb2.pyi +0 -0
- {getstream-3.3.1 → getstream-3.3.3}/getstream/video/rtc/pb/stream/video/sfu/models/__init__.py +0 -0
- {getstream-3.3.1 → getstream-3.3.3}/getstream/video/rtc/pb/stream/video/sfu/models/models_pb2.py +0 -0
- {getstream-3.3.1 → getstream-3.3.3}/getstream/video/rtc/pb/stream/video/sfu/models/models_pb2.pyi +0 -0
- {getstream-3.3.1 → getstream-3.3.3}/getstream/video/rtc/pb/stream/video/sfu/signal_rpc/__init__.py +0 -0
- {getstream-3.3.1 → getstream-3.3.3}/getstream/video/rtc/pb/stream/video/sfu/signal_rpc/signal_pb2.py +0 -0
- {getstream-3.3.1 → getstream-3.3.3}/getstream/video/rtc/pb/stream/video/sfu/signal_rpc/signal_pb2.pyi +0 -0
- {getstream-3.3.1 → getstream-3.3.3}/getstream/video/rtc/pb/stream/video/sfu/signal_rpc/signal_twirp.py +0 -0
- {getstream-3.3.1 → getstream-3.3.3}/getstream/video/rtc/pc.py +0 -0
- {getstream-3.3.1 → getstream-3.3.3}/getstream/video/rtc/peer_connection.py +0 -0
- {getstream-3.3.1 → getstream-3.3.3}/getstream/video/rtc/recording.py +0 -0
- {getstream-3.3.1 → getstream-3.3.3}/getstream/video/rtc/stats_reporter.py +0 -0
- {getstream-3.3.1 → getstream-3.3.3}/getstream/video/rtc/stats_tracer.py +0 -0
- {getstream-3.3.1 → getstream-3.3.3}/getstream/video/rtc/tracer.py +0 -0
- {getstream-3.3.1 → getstream-3.3.3}/getstream/video/rtc/track_util.py +0 -0
- {getstream-3.3.1 → getstream-3.3.3}/getstream/video/rtc/tracks.py +0 -0
- {getstream-3.3.1 → getstream-3.3.3}/getstream/video/rtc/twirp_client_wrapper.py +0 -0
- {getstream-3.3.1 → getstream-3.3.3}/getstream/video/rtc/utils.py +0 -0
- {getstream-3.3.1 → getstream-3.3.3}/getstream/webhook.py +0 -0
- {getstream-3.3.1 → getstream-3.3.3}/pyproject.toml +0 -0
- {getstream-3.3.1 → getstream-3.3.3}/pytest.ini +0 -0
- {getstream-3.3.1 → getstream-3.3.3}/uv.lock +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: getstream
|
|
3
|
-
Version: 3.3.
|
|
3
|
+
Version: 3.3.3
|
|
4
4
|
Summary: GetStream Python SDK - Build scalable activity feeds, chat, and video calling applications
|
|
5
5
|
Author-email: sachaarbonel <sacha.arbonel@hotmail.fr>, tbarbugli <tbarbugli@gmail.com>
|
|
6
6
|
License-File: LICENSE.md
|
|
@@ -36,7 +36,7 @@ from getstream.video.rtc.network_monitor import NetworkMonitor
|
|
|
36
36
|
from getstream.video.rtc.recording import RecordingManager
|
|
37
37
|
from getstream.video.rtc.participants import ParticipantsState
|
|
38
38
|
from getstream.video.rtc.tracks import SubscriptionConfig, SubscriptionManager
|
|
39
|
-
from getstream.video.rtc.reconnection import ReconnectionManager
|
|
39
|
+
from getstream.video.rtc.reconnection import ReconnectionManager, ReconnectionStrategy
|
|
40
40
|
from getstream.video.rtc.peer_connection import PeerConnectionManager
|
|
41
41
|
from getstream.video.rtc.models import JoinCallResponse
|
|
42
42
|
from getstream.video.rtc.tracer import Tracer
|
|
@@ -198,6 +198,17 @@ class ConnectionManager(StreamAsyncIOEventEmitter):
|
|
|
198
198
|
async def _on_subscriber_offer(self, event: events_pb2.SubscriberOffer):
|
|
199
199
|
logger.info("Subscriber offer received")
|
|
200
200
|
|
|
201
|
+
# Offers can arrive after the subscriber peer connection has been
|
|
202
|
+
# torn down (slow asyncio loop under load, SFU sending a late
|
|
203
|
+
# renegotiation). `setRemoteDescription` would raise
|
|
204
|
+
# `InvalidStateError: Cannot handle offer in signaling state "closed"`
|
|
205
|
+
# and the exception propagates through the pyee error path, killing
|
|
206
|
+
# the session. Drop the offer instead — there is nothing to
|
|
207
|
+
# negotiate with a closed connection.
|
|
208
|
+
if self.subscriber_pc is None or self.subscriber_pc.signalingState == "closed":
|
|
209
|
+
logger.debug("Subscriber offer arrived after PC closed; dropping")
|
|
210
|
+
return
|
|
211
|
+
|
|
201
212
|
with telemetry.start_as_current_span("rtc.on_subscriber_offer") as span:
|
|
202
213
|
await self.subscriber_negotiation_lock.acquire()
|
|
203
214
|
|
|
@@ -266,6 +277,25 @@ class ConnectionManager(StreamAsyncIOEventEmitter):
|
|
|
266
277
|
finally:
|
|
267
278
|
self.subscriber_negotiation_lock.release()
|
|
268
279
|
|
|
280
|
+
async def _on_signaling_connection_lost(self, reason: str) -> None:
|
|
281
|
+
"""Reconnect when the signaling WebSocket drops unexpectedly.
|
|
282
|
+
|
|
283
|
+
The WebSocketClient itself only logs the error and stops; it has
|
|
284
|
+
no reconnect of its own. This handler bridges that gap by routing
|
|
285
|
+
the loss into the existing `ReconnectionManager`, so a transient
|
|
286
|
+
TCP reset or a missed health check no longer means a dead session.
|
|
287
|
+
"""
|
|
288
|
+
if not self.running:
|
|
289
|
+
return
|
|
290
|
+
logger.warning(f"Signaling WS lost; triggering reconnect: {reason}")
|
|
291
|
+
try:
|
|
292
|
+
await self._reconnector.reconnect(
|
|
293
|
+
strategy=ReconnectionStrategy.FAST,
|
|
294
|
+
reason=f"signaling ws lost: {reason}",
|
|
295
|
+
)
|
|
296
|
+
except Exception:
|
|
297
|
+
logger.exception("Reconnect after signaling WS loss failed")
|
|
298
|
+
|
|
269
299
|
async def _connect_coordinator_ws(self):
|
|
270
300
|
"""
|
|
271
301
|
Connects to the coordinator websocket and subscribes to events.
|
|
@@ -403,6 +433,15 @@ class ConnectionManager(StreamAsyncIOEventEmitter):
|
|
|
403
433
|
# Connect subscriber offer event to handle SDP negotiation
|
|
404
434
|
self._ws_client.on_event("subscriber_offer", self._on_subscriber_offer)
|
|
405
435
|
|
|
436
|
+
# Drive reconnection when the signaling WS drops outside of an
|
|
437
|
+
# SFU-level error event (raw socket close, health-check timeout,
|
|
438
|
+
# transport-level exceptions). Without this handler the
|
|
439
|
+
# WebSocketClient just logs and stops; the session sits hanging
|
|
440
|
+
# until the frontend times out and tears it down.
|
|
441
|
+
self._ws_client.on_event(
|
|
442
|
+
"connection_lost", self._on_signaling_connection_lost
|
|
443
|
+
)
|
|
444
|
+
|
|
406
445
|
# Re-emit the events so they can be subscribed to on the ConnectionManager
|
|
407
446
|
self._ws_client.on_wildcard("*", self.emit)
|
|
408
447
|
|
|
@@ -209,10 +209,16 @@ class ReconnectionManager:
|
|
|
209
209
|
self.connection_manager._connection_options.fast_reconnect = True
|
|
210
210
|
previous_ws_client = self.connection_manager.ws_client
|
|
211
211
|
|
|
212
|
-
# Use _connect_internal with existing connection info
|
|
212
|
+
# Use _connect_internal with existing connection info.
|
|
213
|
+
# `self.join_response` is already the unwrapped data payload
|
|
214
|
+
# (see ConnectionManager._connect_internal: it stores
|
|
215
|
+
# `join_response.data`), so credentials live at the top level.
|
|
213
216
|
await self.connection_manager._connect_internal(
|
|
214
217
|
region=self.connection_manager._connection_options.region,
|
|
215
|
-
token=self.connection_manager.join_response.
|
|
218
|
+
token=self.connection_manager.join_response.credentials.token
|
|
219
|
+
if self.connection_manager.join_response
|
|
220
|
+
else None,
|
|
221
|
+
ws_url=self.connection_manager.join_response.credentials.server.ws_endpoint
|
|
216
222
|
if self.connection_manager.join_response
|
|
217
223
|
else None,
|
|
218
224
|
session_id=self.connection_manager.session_id,
|
|
@@ -67,6 +67,11 @@ class WebSocketClient(StreamAsyncIOEventEmitter):
|
|
|
67
67
|
self.thread = None
|
|
68
68
|
self.running = False
|
|
69
69
|
self.closed = False
|
|
70
|
+
self._connection_lost_sent = False
|
|
71
|
+
# Set when a `call_ended` SFU event arrives. Read by `_on_close` to
|
|
72
|
+
# suppress `connection_lost`, since the close frame that follows carries
|
|
73
|
+
# no distinguishing status code or reason.
|
|
74
|
+
self._call_ended = False
|
|
70
75
|
|
|
71
76
|
# For ping/health check mechanism
|
|
72
77
|
self.ping_thread = None
|
|
@@ -167,6 +172,9 @@ class WebSocketClient(StreamAsyncIOEventEmitter):
|
|
|
167
172
|
event_type = event.WhichOneof("event_payload")
|
|
168
173
|
logger.debug(f"WebSocket message received {event_type}")
|
|
169
174
|
|
|
175
|
+
if event_type and event_type == "call_ended":
|
|
176
|
+
self._call_ended = True
|
|
177
|
+
|
|
170
178
|
if event.HasField("health_check_response"):
|
|
171
179
|
logger.debug("received health check response")
|
|
172
180
|
self.last_health_check_time = time.time()
|
|
@@ -198,27 +206,65 @@ class WebSocketClient(StreamAsyncIOEventEmitter):
|
|
|
198
206
|
|
|
199
207
|
def _on_error(self, ws, error):
|
|
200
208
|
"""Handle WebSocket error."""
|
|
201
|
-
|
|
209
|
+
is_close_frame = (
|
|
202
210
|
isinstance(error, websocket.ABNF)
|
|
203
211
|
and error.opcode == websocket.ABNF.OPCODE_CLOSE
|
|
204
|
-
)
|
|
205
|
-
|
|
206
|
-
#
|
|
207
|
-
logger.debug(f"WebSocket
|
|
212
|
+
)
|
|
213
|
+
if is_close_frame or not self.running:
|
|
214
|
+
# Close-frame-as-error or post-disconnect teardown noise.
|
|
215
|
+
logger.debug(f"WebSocket error after disconnect: {error}")
|
|
208
216
|
else:
|
|
209
217
|
logger.error(f"WebSocket error: {error}")
|
|
210
218
|
|
|
211
219
|
if not self.first_message_event.is_set():
|
|
212
|
-
#
|
|
220
|
+
# Mid-handshake failure: unblock `connect()` with a synthetic
|
|
221
|
+
# error event instead of leaving it parked on `first_message_event`.
|
|
213
222
|
error_event = events_pb2.SfuEvent()
|
|
214
223
|
error_event.error.error.message = str(error)
|
|
215
224
|
self.first_message = error_event
|
|
216
225
|
self.first_message_event.set()
|
|
226
|
+
elif not self.closed and not is_close_frame:
|
|
227
|
+
self._notify_connection_lost(f"error: {error}")
|
|
217
228
|
|
|
218
229
|
def _on_close(self, ws, close_status_code, close_msg):
|
|
219
230
|
"""Handle WebSocket close event."""
|
|
220
231
|
logger.debug(f"WebSocket connection closed: {close_status_code} {close_msg}")
|
|
232
|
+
was_unexpected = not self.closed and not self._call_ended
|
|
221
233
|
self.running = False
|
|
234
|
+
if was_unexpected:
|
|
235
|
+
self._notify_connection_lost(
|
|
236
|
+
f"closed by remote (code={close_status_code} msg={close_msg})"
|
|
237
|
+
)
|
|
238
|
+
|
|
239
|
+
def _notify_connection_lost(self, reason: str) -> None:
|
|
240
|
+
"""Schedule a ``connection_lost`` emit on the main loop.
|
|
241
|
+
|
|
242
|
+
Idempotent per ``WebSocketClient`` instance — only the first call
|
|
243
|
+
per disconnect actually emits. Callers run on the WS worker thread
|
|
244
|
+
or ``_ping_loop`` thread; pyee schedules async listeners via
|
|
245
|
+
``loop.create_task``, which is not thread-safe, hence the hop.
|
|
246
|
+
Same pattern as ``_on_message`` for SFU events.
|
|
247
|
+
"""
|
|
248
|
+
if not self._claim_connection_lost():
|
|
249
|
+
return
|
|
250
|
+
try:
|
|
251
|
+
asyncio.run_coroutine_threadsafe(
|
|
252
|
+
self._emit_connection_lost(reason),
|
|
253
|
+
self.main_loop,
|
|
254
|
+
)
|
|
255
|
+
except Exception:
|
|
256
|
+
logger.exception("Failed to schedule connection_lost emit")
|
|
257
|
+
|
|
258
|
+
def _claim_connection_lost(self) -> bool:
|
|
259
|
+
"""Return True if this is the first connection-lost notification."""
|
|
260
|
+
if self._connection_lost_sent:
|
|
261
|
+
return False
|
|
262
|
+
self._connection_lost_sent = True
|
|
263
|
+
return True
|
|
264
|
+
|
|
265
|
+
async def _emit_connection_lost(self, reason: str) -> None:
|
|
266
|
+
with telemetry.attach_span(self.parent_span):
|
|
267
|
+
self.emit("connection_lost", reason)
|
|
222
268
|
|
|
223
269
|
def _start_ping_handler(self):
|
|
224
270
|
"""Start the ping mechanism in a background thread."""
|
|
@@ -242,6 +288,10 @@ class WebSocketClient(StreamAsyncIOEventEmitter):
|
|
|
242
288
|
current_time = time.time()
|
|
243
289
|
if current_time - self.last_health_check_time > self.ping_interval * 2:
|
|
244
290
|
logger.warning("Health check failed, closing connection")
|
|
291
|
+
# Notify before close() so the owner can reconnect; close()
|
|
292
|
+
# itself sets `self.closed=True` and would suppress the
|
|
293
|
+
# notification in `_on_close`.
|
|
294
|
+
self._notify_connection_lost("health check timeout")
|
|
245
295
|
self.close()
|
|
246
296
|
return
|
|
247
297
|
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{getstream-3.3.1 → getstream-3.3.3}/docs/migration-from-stream-chat-python/01-setup-and-auth.md
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{getstream-3.3.1 → getstream-3.3.3}/getstream/video/rtc/pb/stream/video/sfu/event/__init__.py
RENAMED
|
File without changes
|
{getstream-3.3.1 → getstream-3.3.3}/getstream/video/rtc/pb/stream/video/sfu/event/events_pb2.py
RENAMED
|
File without changes
|
{getstream-3.3.1 → getstream-3.3.3}/getstream/video/rtc/pb/stream/video/sfu/event/events_pb2.pyi
RENAMED
|
File without changes
|
{getstream-3.3.1 → getstream-3.3.3}/getstream/video/rtc/pb/stream/video/sfu/models/__init__.py
RENAMED
|
File without changes
|
{getstream-3.3.1 → getstream-3.3.3}/getstream/video/rtc/pb/stream/video/sfu/models/models_pb2.py
RENAMED
|
File without changes
|
{getstream-3.3.1 → getstream-3.3.3}/getstream/video/rtc/pb/stream/video/sfu/models/models_pb2.pyi
RENAMED
|
File without changes
|
{getstream-3.3.1 → getstream-3.3.3}/getstream/video/rtc/pb/stream/video/sfu/signal_rpc/__init__.py
RENAMED
|
File without changes
|
{getstream-3.3.1 → getstream-3.3.3}/getstream/video/rtc/pb/stream/video/sfu/signal_rpc/signal_pb2.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|