fix(songs): repair generic song list route; make XML import upsert + delete stale while preserving s3File; unlink musicFiles for removed songs; auto-trigger matching
This commit is contained in:
parent
0073f8146d
commit
73b4bc6eb1
@ -34,21 +34,14 @@ router.get('/', async (req: Request, res: Response) => {
|
|||||||
const totalSongs = await Song.countDocuments(query);
|
const totalSongs = await Song.countDocuments(query);
|
||||||
const totalPages = Math.ceil(totalSongs / limit);
|
const totalPages = Math.ceil(totalSongs / limit);
|
||||||
|
|
||||||
// Get songs for this page in the exact playlist order
|
// Generic song listing (not playlist specific)
|
||||||
// Determine the slice of trackIds for the requested page
|
const songs = await Song.find(query)
|
||||||
const pageStart = (page - 1) * limit;
|
.skip(skip)
|
||||||
const pageEnd = Math.min(pageStart + limit, trackIds.length);
|
.limit(limit)
|
||||||
const pageTrackIds = trackIds.slice(pageStart, pageEnd);
|
|
||||||
|
|
||||||
const pageSongs = await Song.find({ id: { $in: pageTrackIds } })
|
|
||||||
.populate('s3File.musicFileId')
|
.populate('s3File.musicFileId')
|
||||||
.lean();
|
.lean();
|
||||||
// Order them to match pageTrackIds
|
|
||||||
const idToSong: Record<string, any> = {};
|
|
||||||
for (const s of pageSongs) idToSong[s.id] = s;
|
|
||||||
const songs = pageTrackIds.map(id => idToSong[id]).filter(Boolean);
|
|
||||||
|
|
||||||
console.log(`Found ${songs.length} songs (${totalSongs} total), ${songs.filter((s: any) => s.s3File?.hasS3File).length} with S3 files`);
|
console.log(`Found ${songs.length} songs (${totalSongs} total)`);
|
||||||
|
|
||||||
res.json({
|
res.json({
|
||||||
songs,
|
songs,
|
||||||
@ -240,17 +233,42 @@ router.get('/export', async (req: Request, res: Response) => {
|
|||||||
router.post('/batch', async (req: Request, res: Response) => {
|
router.post('/batch', async (req: Request, res: Response) => {
|
||||||
try {
|
try {
|
||||||
console.log('Received batch upload request');
|
console.log('Received batch upload request');
|
||||||
const songs = req.body;
|
const songs = Array.isArray(req.body) ? req.body : [];
|
||||||
console.log(`Attempting to save ${songs.length} songs`);
|
console.log(`Attempting to upsert ${songs.length} songs`);
|
||||||
|
|
||||||
// Delete all existing songs first
|
// Build bulk upserts preserving existing s3File field (we only $set provided fields)
|
||||||
await Song.deleteMany({});
|
const ops = songs.map((s: any) => ({
|
||||||
console.log('Cleared existing songs');
|
updateOne: {
|
||||||
|
filter: { id: s.id },
|
||||||
|
update: { $set: s },
|
||||||
|
upsert: true,
|
||||||
|
}
|
||||||
|
}));
|
||||||
|
|
||||||
// Insert new songs
|
if (ops.length > 0) {
|
||||||
const result = await Song.insertMany(songs);
|
await Song.bulkWrite(ops, { ordered: false });
|
||||||
console.log(`Successfully saved ${result.length} songs`);
|
}
|
||||||
res.status(201).json(result);
|
|
||||||
|
// Delete songs that are no longer present in the latest XML and unlink their music files
|
||||||
|
const incomingIds = new Set(songs.map((s: any) => s.id));
|
||||||
|
const existing = await Song.find({}, { id: 1 }).lean();
|
||||||
|
const staleIds = existing.map((e: any) => e.id).filter((id: string) => !incomingIds.has(id));
|
||||||
|
if (staleIds.length > 0) {
|
||||||
|
await Song.deleteMany({ id: { $in: staleIds } });
|
||||||
|
await MusicFile.updateMany({ songId: { $in: staleIds } }, { $unset: { songId: 1 } });
|
||||||
|
}
|
||||||
|
|
||||||
|
console.log('Songs upserted and stale songs removed');
|
||||||
|
|
||||||
|
// Optionally trigger a background matching pass to relink any unmatched files
|
||||||
|
try {
|
||||||
|
const { backgroundJobService } = await import('../services/backgroundJobService.js');
|
||||||
|
backgroundJobService.startJob({ type: 'song-matching', options: { minConfidence: 0.7 } });
|
||||||
|
} catch (e) {
|
||||||
|
console.warn('Could not trigger matching job after XML import:', e);
|
||||||
|
}
|
||||||
|
|
||||||
|
res.status(201).json({ upserted: songs.length });
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error('Error creating songs:', error);
|
console.error('Error creating songs:', error);
|
||||||
res.status(500).json({ message: 'Error creating songs', error });
|
res.status(500).json({ message: 'Error creating songs', error });
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user