fix cloud ordering

This commit is contained in:
Richard Yu
2025-12-03 23:53:04 -08:00
parent b9537d352a
commit 2aa2be6d90
3 changed files with 37 additions and 28 deletions

View File

@@ -38,7 +38,7 @@ async function fetchJobsRaw(
offset: number = 0 offset: number = 0
): Promise<FetchJobsRawResult> { ): Promise<FetchJobsRawResult> {
const statusParam = statuses.join(',') const statusParam = statuses.join(',')
const url = `/jobs?status=${statusParam}&limit=${maxItems}&offset=${offset}&sort_by=create_time&order=desc` const url = `/jobs?status=${statusParam}&limit=${maxItems}&offset=${offset}`
try { try {
const res = await fetchApi(url) const res = await fetchApi(url)
if (!res.ok) { if (!res.ok) {
@@ -53,58 +53,67 @@ async function fetchJobsRaw(
} }
} }
// Large offset to ensure running/pending jobs sort above history
const QUEUE_PRIORITY_BASE = 1_000_000
/** /**
* Assigns synthetic priority to jobs based on sorted position. * Assigns synthetic priority to jobs.
* Priority = total - offset - index (highest = newest)
* Only assigns if job doesn't already have a server-provided priority. * Only assigns if job doesn't already have a server-provided priority.
*/ */
function assignSyntheticPriority( function assignPriority(
jobs: RawJobListItem[], jobs: RawJobListItem[],
total: number, basePriority: number
offset: number
): JobListItem[] { ): JobListItem[] {
return jobs.map((job, index) => ({ return jobs.map((job, index) => ({
...job, ...job,
priority: job.priority ?? total - offset - index priority: job.priority ?? basePriority - index
})) }))
} }
/** /**
* Fetches history (completed jobs) * Fetches history (completed jobs)
* Returns jobs sorted by create_time descending (newest first) via API * Assigns synthetic priority starting from total (lower than queue jobs).
* Assigns synthetic priority based on position if not provided by server.
*/ */
export async function fetchHistory( export async function fetchHistory(
fetchApi: (url: string) => Promise<Response>, fetchApi: (url: string) => Promise<Response>,
maxItems: number = 200, maxItems: number = 200,
offset: number = 0 offset: number = 0
): Promise<JobListItem[]> { ): Promise<JobListItem[]> {
const { const { jobs, total } = await fetchJobsRaw(
jobs, fetchApi,
total, ['completed'],
offset: responseOffset maxItems,
} = await fetchJobsRaw(fetchApi, ['completed'], maxItems, offset) offset
return assignSyntheticPriority(jobs, total, responseOffset) )
// History gets priority based on total count (lower than queue)
return assignPriority(jobs, total - offset)
} }
/** /**
* Fetches queue (in_progress + pending jobs) * Fetches queue (in_progress + pending jobs)
* Assigns synthetic priority based on position if not provided by server. * Pending jobs get highest priority, then running jobs.
*/ */
export async function fetchQueue( export async function fetchQueue(
fetchApi: (url: string) => Promise<Response> fetchApi: (url: string) => Promise<Response>
): Promise<{ Running: JobListItem[]; Pending: JobListItem[] }> { ): Promise<{ Running: JobListItem[]; Pending: JobListItem[] }> {
const { jobs, total, offset } = await fetchJobsRaw( const { jobs } = await fetchJobsRaw(
fetchApi, fetchApi,
['in_progress', 'pending'], ['in_progress', 'pending'],
200, 200,
0 0
) )
const jobsWithPriority = assignSyntheticPriority(jobs, total, offset)
const running = jobs.filter((j) => j.status === 'in_progress')
const pending = jobs.filter((j) => j.status === 'pending')
// Pending gets highest priority, then running
// Both are above any history job due to QUEUE_PRIORITY_BASE
return { return {
Running: jobsWithPriority.filter((j) => j.status === 'in_progress'), Running: assignPriority(running, QUEUE_PRIORITY_BASE + running.length),
Pending: jobsWithPriority.filter((j) => j.status === 'pending') Pending: assignPriority(
pending,
QUEUE_PRIORITY_BASE + running.length + pending.length
)
} }
} }

View File

@@ -332,13 +332,6 @@ export class TaskItemImpl {
return undefined return undefined
} }
/**
* Server-provided creation time in milliseconds
*/
get createTime(): number {
return this.job.create_time
}
/** /**
* Execution messages - not available in Jobs API * Execution messages - not available in Jobs API
*/ */
@@ -346,6 +339,13 @@ export class TaskItemImpl {
return [] return []
} }
/**
* Server-provided creation time in milliseconds
*/
get createTime(): number {
return this.job.create_time
}
/** /**
* Whether the job was interrupted/cancelled * Whether the job was interrupted/cancelled
*/ */

View File

@@ -332,7 +332,7 @@ describe('useJobList', () => {
expect(vi.getTimerCount()).toBe(0) expect(vi.getTimerCount()).toBe(0)
}) })
it('sorts all tasks by queue index descending', async () => { it('sorts all tasks by priority descending', async () => {
queueStoreMock.pendingTasks = [ queueStoreMock.pendingTasks = [
createTask({ promptId: 'p', queueIndex: 1, mockState: 'pending' }) createTask({ promptId: 'p', queueIndex: 1, mockState: 'pending' })
] ]