From acacc3622dc8b6444b48b4b124972ec5d9f82b59 Mon Sep 17 00:00:00 2001 From: trekkie1707 Date: Tue, 19 Aug 2025 01:49:08 -0400 Subject: [PATCH 1/3] adding thread for processing large playlists --- skill/app.py | 17 ++++++++++++++--- 1 file changed, 14 insertions(+), 3 deletions(-) diff --git a/skill/app.py b/skill/app.py index 9c48ad0..841d710 100755 --- a/skill/app.py +++ b/skill/app.py @@ -3,6 +3,9 @@ import logging import os import random import sys +from multiprocessing import Process, Manager +from multiprocessing.managers import BaseManager + from ask_sdk_core.skill_builder import SkillBuilder from ask_sdk_core.dispatch_components import AbstractRequestHandler, AbstractRequestInterceptor, AbstractResponseInterceptor @@ -173,7 +176,10 @@ if 'NAVI_DEBUG' in os.environ: logger.warning('Log level set to WARNING') # Create a queue -play_queue = queue.MediaQueue() +BaseManager.register('MediaQueue', queue.MediaQueue) +manager = BaseManager() +manager.start() +play_queue = manager.MediaQueue() logger.debug('MediaQueue object created...') # Connect to Navidrome @@ -483,8 +489,9 @@ class NaviSonicPlayPlaylist(AbstractRequestHandler): else: song_id_list = connection.build_song_list_from_playlist(playlist_id) play_queue.clear() - controller.enqueue_songs(connection, play_queue, song_id_list) - + controller.enqueue_songs(connection, play_queue, [song_id_list[0]]) + process = Process(target=queueWorkerThread, args=(connection, play_queue, song_id_list[1:])) + process.start() speech = 'Playing playlist ' + str(playlist.value) logger.info(speech) card = {'title': 'AskNavidrome', @@ -494,6 +501,10 @@ class NaviSonicPlayPlaylist(AbstractRequestHandler): return controller.start_playback('play', speech, card, track_details, handler_input) +def queueWorkerThread(connection, play_queue, song_id_list): + logger.debug('In playlist processing thread!') + controller.enqueue_songs(connection, play_queue, song_id_list) + logger.debug('Finished playlist processing!') class NaviSonicPlayMusicByGenre(AbstractRequestHandler): """ Play songs from the given genere From 1ef49d42efc792e1a1701f2236025af33ffc3152 Mon Sep 17 00:00:00 2001 From: trekkie1707 Date: Tue, 19 Aug 2025 22:43:35 -0400 Subject: [PATCH 2/3] Be sure to sync the queue again after async queue adds. Now return 2 items with initial response --- skill/app.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/skill/app.py b/skill/app.py index 841d710..eeff659 100755 --- a/skill/app.py +++ b/skill/app.py @@ -489,8 +489,8 @@ class NaviSonicPlayPlaylist(AbstractRequestHandler): else: song_id_list = connection.build_song_list_from_playlist(playlist_id) play_queue.clear() - controller.enqueue_songs(connection, play_queue, [song_id_list[0]]) - process = Process(target=queueWorkerThread, args=(connection, play_queue, song_id_list[1:])) + controller.enqueue_songs(connection, play_queue, [song_id_list[0], song_id_list[1]]) + process = Process(target=queueWorkerThread, args=(connection, play_queue, song_id_list[2:])) process.start() speech = 'Playing playlist ' + str(playlist.value) logger.info(speech) @@ -504,6 +504,7 @@ class NaviSonicPlayPlaylist(AbstractRequestHandler): def queueWorkerThread(connection, play_queue, song_id_list): logger.debug('In playlist processing thread!') controller.enqueue_songs(connection, play_queue, song_id_list) + play_queue.sync() logger.debug('Finished playlist processing!') class NaviSonicPlayMusicByGenre(AbstractRequestHandler): From 0d4ce1e0ed12dc033ba6eb427f816abd5f61556c Mon Sep 17 00:00:00 2001 From: trekkie1707 Date: Tue, 19 Aug 2025 23:12:48 -0400 Subject: [PATCH 3/3] Make sure we kill any existing process before we try to spin one up again. --- skill/app.py | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/skill/app.py b/skill/app.py index eeff659..68458cf 100755 --- a/skill/app.py +++ b/skill/app.py @@ -182,6 +182,8 @@ manager.start() play_queue = manager.MediaQueue() logger.debug('MediaQueue object created...') +backgroundProcess = None + # Connect to Navidrome connection = api.SubsonicConnection(navidrome_url, navidrome_user, @@ -472,8 +474,13 @@ class NaviSonicPlayPlaylist(AbstractRequestHandler): return is_intent_name('NaviSonicPlayPlaylist')(handler_input) def handle(self, handler_input: HandlerInput) -> Response: + global backgroundProcess logger.debug('In NaviSonicPlayPlaylist') + if backgroundProcess != None: + backgroundProcess.terminate() + backgroundProcess.join() + # Get the requested playlist playlist = get_slot_value_v2(handler_input, 'playlist') @@ -490,8 +497,8 @@ class NaviSonicPlayPlaylist(AbstractRequestHandler): song_id_list = connection.build_song_list_from_playlist(playlist_id) play_queue.clear() controller.enqueue_songs(connection, play_queue, [song_id_list[0], song_id_list[1]]) - process = Process(target=queueWorkerThread, args=(connection, play_queue, song_id_list[2:])) - process.start() + backgroundProcess = Process(target=queueWorkerThread, args=(connection, play_queue, song_id_list[2:])) + backgroundProcess.start() speech = 'Playing playlist ' + str(playlist.value) logger.info(speech) card = {'title': 'AskNavidrome',