playlist manager: serialize insert requests

We've seen cases where videos are not inserted even though the API call succeeded.
Our suspicion is that two concurrent insert calls for the same video are causing a race.

We try to avoid this by putting a lock around insert calls
pull/288/head
Mike Lang 3 years ago
parent a942af9cb4
commit 63d8b1d504

@ -185,6 +185,9 @@ class PlaylistManager(object):
class YoutubeAPI(object): class YoutubeAPI(object):
def __init__(self, client): def __init__(self, client):
self.client = client self.client = client
# We've observed failures in the playlist API when doing concurrent calls for the same video.
# We could maybe have a per-video lock but this is easier.
self.insert_lock = gevent.lock.RLock()
def insert_into_playlist(self, playlist, video_id, index): def insert_into_playlist(self, playlist, video_id, index):
json = { json = {
@ -197,15 +200,16 @@ class YoutubeAPI(object):
"position": index, "position": index,
}, },
} }
resp = self.client.request("POST", "https://www.googleapis.com/youtube/v3/playlistItems", with self.insert_lock:
params={"part": "snippet"}, resp = self.client.request("POST", "https://www.googleapis.com/youtube/v3/playlistItems",
json=json, params={"part": "snippet"},
metric_name="playlist_insert", json=json,
) metric_name="playlist_insert",
if not resp.ok: )
raise Exception("Failed to insert {video_id} at index {index} of {playlist} with {resp.status_code}: {resp.content}".format( if not resp.ok:
playlist=playlist, video_id=video_id, index=index, resp=resp, raise Exception("Failed to insert {video_id} at index {index} of {playlist} with {resp.status_code}: {resp.content}".format(
)) playlist=playlist, video_id=video_id, index=index, resp=resp,
))
def list_playlist(self, playlist): def list_playlist(self, playlist):
"""Fetches the first page of playlist contents and returns a ListQuery object. """Fetches the first page of playlist contents and returns a ListQuery object.

Loading…
Cancel
Save