From 1956441d520153144c47f4ff1f885dffc07548a0 Mon Sep 17 00:00:00 2001 From: Zaid Abdulla Date: Mon, 28 Sep 2020 12:47:15 -0700 Subject: [PATCH] Limit number of tasks in queue --- ui/components/summon-button.ts | 3 ++- ui/devices-page.ts | 26 +++++++++++------------- ui/drawer-component.ts | 2 +- ui/task-queue.ts | 37 ++++++++++++++++++++++++++++++---- 4 files changed, 48 insertions(+), 20 deletions(-) diff --git a/ui/components/summon-button.ts b/ui/components/summon-button.ts index 79a5566..0b66310 100644 --- a/ui/components/summon-button.ts +++ b/ui/components/summon-button.ts @@ -81,7 +81,8 @@ const component: ClosureComponent = (): Component => { store.fulfill(0, Date.now()); }) .catch((err) => { - throw err; + e.target.disabled = false; + notifications.push("error", err.message); }); }, }, diff --git a/ui/devices-page.ts b/ui/devices-page.ts index 3b7ddc5..ac06308 100644 --- a/ui/devices-page.ts +++ b/ui/devices-page.ts @@ -23,7 +23,7 @@ import config from "./config"; import indexTableComponent from "./index-table-component"; import filterComponent from "./filter-component"; import * as store from "./store"; -import * as taskQueue from "./task-queue"; +import { queueTask, stageDownload } from "./task-queue"; import * as notifications from "./notifications"; import { parse, stringify } from "../lib/common/expression-parser"; import { evaluate, extractParams } from "../lib/common/expression"; @@ -91,12 +91,11 @@ function renderActions(selected: Set): Children { title: "Reboot selected devices", disabled: !selected.size, onclick: () => { - for (const d of selected) { - taskQueue.queueTask({ - name: "reboot", - device: d, - }); - } + const tasks = [...selected].map((s) => ({ + name: "reboot", + device: s, + })); + queueTask(...tasks); }, }, "Reboot" @@ -110,12 +109,11 @@ function renderActions(selected: Set): Children { title: "Factory reset selected devices", disabled: !selected.size, onclick: () => { - for (const d of selected) { - taskQueue.queueTask({ - name: "factoryReset", - device: d, - }); - } + const tasks = [...selected].map((s) => ({ + name: "factoryReset", + device: s, + })); + queueTask(...tasks); }, }, "Reset" @@ -129,7 +127,7 @@ function renderActions(selected: Set): Children { title: "Push a firmware or a config file", disabled: !selected.size, onclick: () => { - taskQueue.stageDownload({ + stageDownload({ name: "download", devices: [...selected], }); diff --git a/ui/drawer-component.ts b/ui/drawer-component.ts index a1ae879..4e75f9d 100644 --- a/ui/drawer-component.ts +++ b/ui/drawer-component.ts @@ -468,7 +468,7 @@ const component: ClosureComponent = (): Component => { store.fulfill(0, Date.now()); }) .catch((err) => { - throw err; + notifications.push("error", err.message); }); }, }, diff --git a/ui/task-queue.ts b/ui/task-queue.ts index 0f3800b..bcb2a7c 100644 --- a/ui/task-queue.ts +++ b/ui/task-queue.ts @@ -19,6 +19,7 @@ import * as store from "./store"; import { Task } from "../lib/types"; +import * as notifications from "./notifications"; export interface QueueTask extends Task { status?: string; @@ -29,12 +30,27 @@ export interface StageTask extends Task { devices: string[]; } +const MAX_QUEUE = 100; + const queue: Set = new Set(); const staging: Set = new Set(); -export function queueTask(task: QueueTask): void { - task.status = "queued"; - queue.add(task); +function canQueue(tasks: QueueTask[]): boolean { + let count = queue.size; + for (const task of tasks) if (!queue.has(task)) ++count; + return count <= MAX_QUEUE; +} + +export function queueTask(...tasks: QueueTask[]): void { + if (!canQueue(tasks)) { + notifications.push("error", "Too many tasks in queue"); + return; + } + + for (const task of tasks) { + task.status = "queued"; + queue.add(task); + } } export function deleteTask(task: QueueTask): void { @@ -58,10 +74,18 @@ export function clearStaging(): void { } export function stageSpv(task: StageTask): void { + if (queue.size + task.devices.length > MAX_QUEUE) { + notifications.push("error", "Too many tasks in queue"); + return; + } staging.add(task); } export function stageDownload(task: StageTask): void { + if (queue.size + task.devices.length > MAX_QUEUE) { + notifications.push("error", "Too many tasks in queue"); + return; + } staging.add(task); } @@ -75,10 +99,15 @@ export function commit( ) => void ): Promise { const devices: { [deviceId: string]: any[] } = {}; + + if (!canQueue(tasks)) + return Promise.reject(new Error("Too many tasks in queue")); + for (const t of tasks) { devices[t.device] = devices[t.device] || []; devices[t.device].push(t); - queueTask(t); + t.status = "queued"; + queue.add(t); } return new Promise((resolve) => {