diff --git a/beets/autotag/mb.py b/beets/autotag/mb.py index a7553b1b1..30a8d07d2 100644 --- a/beets/autotag/mb.py +++ b/beets/autotag/mb.py @@ -20,10 +20,12 @@ syntax, and other uninteresting parts of using musicbrainz2. The principal interface is the function `match_album`. """ +from __future__ import with_statement # for Python 2.5 import re import time import datetime import musicbrainz2.webservice as mbws +from threading import Lock class ServerBusyError(Exception): pass @@ -34,6 +36,7 @@ class ServerBusyError(Exception): pass MAX_QUERY_RETRY = 8 QUERY_WAIT_TIME = 1.0 last_query_time = 0.0 +mb_lock = Lock() def _query_wrap(fun, *args, **kwargs): """Wait until at least `QUERY_WAIT_TIME` seconds have passed since the last invocation of this function. Then call @@ -41,25 +44,26 @@ def _query_wrap(fun, *args, **kwargs): then try again. Tries up to `MAX_QUERY_RETRY` times before giving up. """ - global last_query_time - for i in range(MAX_QUERY_RETRY): - since_last_query = time.time() - last_query_time - if since_last_query < QUERY_WAIT_TIME: - time.sleep(QUERY_WAIT_TIME - since_last_query) - last_query_time = time.time() - try: - # Try the function. - res = fun(*args, **kwargs) - except mbws.WebServiceError, e: - # Server busy. Retry. - if 'Error 503' not in str(e.reason): - # This is not the error we're looking for. - raise - else: - # Success. Return the result. - return res - # Gave up. - raise ServerBusyError() + with mb_lock: + global last_query_time + for i in range(MAX_QUERY_RETRY): + since_last_query = time.time() - last_query_time + if since_last_query < QUERY_WAIT_TIME: + time.sleep(QUERY_WAIT_TIME - since_last_query) + last_query_time = time.time() + try: + # Try the function. + res = fun(*args, **kwargs) + except mbws.WebServiceError, e: + # Server busy. Retry. + if 'Error 503' not in str(e.reason): + # This is not the error we're looking for. + raise + else: + # Success. Return the result. + return res + # Gave up. + raise ServerBusyError() # FIXME exponential backoff? def _lucene_escape(text):