mirror of
https://github.com/20kaushik02/spotify-manager.git
synced 2026-01-25 14:14:06 +00:00
playlist data caching
This commit is contained in:
@@ -1,7 +1,7 @@
|
|||||||
import { createClient } from "redis";
|
import { createClient } from "redis";
|
||||||
|
|
||||||
import curriedLogger from "../utils/logger.ts";
|
|
||||||
import { sleep } from "../utils/flake.ts";
|
import { sleep } from "../utils/flake.ts";
|
||||||
|
import curriedLogger from "../utils/logger.ts";
|
||||||
const logger = curriedLogger(import.meta.filename);
|
const logger = curriedLogger(import.meta.filename);
|
||||||
|
|
||||||
if (!process.env["REDIS_URI"])
|
if (!process.env["REDIS_URI"])
|
||||||
|
|||||||
@@ -24,6 +24,8 @@ import myGraph from "../utils/graph.ts";
|
|||||||
import { parseSpotifyLink } from "../utils/spotifyUriTransformer.ts";
|
import { parseSpotifyLink } from "../utils/spotifyUriTransformer.ts";
|
||||||
// import { randomBool, sleep } from "../utils/flake.ts";
|
// import { randomBool, sleep } from "../utils/flake.ts";
|
||||||
|
|
||||||
|
import { redisClient } from "../config/redis.ts";
|
||||||
|
|
||||||
// load db models
|
// load db models
|
||||||
import Playlists from "../models/playlists.ts";
|
import Playlists from "../models/playlists.ts";
|
||||||
import Links from "../models/links.ts";
|
import Links from "../models/links.ts";
|
||||||
@@ -411,12 +413,12 @@ interface _GetPlaylistTracks {
|
|||||||
is_local: boolean;
|
is_local: boolean;
|
||||||
uri: string;
|
uri: string;
|
||||||
}[];
|
}[];
|
||||||
snapshot_id: string;
|
snapshotID: string;
|
||||||
}
|
}
|
||||||
const _getPlaylistTracks: (
|
const _getPlaylistTracks: (
|
||||||
opts: _GetPlaylistTracksArgs
|
opts: _GetPlaylistTracksArgs
|
||||||
) => Promise<_GetPlaylistTracks | null> = async ({ req, res, playlistID }) => {
|
) => Promise<_GetPlaylistTracks | null> = async ({ req, res, playlistID }) => {
|
||||||
let initialFields = ["tracks(next,items(is_local,track(uri)))"];
|
let initialFields = ["snapshot_id,tracks(next,items(is_local,track(uri)))"];
|
||||||
let mainFields = ["next", "items(is_local,track(uri))"];
|
let mainFields = ["next", "items(is_local,track(uri))"];
|
||||||
|
|
||||||
const respData = await getPlaylistDetailsFirstPage({
|
const respData = await getPlaylistDetailsFirstPage({
|
||||||
@@ -427,13 +429,23 @@ const _getPlaylistTracks: (
|
|||||||
});
|
});
|
||||||
if (!respData) return null;
|
if (!respData) return null;
|
||||||
|
|
||||||
|
// check cache
|
||||||
|
const cachedSnapshotID = await redisClient.get(
|
||||||
|
"playlist_snapshot:" + playlistID
|
||||||
|
);
|
||||||
|
if (cachedSnapshotID === respData.snapshot_id) {
|
||||||
|
const cachedTracksData = (await redisClient.json.get(
|
||||||
|
"playlist_tracks:" + playlistID
|
||||||
|
)) as _GetPlaylistTracks["tracks"];
|
||||||
|
return { tracks: cachedTracksData, snapshotID: cachedSnapshotID };
|
||||||
|
}
|
||||||
|
|
||||||
const pl: _GetPlaylistTracks = {
|
const pl: _GetPlaylistTracks = {
|
||||||
tracks: [],
|
tracks: [],
|
||||||
snapshot_id: respData.snapshot_id,
|
snapshotID: respData.snapshot_id,
|
||||||
};
|
};
|
||||||
let nextURL;
|
let nextURL;
|
||||||
|
|
||||||
// varying fields again smh
|
|
||||||
if (respData.tracks.next) {
|
if (respData.tracks.next) {
|
||||||
nextURL = new URL(respData.tracks.next);
|
nextURL = new URL(respData.tracks.next);
|
||||||
nextURL.searchParams.set("fields", mainFields.join());
|
nextURL.searchParams.set("fields", mainFields.join());
|
||||||
@@ -467,6 +479,13 @@ const _getPlaylistTracks: (
|
|||||||
nextURL = nextData.next;
|
nextURL = nextData.next;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// cache new data
|
||||||
|
await redisClient.set(
|
||||||
|
"playlist_snapshot:" + playlistID,
|
||||||
|
respData.snapshot_id
|
||||||
|
);
|
||||||
|
await redisClient.json.set("playlist_tracks:" + playlistID, "$", pl.tracks);
|
||||||
|
|
||||||
return pl;
|
return pl;
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -662,7 +681,7 @@ const _pruneSingleLinkCore: (
|
|||||||
const toDelNum = indexes.length;
|
const toDelNum = indexes.length;
|
||||||
|
|
||||||
// remove in batches of 100 (from reverse, to preserve positions while modifying)
|
// remove in batches of 100 (from reverse, to preserve positions while modifying)
|
||||||
let currentSnapshot = toPlaylist.snapshot_id;
|
let currentSnapshot = toPlaylist.snapshotID;
|
||||||
while (indexes.length > 0) {
|
while (indexes.length > 0) {
|
||||||
const nextBatch = indexes.splice(Math.max(indexes.length - 100, 0), 100);
|
const nextBatch = indexes.splice(Math.max(indexes.length - 100, 0), 100);
|
||||||
const delResponse = await removePlaylistItems({
|
const delResponse = await removePlaylistItems({
|
||||||
|
|||||||
@@ -25,6 +25,11 @@ import type {
|
|||||||
UserObject,
|
UserObject,
|
||||||
} from "./objects.types.ts";
|
} from "./objects.types.ts";
|
||||||
|
|
||||||
|
// TODO: the data that actually gets retrieved from Spotify
|
||||||
|
// depends on the fields I pass as parameters to the API
|
||||||
|
// so... technically all fields are optional? but that's so
|
||||||
|
// horrible...
|
||||||
|
|
||||||
// GET method
|
// GET method
|
||||||
// Albums
|
// Albums
|
||||||
export type GetAlbum = AlbumObject;
|
export type GetAlbum = AlbumObject;
|
||||||
|
|||||||
Reference in New Issue
Block a user