From cd1da5a61c1fb8b4dc8115c5b39b3a2a02bb95d2 Mon Sep 17 00:00:00 2001 From: SergeantPanda Date: Mon, 28 Apr 2025 17:25:03 -0500 Subject: [PATCH] Added a new channel model to update m3u profile counts and utilize it during stream switches. --- apps/channels/models.py | 47 +++++++++++++++++++++++++++ apps/proxy/ts_proxy/stream_manager.py | 26 +++++++++++---- 2 files changed, 66 insertions(+), 7 deletions(-) diff --git a/apps/channels/models.py b/apps/channels/models.py index 0b66c468..4485936e 100644 --- a/apps/channels/models.py +++ b/apps/channels/models.py @@ -407,6 +407,53 @@ class Channel(models.Model): if current_count > 0: redis_client.decr(profile_connections_key) + def update_stream_profile(self, new_profile_id): + """ + Updates the profile for the current stream and adjusts connection counts. + + Args: + new_profile_id: The ID of the new stream profile to use + + Returns: + bool: True if successful, False otherwise + """ + redis_client = RedisClient.get_client() + + # Get current stream ID + stream_id_bytes = redis_client.get(f"channel_stream:{self.id}") + if not stream_id_bytes: + logger.debug("No active stream found for channel") + return False + + stream_id = int(stream_id_bytes) + + # Get current profile ID + current_profile_id_bytes = redis_client.get(f"stream_profile:{stream_id}") + if not current_profile_id_bytes: + logger.debug("No profile found for current stream") + return False + + current_profile_id = int(current_profile_id_bytes) + + # Don't do anything if the profile is already set to the requested one + if current_profile_id == new_profile_id: + return True + + # Decrement connection count for old profile + old_profile_connections_key = f"profile_connections:{current_profile_id}" + old_count = int(redis_client.get(old_profile_connections_key) or 0) + if old_count > 0: + redis_client.decr(old_profile_connections_key) + + # Update the profile mapping + redis_client.set(f"stream_profile:{stream_id}", new_profile_id) + + # Increment connection count for new profile + new_profile_connections_key = f"profile_connections:{new_profile_id}" + redis_client.incr(new_profile_connections_key) + logger.info(f"Updated stream {stream_id} profile from {current_profile_id} to {new_profile_id}") + return True + class ChannelProfile(models.Model): name = models.CharField(max_length=100, unique=True) diff --git a/apps/proxy/ts_proxy/stream_manager.py b/apps/proxy/ts_proxy/stream_manager.py index 8f7b1817..6fd2b4b8 100644 --- a/apps/proxy/ts_proxy/stream_manager.py +++ b/apps/proxy/ts_proxy/stream_manager.py @@ -543,15 +543,27 @@ class StreamManager: logger.info(f"Switching stream URL from {self.url} to {new_url}") - # Release old stream resources if we have a current stream ID - if self.current_stream_id: + # Import both models for proper resource management + from apps.channels.models import Stream, Channel + + # Update stream profile if we're switching streams + if self.current_stream_id and stream_id and self.current_stream_id != stream_id: try: - from apps.channels.models import Stream - stream = Stream.objects.get(pk=self.current_stream_id) - stream.release_stream() - logger.info(f"Released stream {self.current_stream_id} for channel {self.channel_id}") + # Get the channel by UUID + channel = Channel.objects.get(uuid=self.channel_id) + + # Get stream to find its profile + new_stream = Stream.objects.get(pk=stream_id) + + # Use the new method to update the profile and manage connection counts + if new_stream.m3u_account_id: + success = channel.update_stream_profile(new_stream.m3u_account_id) + if success: + logger.debug(f"Updated stream profile for channel {self.channel_id} to use profile from stream {stream_id}") + else: + logger.warning(f"Failed to update stream profile for channel {self.channel_id}") except Exception as e: - logger.error(f"Error releasing stream {self.current_stream_id}: {e}") + logger.error(f"Error updating stream profile for channel {self.channel_id}: {e}") # CRITICAL: Set a flag to prevent immediate reconnection with old URL self.url_switching = True