mirror of
https://github.com/Dispatcharr/Dispatcharr.git
synced 2026-01-23 02:35:14 +00:00
Enhancement: Increase time for a client to search for an available connection from 1.5 seconds to 3 seconds. This will help when clients are changing channels and release the old connection AFTER attempting to start the new connection. Closes #503
Bug Fix: Fix a bug where searching for an available stream could clear out stream locks for streams that it never acquired a lock for.
This commit is contained in:
parent
0031d55bab
commit
ec21e8329d
1 changed files with 46 additions and 24 deletions
|
|
@ -128,7 +128,7 @@ def stream_ts(request, channel_id):
|
|||
ChannelService.stop_channel(channel_id)
|
||||
|
||||
# Use fixed retry interval and timeout
|
||||
retry_timeout = 1.5 # 1.5 seconds total timeout
|
||||
retry_timeout = 3 # 3 seconds total timeout
|
||||
retry_interval = 0.1 # 100ms between attempts
|
||||
wait_start_time = time.time()
|
||||
|
||||
|
|
@ -138,9 +138,10 @@ def stream_ts(request, channel_id):
|
|||
profile_value = None
|
||||
error_reason = None
|
||||
attempt = 0
|
||||
should_retry = True
|
||||
|
||||
# Try to get a stream with fixed interval retries
|
||||
while time.time() - wait_start_time < retry_timeout:
|
||||
while should_retry and time.time() - wait_start_time < retry_timeout:
|
||||
attempt += 1
|
||||
stream_url, stream_user_agent, transcode, profile_value = (
|
||||
generate_stream_url(channel_id)
|
||||
|
|
@ -152,35 +153,53 @@ def stream_ts(request, channel_id):
|
|||
)
|
||||
break
|
||||
|
||||
# If we failed because there are no streams assigned, don't retry
|
||||
_, _, error_reason = channel.get_stream()
|
||||
if error_reason and "maximum connection limits" not in error_reason:
|
||||
logger.warning(
|
||||
f"[{client_id}] Can't retry - error not related to connection limits: {error_reason}"
|
||||
# On first failure, check if the error is retryable
|
||||
if attempt == 1:
|
||||
_, _, error_reason = channel.get_stream()
|
||||
if error_reason and "maximum connection limits" not in error_reason:
|
||||
logger.warning(
|
||||
f"[{client_id}] Can't retry - error not related to connection limits: {error_reason}"
|
||||
)
|
||||
should_retry = False
|
||||
break
|
||||
|
||||
# Check if we have time remaining for another sleep cycle
|
||||
elapsed_time = time.time() - wait_start_time
|
||||
remaining_time = retry_timeout - elapsed_time
|
||||
|
||||
# If we don't have enough time for the next sleep interval, break
|
||||
# but only after we've already made an attempt (the while condition will try one more time)
|
||||
if remaining_time <= retry_interval:
|
||||
logger.info(
|
||||
f"[{client_id}] Insufficient time ({remaining_time:.1f}s) for another sleep cycle, will make one final attempt"
|
||||
)
|
||||
break
|
||||
|
||||
# Wait 100ms before retrying
|
||||
elapsed_time = time.time() - wait_start_time
|
||||
remaining_time = retry_timeout - elapsed_time
|
||||
if remaining_time > retry_interval:
|
||||
# Wait before retrying
|
||||
logger.info(
|
||||
f"[{client_id}] Waiting {retry_interval*1000:.0f}ms for a connection to become available (attempt {attempt}, {remaining_time:.1f}s remaining)"
|
||||
)
|
||||
gevent.sleep(retry_interval)
|
||||
retry_interval += 0.025 # Increase wait time by 25ms for next attempt
|
||||
|
||||
# Make one final attempt if we still don't have a stream, should retry, and haven't exceeded timeout
|
||||
if stream_url is None and should_retry and time.time() - wait_start_time < retry_timeout:
|
||||
attempt += 1
|
||||
logger.info(
|
||||
f"[{client_id}] Making final attempt {attempt} at timeout boundary"
|
||||
)
|
||||
stream_url, stream_user_agent, transcode, profile_value = (
|
||||
generate_stream_url(channel_id)
|
||||
)
|
||||
if stream_url is not None:
|
||||
logger.info(
|
||||
f"[{client_id}] Waiting {retry_interval*1000:.0f}ms for a connection to become available (attempt {attempt}, {remaining_time:.1f}s remaining)"
|
||||
f"[{client_id}] Successfully obtained stream on final attempt for channel {channel_id}"
|
||||
)
|
||||
gevent.sleep(retry_interval)
|
||||
retry_interval += 0.025 # Increase wait time by 25ms for next attempt
|
||||
|
||||
if stream_url is None:
|
||||
# Make sure to release any stream locks that might have been acquired
|
||||
if hasattr(channel, "streams") and channel.streams.exists():
|
||||
for stream in channel.streams.all():
|
||||
try:
|
||||
stream.release_stream()
|
||||
logger.info(
|
||||
f"[{client_id}] Released stream {stream.id} for channel {channel_id}"
|
||||
)
|
||||
except Exception as e:
|
||||
logger.error(f"[{client_id}] Error releasing stream: {e}")
|
||||
# Release the channel's stream lock if one was acquired
|
||||
# Note: Only call this if get_stream() actually assigned a stream
|
||||
# In our case, if stream_url is None, no stream was ever assigned, so don't release
|
||||
|
||||
# Get the specific error message if available
|
||||
wait_duration = f"{int(time.time() - wait_start_time)}s"
|
||||
|
|
@ -189,6 +208,9 @@ def stream_ts(request, channel_id):
|
|||
if error_reason
|
||||
else "No available streams for this channel"
|
||||
)
|
||||
logger.info(
|
||||
f"[{client_id}] Failed to obtain stream after {attempt} attempts over {wait_duration}: {error_msg}"
|
||||
)
|
||||
return JsonResponse(
|
||||
{"error": error_msg, "waited": wait_duration}, status=503
|
||||
) # 503 Service Unavailable is appropriate here
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue