import { SpotifyTrack } from "../types/spotify.ts"; import { getSpotifyAccessToken } from "../spotify-api.ts"; import { assert } from "jsr:@std/assert/assert"; // Simple in-memory cache for track objects by ID const trackCache = new Map(); /** * Inner function that performs the actual API call without retries. */ async function fetchSpotifyTrackById(trackId: string): Promise { const accessToken = await getSpotifyAccessToken(); const url = `https://api.spotify.com/v1/tracks/${trackId}?market=US`; const response = await fetch(url, { headers: { "Authorization": `Bearer ${accessToken}`, }, }); if (!response.ok) { throw new Error( `Failed to fetch track: ${response.status} ${await response.text()}`, ); } const track: SpotifyTrack = await response.json(); // Cache the result trackCache.set(trackId, track); return track; } /** * Fetches a Spotify track by its ID, with caching. * Returns the full SpotifyTrack object. */ export async function getSpotifyTrackById( trackId: string, ): Promise { // Check cache first if (trackCache.has(trackId)) { return trackCache.get(trackId)!; } const maxRetries = 10; let lastError: Error; for (let attempt = 1; attempt <= maxRetries; attempt++) { try { return await fetchSpotifyTrackById(trackId); } catch (error) { lastError = error as Error; if (attempt === maxRetries) { throw Error(`Attempt ${attempt}: ${lastError}`); } // Optional: add delay between retries await new Promise((resolve) => setTimeout(resolve, 1000 * attempt)); } } throw lastError!; } Deno.test("getSpotifyTrackById basic", async () => { // Example: Blinding Lights by The Weeknd const trackId = "2EqlS6tkEnglzr7tkKAAYD"; // First call (should fetch from API) const track1 = await getSpotifyTrackById(trackId); assert(track1.id === trackId); assert(typeof track1.name === "string"); assert(Array.isArray(track1.artists)); // Second call (should hit cache) const start = performance.now(); const track2 = await getSpotifyTrackById(trackId); const elapsed = performance.now() - start; console.log(track2); console.log("Second call elapsed:", elapsed, "ms"); assert(track2.id === trackId); assert(typeof track2.name === "string"); assert(Array.isArray(track2.artists)); assert(elapsed < 10, `Second call took too long: ${elapsed}ms`); });