@ -14,6 +14,7 @@ from common.database import DBManager, query
from common . googleapis import GoogleAPIClient
from common . googleapis import GoogleAPIClient
PlaylistConfig = namedtuple ( " Playlist " , [ " tags " , " first_event_id " , " last_event_id " ] )
PlaylistEntry = namedtuple ( " PlaylistEntry " , [ " entry_id " , " video_id " ] )
PlaylistEntry = namedtuple ( " PlaylistEntry " , [ " entry_id " , " video_id " ] )
@ -61,13 +62,13 @@ class PlaylistManager(object):
logging . debug ( f " Found { len ( videos ) } eligible videos " )
logging . debug ( f " Found { len ( videos ) } eligible videos " )
logging . info ( " Getting dynamic playlists " )
logging . info ( " Getting dynamic playlists " )
playlist _tag s = self . get_playlist_ tags ( )
playlist s = self . get_playlist_ config ( )
logging . debug ( f " Found { len ( playlist _tag s) } playlists " )
logging . debug ( f " Found { len ( playlist s) } playlists " )
# start all workers
# start all workers
workers = { }
workers = { }
for playlist_id , tags in playlist_tag s. items ( ) :
for playlist_id , playlist_config in playlist s. items ( ) :
workers [ playlist_id ] = gevent . spawn ( self . update_playlist , playlist_id , tags , videos )
workers [ playlist_id ] = gevent . spawn ( self . update_playlist , playlist_id , playlist_config , videos )
# check each one for success, reset on failure
# check each one for success, reset on failure
for playlist_id , worker in workers . items ( ) :
for playlist_id , worker in workers . items ( ) :
@ -90,26 +91,32 @@ class PlaylistManager(object):
self . dbmanager . put_conn ( conn )
self . dbmanager . put_conn ( conn )
return { video . video_id : video for video in videos }
return { video . video_id : video for video in videos }
def get_playlist_ tags ( self ) :
def get_playlist_ config ( self ) :
conn = self . dbmanager . get_conn ( )
conn = self . dbmanager . get_conn ( )
playlist_tags = {
playlists = {
row . playlist_id : [ tag . lower ( ) for tag in row . tags ]
row . playlist_id : PlaylistConfig (
for row in query ( conn , " SELECT playlist_id, tags FROM playlists " )
[ tag . lower ( ) for tag in row . tags ] ,
row . first_event_id ,
row . last_event_id ,
) for row in query ( conn , " SELECT playlist_id, tags, first_event_id, last_event_id FROM playlists " )
}
}
self . dbmanager . put_conn ( conn )
self . dbmanager . put_conn ( conn )
duplicates = set ( playlist_tags ) & set ( self . static_playlist_tags )
duplicates = set ( playlist s) & set ( self . static_playlist s)
if duplicates :
if duplicates :
raise ValueError (
raise ValueError (
" Some playlists are listed in both static and dynamic playlist sources: {} " . format ( " , " . join ( duplicates ) )
" Some playlists are listed in both static and dynamic playlist sources: {} " . format ( " , " . join ( duplicates ) )
)
)
playlist_tags . update ( self . static_playlist_tags )
playlists . update ( {
return playlist_tags
id : PlaylistConfig ( tags , None , None )
for id , tags in self . static_playlists . items ( )
} )
return playlists
def update_playlist ( self , playlist_id , tags , videos ) :
def update_playlist ( self , playlist_id , playlist_config , videos ) :
# Filter the video list for videos with matching tags
# Filter the video list for videos with matching tags
matching = [
matching = [
video for video in videos . values ( )
video for video in videos . values ( )
if all ( tag in [ t . lower ( ) for t in video . tags ] for tag in tags)
if all ( tag in [ t . lower ( ) for t in video . tags ] for tag in playlist_config. tags)
]
]
logging . debug ( f " Found { len ( matching ) } matching videos for playlist { playlist_id } " )
logging . debug ( f " Found { len ( matching ) } matching videos for playlist { playlist_id } " )
# If we have nothing to add, short circuit without doing any API calls to save quota.
# If we have nothing to add, short circuit without doing any API calls to save quota.