Retry failed song downloads instead of getting stuck

MusicServerClient functions now take an optional on_failed callback,
called when a request fails or returns invalid JSON. Before, a failed
request was silently dropped, so a failure while preloading a song left
Playlist.is_song_downloading set forever and no more songs were fetched.

Song fetching retries the step that failed (download, queue or info)
every song_fetch_retry_seconds, so the server and the game keep the same
playlist.
This commit is contained in:
Sansan committed 2026-10-05 19:47:10 +02:00
1 parent 91adf52cf4
commit 40ed4da908
4 files changed
+167 -65

No files matched your search

+38 -25
View File
@@ -140,6 +140,9 @@ var songs: Array= []
var soundtracks: Array = []
var current_player: Node
## Seconds to wait before retrying a song download step that failed.
var song_fetch_retry_seconds: float = 5.0
# Called when the node enters the scene tree for the first time.
func _ready() -> void:
var debug: bool = OS.has_feature("debug")
@@ -277,36 +280,46 @@ func play_next_song() -> void:
func fetch_song() -> void:
print("fetch_song")
Playlist.is_song_downloading = true
var new_song_object: SongObject = SongObject.new()
var fetch_song_done: Callable = func fetch_song_done(body: PackedByteArray) -> void:
print("fetch_song_done")
_download_random_song(SongObject.new())
# Fetching a song takes three requests. If one fails, only that step is retried, so
# the server and the game keep the same songs in their playlists.
func _download_random_song(new_song_object: SongObject) -> void:
var song_downloaded: Callable = func song_downloaded(body: PackedByteArray) -> void:
print("song_downloaded")
var sound: AudioStream = AudioStreamMP3.new()
sound.data = body
new_song_object.song = sound
var added_to_que_done: Callable = func added_to_que_done() -> void:
print("added_to_que_done")
var fetch_song_info_done: Callable = func fetch_song_info_done(data_received: Dictionary) -> void:
print("fetch_song_info_done")
new_song_object.song_number = data_received.SongNo
new_song_object.soundtrack_title = data_received.Soundtrack
new_song_object.song_title = data_received.Song
print("new_song_object: ", new_song_object.to_string())
Playlist.add_to_playlist(new_song_object)
next_button.disabled = false
if Playlist.should_preload_more_songs():
fetch_song()
else:
Playlist.is_song_downloading = false
if Settings.is_debug:
update_song_list()
MusicServerClient.fetch_song_info(fetch_song_info_done)
_add_song_to_queue(new_song_object)
MusicServerClient.fetch_random_song(Settings.use_low_played_mode, song_downloaded,
_retry_later.bind(_download_random_song.bind(new_song_object)))
MusicServerClient.add_to_queue(added_to_que_done)
func _add_song_to_queue(new_song_object: SongObject) -> void:
MusicServerClient.add_to_queue(_fetch_song_info.bind(new_song_object),
_retry_later.bind(_add_song_to_queue.bind(new_song_object)))
func _fetch_song_info(new_song_object: SongObject) -> void:
var song_info_fetched: Callable = func song_info_fetched(data_received: Dictionary) -> void:
print("song_info_fetched")
new_song_object.song_number = data_received.SongNo
new_song_object.soundtrack_title = data_received.Soundtrack
new_song_object.song_title = data_received.Song
print("new_song_object: ", new_song_object.to_string())
Playlist.add_to_playlist(new_song_object)
next_button.disabled = false
if Playlist.should_preload_more_songs():
fetch_song()
else:
Playlist.is_song_downloading = false
if Settings.is_debug:
update_song_list()
MusicServerClient.fetch_song_info(song_info_fetched,
_retry_later.bind(_fetch_song_info.bind(new_song_object)))
func _retry_later(step: Callable) -> void:
print("Song download failed, retrying in %s seconds" % song_fetch_retry_seconds)
get_tree().create_timer(song_fetch_retry_seconds).timeout.connect(step)
MusicServerClient.fetch_random_song(Settings.use_low_played_mode, fetch_song_done)
func update_song_list() -> void:
print("update_song_list")
if Playlist.currently_playing_song >= 0: