fix(open-api): schedules 的缓存/Redis 分支补齐 voteCount,消除分支间字段不一致
上一步只给数据库分支补了 voteCount,但实测该接口通常命中缓存分支, 导致 voteCount 依然缺失。抽出 buildVoteCountMap() 供三条分支共用, 保证无论缓存命中与否,输出结构一致。
This commit is contained in:
@@ -21,6 +21,32 @@ import {
|
|||||||
type VisibilitySettingsLike
|
type VisibilitySettingsLike
|
||||||
} from '~~/server/utils/schedule-visibility'
|
} from '~~/server/utils/schedule-visibility'
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 批量统计歌曲票数。
|
||||||
|
*
|
||||||
|
* 该接口有缓存分支和数据库分支两条路径,此前字段互不一致
|
||||||
|
* (序列号只在缓存分支有、票数只在数据库分支有)。统一由本函数提供票数,
|
||||||
|
* 保证把缓存开关、Redis 开关怎么组合,输出结构都一致。
|
||||||
|
*/
|
||||||
|
async function buildVoteCountMap(songIds: number[]): Promise<Map<number, number>> {
|
||||||
|
const map = new Map<number, number>()
|
||||||
|
if (songIds.length === 0) return map
|
||||||
|
|
||||||
|
const rows = await db
|
||||||
|
.select({
|
||||||
|
songId: votes.songId,
|
||||||
|
count: sql`count(*)`
|
||||||
|
})
|
||||||
|
.from(votes)
|
||||||
|
.where(inArray(votes.songId, songIds))
|
||||||
|
.groupBy(votes.songId)
|
||||||
|
|
||||||
|
rows.forEach((row) => {
|
||||||
|
map.set(row.songId, Number(row.count))
|
||||||
|
})
|
||||||
|
return map
|
||||||
|
}
|
||||||
|
|
||||||
export default defineEventHandler(async (event) => {
|
export default defineEventHandler(async (event) => {
|
||||||
try {
|
try {
|
||||||
const query = getQuery(event)
|
const query = getQuery(event)
|
||||||
@@ -85,6 +111,10 @@ export default defineEventHandler(async (event) => {
|
|||||||
}
|
}
|
||||||
filteredSchedules = applyVisibilityFilter(filteredSchedules)
|
filteredSchedules = applyVisibilityFilter(filteredSchedules)
|
||||||
|
|
||||||
|
const voteCounts = await buildVoteCountMap(
|
||||||
|
filteredSchedules.map((s: any) => s.song?.id).filter(Boolean)
|
||||||
|
)
|
||||||
|
|
||||||
// 转换为开放API格式
|
// 转换为开放API格式
|
||||||
const result = {
|
const result = {
|
||||||
success: true,
|
success: true,
|
||||||
@@ -101,7 +131,8 @@ export default defineEventHandler(async (event) => {
|
|||||||
semester: schedule.song.semester,
|
semester: schedule.song.semester,
|
||||||
cover: schedule.song.cover,
|
cover: schedule.song.cover,
|
||||||
musicPlatform: schedule.song.musicPlatform,
|
musicPlatform: schedule.song.musicPlatform,
|
||||||
musicId: schedule.song.musicId
|
musicId: schedule.song.musicId,
|
||||||
|
voteCount: voteCounts.get(schedule.song.id) || 0
|
||||||
},
|
},
|
||||||
playTime: schedule.playTime
|
playTime: schedule.playTime
|
||||||
? {
|
? {
|
||||||
@@ -141,6 +172,11 @@ export default defineEventHandler(async (event) => {
|
|||||||
|
|
||||||
if (redisData) {
|
if (redisData) {
|
||||||
const filteredRedisData = applyVisibilityFilter(redisData)
|
const filteredRedisData = applyVisibilityFilter(redisData)
|
||||||
|
|
||||||
|
const voteCounts = await buildVoteCountMap(
|
||||||
|
filteredRedisData.map((s: any) => s.song?.id).filter(Boolean)
|
||||||
|
)
|
||||||
|
|
||||||
// 转换为开放API格式
|
// 转换为开放API格式
|
||||||
const result = {
|
const result = {
|
||||||
success: true,
|
success: true,
|
||||||
@@ -157,7 +193,8 @@ export default defineEventHandler(async (event) => {
|
|||||||
semester: schedule.song.semester,
|
semester: schedule.song.semester,
|
||||||
cover: schedule.song.cover,
|
cover: schedule.song.cover,
|
||||||
musicPlatform: schedule.song.musicPlatform,
|
musicPlatform: schedule.song.musicPlatform,
|
||||||
musicId: schedule.song.musicId
|
musicId: schedule.song.musicId,
|
||||||
|
voteCount: voteCounts.get(schedule.song.id) || 0
|
||||||
},
|
},
|
||||||
playTime: schedule.playTime
|
playTime: schedule.playTime
|
||||||
? {
|
? {
|
||||||
@@ -322,24 +359,7 @@ export default defineEventHandler(async (event) => {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
// 统计每首歌的票数。
|
const voteCountsMap = await buildVoteCountMap(songIds)
|
||||||
// 该接口的缓存分支(本文件上方)会返回 voteCount,数据库分支此前漏了,
|
|
||||||
// 导致两条分支字段不一致,这里补齐。
|
|
||||||
const voteCountsMap = new Map<number, number>()
|
|
||||||
if (songIds.length > 0) {
|
|
||||||
const voteCountsData = await db
|
|
||||||
.select({
|
|
||||||
songId: votes.songId,
|
|
||||||
count: sql`count(*)`
|
|
||||||
})
|
|
||||||
.from(votes)
|
|
||||||
.where(inArray(votes.songId, songIds))
|
|
||||||
.groupBy(votes.songId)
|
|
||||||
|
|
||||||
voteCountsData.forEach((row) => {
|
|
||||||
voteCountsMap.set(row.songId, Number(row.count))
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
// 格式化数据
|
// 格式化数据
|
||||||
const formattedSchedules = schedulesData.map((schedule) => {
|
const formattedSchedules = schedulesData.map((schedule) => {
|
||||||
|
|||||||
Reference in New Issue
Block a user