frontend/benchmarks/queue-sync.test.js
Rama main · réplica de lectura del repositorio original.
// Opt-in timing experiment, not a wall-clock assertion in CI.
import { execFileSync } from 'node:child_process'
import { performance } from 'node:perf_hooks'
import { env } from 'node:process'
import { fileURLToPath, pathToFileURL } from 'node:url'
import { dirname, join, resolve } from 'node:path'
import { writeFileSync, unlinkSync } from 'node:fs'
import { describe, expect, it, vi } from 'vitest'
const fixture = vi.hoisted(() => ({ jobs: [] }))
vi.mock('/src/model/api', () => ({
default: {
getQueue: async () => ({ data: fixture.jobs }),
onMessage: () => {},
downloadFileURL: (file) => `/media/${file}`,
},
}))
vi.mock('/src/model/settings', () => ({
useSettingsManager: () => ({ settings: { value: {} } }),
}))
function generatedJobs(count) {
return Array.from({ length: count }, (_, i) => ({
song: {
song_id: `generated:${i}`,
name: `Track ${i}`,
artists: ['Generated artist'],
},
status: i % 5 === 0 ? 'done' : i % 5 === 1 ? 'downloading' : 'queued',
progress: i % 5 === 0 ? 100 : i % 5 === 1 ? 20 : 0,
filename: i % 5 === 0 ? `generated/${i}.mp3` : null,
provider: 'youtube-music',
position: i + 1,
message: '',
}))
}
function snapshot(model) {
return model.useProgressTracker().downloadQueue.value.map((item) => ({
key: item.key,
state: item.state,
progress: item.progress,
provider: item.provider,
message: item.message,
position: item.position,
filename: item.filename,
url: item.web_download_url,
}))
}
function median(samples) {
return [...samples].sort((a, b) => a - b)[Math.floor(samples.length / 2)]
}
async function measure(load, count) {
vi.resetModules()
fixture.jobs = []
const model = await load()
await model.syncQueueFromServer()
fixture.jobs = generatedJobs(count)
const started = performance.now()
await model.syncQueueFromServer()
const initial = performance.now() - started
const tracker = model.useProgressTracker()
const unchanged = []
const changed = []
const versionBefore = tracker.queueVersion.value
for (let i = 0; i < 3; i++) {
const start = performance.now()
await model.syncQueueFromServer()
unchanged.push(performance.now() - start)
}
const unchangedNotifications = tracker.queueVersion.value - versionBefore
for (let i = 0; i < 3; i++) {
fixture.jobs = fixture.jobs.map((row, index) =>
index % 10 === 1 ? { ...row, progress: row.progress + 1 } : row
)
const start = performance.now()
await model.syncQueueFromServer()
changed.push(performance.now() - start)
}
vi.clearAllTimers()
return {
final: snapshot(model),
timing: {
initial_ms: initial,
unchanged_median_ms: median(unchanged),
changed_median_ms: median(changed),
unchanged_notifications: unchangedNotifications,
},
}
}
describe.skipIf(env.DOWNTIFY_QUEUE_BENCHMARK !== '1')(
'real queue synchronization benchmark',
() => {
it('compares generated snapshots with the public baseline', async () => {
vi.useFakeTimers({ toFake: ['setInterval', 'clearInterval'] })
const here = dirname(fileURLToPath(import.meta.url))
const ref =
env.DOWNTIFY_QUEUE_BASELINE_REF ||
'6d7bebf00d7e41c011645b9ebe1de004c9e31e74'
const baseline = execFileSync(
'git',
['show', `${ref}:frontend/src/model/download.js`],
{
cwd: resolve(here, '../..'),
encoding: 'utf8',
}
)
const temporary = join(here, `.queue-baseline-${process.pid}.js`)
writeFileSync(temporary, baseline)
try {
const results = []
for (const count of [250, 2000, 10000]) {
const old = await measure(
() => import(/* @vite-ignore */ pathToFileURL(temporary).href),
count
)
const current = await measure(
() => import('../src/model/download.js'),
count
)
expect(current.final).toEqual(old.final)
expect(current.timing.unchanged_notifications).toBe(0)
results.push({
rows: count,
baseline: old.timing,
current: current.timing,
})
}
const report = JSON.stringify({ ref, results }, null, 2)
if (env.DOWNTIFY_QUEUE_BENCHMARK_OUTPUT) {
writeFileSync(env.DOWNTIFY_QUEUE_BENCHMARK_OUTPUT, report + '\n')
}
console.log('QUEUE_SYNC_BENCHMARK ' + report)
} finally {
unlinkSync(temporary)
vi.clearAllTimers()
vi.useRealTimers()
}
}, 240000)
}
)