First draft of multi-task in a single session. (#622)

This commit is contained in:
Marc-Andre Ferland
2022-12-08 00:42:46 -05:00
committed by GitHub
parent f8dee7e25f
commit ba2c966329
7 changed files with 179 additions and 95 deletions

View File

@ -383,7 +383,7 @@
throw new Error('exception is not an Error or a string.')
}
}
const res = await fetch('/image/stop?session_id=' + SD.sessionId)
const res = await fetch('/image/stop?task=' + this.id)
if (!res.ok) {
console.log('Stop response:', res)
throw new Error(res.statusText)
@ -556,13 +556,19 @@
case TaskStatus.pending:
case TaskStatus.waiting:
// Wait for server status to include this task.
await waitUntil(async () => ((task.#id && serverState.task === task.#id)
|| await Promise.resolve(callback?.call(task))
|| signal?.aborted),
await waitUntil(
async () => {
if (task.#id && typeof serverState.tasks === 'object' && Object.keys(serverState.tasks).includes(String(task.#id))) {
return true
}
if (await Promise.resolve(callback?.call(task)) || signal?.aborted) {
return true
}
},
TASK_STATE_SERVER_UPDATE_DELAY,
timeout,
)
if (this.#id && serverState.task === this.#id) {
if (this.#id && typeof serverState.tasks === 'object' && Object.keys(serverState.tasks).includes(String(task.#id))) {
this._setStatus(TaskStatus.waiting)
}
if (await Promise.resolve(callback?.call(this)) || signal?.aborted) {
@ -572,19 +578,20 @@
return true
}
// Wait for task to start on server.
await waitUntil(async () => (serverState.task !== task.#id || serverState.session !== 'pending'
|| await Promise.resolve(callback?.call(task))
|| signal?.aborted),
await waitUntil(
async () => {
if (typeof serverState.tasks !== 'object' || serverState.tasks[String(task.#id)] !== 'pending') {
return true
}
if (await Promise.resolve(callback?.call(task)) || signal?.aborted) {
return true
}
},
TASK_STATE_SERVER_UPDATE_DELAY,
timeout,
)
if (serverState.task === this.#id
&& (
serverState.session === 'running'
|| serverState.session === 'buffer'
|| serverState.session === 'completed'
)
) {
const state = (typeof serverState.tasks === 'object' ? serverState.tasks[String(task.#id)] : undefined)
if (state === 'running' || state === 'buffer' || state === 'completed') {
this._setStatus(TaskStatus.processing)
}
if (await Promise.resolve(callback?.call(task)) || signal?.aborted) {
@ -594,9 +601,15 @@
return true
}
case TaskStatus.processing:
await waitUntil(async () => (serverState.task !== task.#id || serverState.session !== 'running'
|| await Promise.resolve(callback?.call(task))
|| signal?.aborted),
await waitUntil(
async () => {
if (typeof serverState.tasks !== 'object' || serverState.tasks[String(task.#id)] !== 'running') {
return true
}
if (await Promise.resolve(callback?.call(task)) || signal?.aborted) {
return true
}
},
TASK_STATE_SERVER_UPDATE_DELAY,
timeout,
)
@ -882,7 +895,8 @@
throw e
}
// Update class status and callback.
switch(serverState.session) {
const taskState = (typeof serverState.tasks === 'object' ? serverState.tasks[String(this.id)] : undefined)
switch(taskState) {
case 'pending': // Session has pending tasks.
console.error('Server %o render request %o is still waiting.', serverState, renderRequest)
//Only update status if not already set by waitUntil
@ -915,7 +929,7 @@
return false
default:
if (!progressCallback) {
const err = new Error('Unexpected server task state: ' + serverState.session || 'Undefined')
const err = new Error('Unexpected server task state: ' + taskState || 'Undefined')
this.abort(err)
throw err
}
@ -1065,6 +1079,14 @@
return models
}
function getServerCapacity() {
let activeDevicesCount = Object.keys(serverState?.devices?.active || {}).length
if (window.document.visibilityState === 'hidden') {
activeDevicesCount = 1 + activeDevicesCount
}
return activeDevicesCount
}
function continueTasks() {
if (typeof navigator?.scheduling?.isInputPending === 'function') {
const inputPendingOptions = {
@ -1077,13 +1099,17 @@
return asyncDelay(CONCURRENT_TASK_INTERVAL)
}
}
const serverCapacity = getServerCapacity()
if (task_queue.size <= 0 && concurrent_generators.size <= 0) {
eventSource.fireEvent(EVENT_IDLE, {})
eventSource.fireEvent(EVENT_IDLE, {capacity: serverCapacity, idle: true})
// Calling idle could result in task being added to queue.
if (task_queue.size <= 0 && concurrent_generators.size <= 0) {
return asyncDelay(IDLE_COOLDOWN)
}
}
if (task_queue.size < serverCapacity) {
eventSource.fireEvent(EVENT_IDLE, {capacity: serverCapacity - task_queue.size})
}
const completedTasks = []
for (let [generator, promise] of concurrent_generators.entries()) {
if (promise.isPending) {
@ -1122,7 +1148,6 @@
concurrent_generators.set(generator, promise)
}
const serverCapacity = 2
for (let [task, generator] of task_queue.entries()) {
const cTsk = completedTasks.find((item) => item.generator === generator)
if (cTsk?.promise?.rejectReason || task.hasFailed) {
@ -1211,6 +1236,7 @@
removeEventListener: (...args) => eventSource.removeEventListener(...args),
isServerAvailable,
getServerCapacity,
getSystemInfo,
getDevices,
@ -1228,6 +1254,14 @@
configurable: false,
get: () => serverState,
},
isAvailable: {
configurable: false,
get: () => isServerAvailable(),
},
serverCapacity: {
configurable: false,
get: () => getServerCapacity(),
},
sessionId: {
configurable: false,
get: () => sessionId,