@@ -59,15 +59,17 @@ defmodule Pling.Playlists.MusicLibrary do
5959 Gets a playlist by Spotify ID, fetching it from Spotify if it doesn't exist locally.
6060 Returns the playlist as soon as it has basic info and at least one track.
6161 """
62- def get_or_fetch_playlist ( spotify_id , timeout \\ 5000 ) do
62+ def get_or_fetch_playlist ( spotify_id ) do
6363 case Repo . get ( Playlist , spotify_id ) do
6464 nil ->
6565 ref = make_ref ( )
6666 parent = self ( )
67- notification_agent = Process . spawn ( fn -> receive do: ( _ -> :ok ) end , [ ] )
67+ Logger . debug ( "Starting playlist fetch" , spotify_id: spotify_id , ref: ref )
6868
6969 callback = fn
7070 % { "playlist_info" => info } ->
71+ Logger . debug ( "Processing playlist info" , name: info [ "name" ] )
72+
7173 playlist = % Playlist {
7274 spotify_id: spotify_id ,
7375 name: info [ "name" ] ,
@@ -77,63 +79,78 @@ defmodule Pling.Playlists.MusicLibrary do
7779 }
7880
7981 { :ok , saved_playlist } = Repo . insert ( playlist )
80- saved_playlist
82+ :ok
8183
8284 % { "track" => track } ->
83- result =
84- Repo . transaction ( fn ->
85- track_entry = % Track {
86- uri: track [ "uri" ] ,
87- title: track [ "name" ] ,
88- artists: Enum . map ( track [ "artists" ] , & & 1 [ "name" ] ) ,
89- popularity: track [ "popularity" ] ,
90- album: track [ "album" ] [ "name" ]
91- }
92-
93- # First ensure the track exists
94- { :ok , saved_track } = Repo . insert ( track_entry , on_conflict: :nothing )
95-
96- # Then create the association only if track was saved
97- if saved_track . uri do
98- { 1 , _ } =
99- Repo . insert_all (
100- "playlist_tracks" ,
101- [
102- % {
103- track_uri: saved_track . uri ,
104- playlist_spotify_id: spotify_id ,
105- inserted_at: NaiveDateTime . utc_now ( ) |> NaiveDateTime . truncate ( :second ) ,
106- updated_at: NaiveDateTime . utc_now ( ) |> NaiveDateTime . truncate ( :second )
107- }
108- ] ,
109- on_conflict: :nothing
110- )
111- end
112-
113- # Notify parent process of first track
114- if not Process . get ( @ notification_key ) do
115- Process . put ( @ notification_key , true )
116- send ( parent , { :first_track_saved , ref , spotify_id } )
117- end
118-
119- saved_track
120- end )
121-
122- # Try to notify of first track - only the first message will be received
123- try do
124- send ( notification_agent , :notified )
125- send ( parent , { :first_track_saved , ref , spotify_id } )
126- catch
127- # Process already notified
128- :error , :badarg -> :ok
85+ Logger . debug ( "Processing track" , title: track [ "name" ] , uri: track [ "uri" ] )
86+
87+ case Repo . transaction ( fn ->
88+ track_entry = % Track {
89+ uri: track [ "uri" ] ,
90+ title: track [ "name" ] ,
91+ artists: Enum . map ( track [ "artists" ] , & & 1 [ "name" ] ) ,
92+ popularity: track [ "popularity" ] ,
93+ album: track [ "album" ] [ "name" ]
94+ }
95+
96+ # First ensure the track exists
97+ { :ok , saved_track } = Repo . insert ( track_entry , on_conflict: :nothing )
98+ Logger . debug ( "Track saved" , uri: saved_track . uri )
99+
100+ # Then create the association only if track was saved
101+ if saved_track . uri do
102+ { 1 , _ } =
103+ Repo . insert_all (
104+ "playlist_tracks" ,
105+ [
106+ % {
107+ track_uri: saved_track . uri ,
108+ playlist_spotify_id: spotify_id ,
109+ inserted_at:
110+ NaiveDateTime . utc_now ( ) |> NaiveDateTime . truncate ( :second ) ,
111+ updated_at:
112+ NaiveDateTime . utc_now ( ) |> NaiveDateTime . truncate ( :second )
113+ }
114+ ] ,
115+ on_conflict: :nothing
116+ )
117+
118+ Logger . debug ( "Playlist-track association created" ,
119+ track_uri: saved_track . uri ,
120+ playlist_id: spotify_id
121+ )
122+ end
123+
124+ # Notify parent process of first track
125+ notified = Process . get ( @ notification_key )
126+
127+ Logger . debug ( "Checking notification status" ,
128+ already_notified: notified ,
129+ notification_key: @ notification_key
130+ )
131+
132+ if notified == nil do
133+ Process . put ( @ notification_key , true )
134+ Logger . debug ( "Sending first track notification" , ref: ref )
135+ send ( parent , { :first_track_saved , ref , spotify_id } )
136+ end
137+
138+ saved_track
139+ end ) do
140+ { :ok , saved_track } ->
141+ Logger . debug ( "Transaction completed successfully" , track_uri: saved_track . uri )
142+ :ok
143+
144+ { :error , reason } ->
145+ Logger . warning ( "Transaction failed" , error: inspect ( reason ) )
146+ :ok
129147 end
130-
131- result
132148 end
133149
134150 Task . start ( fn ->
135151 case Pling.Services.Spotify . stream_playlist ( spotify_id , callback ) do
136152 :ok ->
153+ Logger . debug ( "Playlist stream completed successfully" , spotify_id: spotify_id )
137154 :ok
138155
139156 { :error , reason } ->
@@ -145,19 +162,16 @@ defmodule Pling.Playlists.MusicLibrary do
145162
146163 receive do
147164 { :first_track_saved , ^ ref , playlist_id } ->
165+ Logger . debug ( "Received first track notification" , playlist_id: playlist_id )
166+
148167 case Repo . get ( Playlist , playlist_id ) do
149168 nil -> { :error , :playlist_fetch_failed }
150169 playlist -> { :ok , :first_track_saved , playlist }
151170 end
152171
153172 { :playlist_error , ^ ref , reason } ->
173+ Logger . debug ( "Received playlist error" , error: inspect ( reason ) )
154174 { :error , reason }
155- after
156- timeout ->
157- case Repo . get ( Playlist , spotify_id ) do
158- nil -> { :error , :playlist_fetch_timeout }
159- playlist -> { :ok , :timeout , playlist }
160- end
161175 end
162176
163177 playlist ->
0 commit comments