Skip to content

Commit

Permalink
fix(spotify): detect rate limiting (#4253)
Browse files Browse the repository at this point in the history
  • Loading branch information
dvikan authored Sep 3, 2024
1 parent 3dc8b65 commit 293d04f
Show file tree
Hide file tree
Showing 2 changed files with 47 additions and 25 deletions.
68 changes: 45 additions & 23 deletions bridges/SpotifyBridge.php
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,10 @@ class SpotifyBridge extends BridgeAbstract
'name' => 'Spotify URIs',
'type' => 'text',
'required' => true,
'exampleValue' => 'spotify:artist:4lianjyuR1tqf6oUX8kjrZ [,spotify:playlist:37i9dQZF1DXcBWIGoYBM5M,spotify:show:6ShFMYxeDNMo15COLObDvC]',

// spotify:playlist:37i9dQZF1DXcBWIGoYBM5M
// spotify:show:6ShFMYxeDNMo15COLObDvC
'exampleValue' => 'spotify:artist:4lianjyuR1tqf6oUX8kjrZ',
],
'albumtype' => [
'name' => 'Album type',
Expand Down Expand Up @@ -93,6 +96,25 @@ class SpotifyBridge extends BridgeAbstract
private $token = '';

public function collectData()
{
/**
* https://developer.spotify.com/documentation/web-api/concepts/rate-limits
*/
$cacheKey = 'spotify_rate_limit';

try {
$this->collectDataInternal();
} catch (HttpException $e) {
if ($e->getCode() === 429) {
$retryAfter = $e->response->getHeader('Retry-After') ?? (60 * 5);
$this->cache->set($cacheKey, true, $retryAfter);
throw new RateLimitException(sprintf('Rate limited by spotify, try again in %s seconds', $retryAfter));
}
throw $e;
}
}

private function collectDataInternal()
{
$this->fetchAccessToken();

Expand Down Expand Up @@ -125,6 +147,27 @@ public function collectData()
}
}

private function fetchAccessToken()
{
$cacheKey = sprintf('SpotifyBridge:%s:%s', $this->getInput('clientid'), $this->getInput('clientsecret'));

$token = $this->cache->get($cacheKey);
if ($token) {
$this->token = $token;
} else {
$basicAuth = base64_encode(sprintf('%s:%s', $this->getInput('clientid'), $this->getInput('clientsecret')));
$json = getContents('https://accounts.spotify.com/api/token', [
"Authorization: Basic $basicAuth",
], [
CURLOPT_POSTFIELDS => 'grant_type=client_credentials',
]);
$data = Json::decode($json);
$this->token = $data['access_token'];

$this->cache->set($cacheKey, $this->token, 3600);
}
}

private function getEntriesFromQuery()
{
$entries = [];
Expand Down Expand Up @@ -276,27 +319,6 @@ private function getDate($entry)
return DateTime::createFromFormat('Y-m-d', $date)->getTimestamp();
}

private function fetchAccessToken()
{
$cacheKey = sprintf('SpotifyBridge:%s:%s', $this->getInput('clientid'), $this->getInput('clientsecret'));

$token = $this->cache->get($cacheKey);
if ($token) {
$this->token = $token;
} else {
$basicAuth = base64_encode(sprintf('%s:%s', $this->getInput('clientid'), $this->getInput('clientsecret')));
$json = getContents('https://accounts.spotify.com/api/token', [
"Authorization: Basic $basicAuth",
], [
CURLOPT_POSTFIELDS => 'grant_type=client_credentials',
]);
$data = Json::decode($json);
$this->token = $data['access_token'];

$this->cache->set($cacheKey, $this->token, 3600);
}
}

public function getURI()
{
if (empty($this->uri)) {
Expand Down Expand Up @@ -346,4 +368,4 @@ public function getIcon()
{
return 'https://www.scdn.co/i/_global/favicon.png';
}
}
}
4 changes: 2 additions & 2 deletions middlewares/CacheMiddleware.php
Original file line number Diff line number Diff line change
Expand Up @@ -44,8 +44,8 @@ public function __invoke(Request $request, $next): Response
$response = $next($request);

if (in_array($response->getCode(), [403, 429, 500, 503])) {
// Cache these responses for about ~20 mins on average
$this->cache->set($cacheKey, $response, 60 * 15 + rand(1, 60 * 10));
// Cache these responses for about ~10 mins on average
$this->cache->set($cacheKey, $response, 60 * 5 + rand(1, 60 * 10));
}

// For 1% of requests, prune cache
Expand Down

0 comments on commit 293d04f

Please sign in to comment.