Clear task queue logic
This commit is contained in:
parent
57ccf14553
commit
236135f1ca
@ -28,8 +28,8 @@ export class Scheduler {
|
|||||||
|
|
||||||
private scheduleUniqTask(seconds: number, name: string, args: Args = {}) {
|
private scheduleUniqTask(seconds: number, name: string, args: Args = {}) {
|
||||||
const taskScheduler = () => {
|
const taskScheduler = () => {
|
||||||
if (!this.taskQueue.hasNamed(name)) {
|
if (!this.taskQueue.has(t => t.name === name)) {
|
||||||
this.taskQueue.push(name, args, timestamp() + Math.min(seconds, 5 * 60));
|
this.scheduleTask(name, args, timestamp() + Math.min(seconds, 5 * 60));
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
taskScheduler();
|
taskScheduler();
|
||||||
@ -48,23 +48,23 @@ export class Scheduler {
|
|||||||
return this.actionQueue.pop();
|
return this.actionQueue.pop();
|
||||||
}
|
}
|
||||||
|
|
||||||
scheduleTask(name: string, args: Args): void {
|
scheduleTask(name: string, args: Args, ts?: number | undefined): void {
|
||||||
this.logger.log('PUSH TASK', name, args);
|
this.logger.log('PUSH TASK', name, args, ts);
|
||||||
const villageId = args.villageId;
|
const villageId = args.villageId;
|
||||||
if (isBuildingTask(name)) {
|
if (isBuildingTask(name)) {
|
||||||
this.taskQueue.insertAfterLast(
|
const insertedTs = calculateTimeToPushAfter(
|
||||||
|
this.taskQueue.seeItems(),
|
||||||
t => isBuildingTask(t.name) && sameVillage(villageId, t.args),
|
t => isBuildingTask(t.name) && sameVillage(villageId, t.args),
|
||||||
name,
|
ts
|
||||||
args,
|
|
||||||
timestamp()
|
|
||||||
);
|
);
|
||||||
|
this.taskQueue.push(name, args, insertedTs);
|
||||||
} else {
|
} else {
|
||||||
this.taskQueue.push(name, args, timestamp());
|
this.taskQueue.push(name, args, ts || timestamp());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
completeTask(id: TaskId) {
|
completeTask(id: TaskId) {
|
||||||
this.taskQueue.complete(id);
|
this.taskQueue.remove(id);
|
||||||
this.actionQueue.clear();
|
this.actionQueue.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -74,13 +74,16 @@ export class Scheduler {
|
|||||||
}
|
}
|
||||||
|
|
||||||
postponeTask(id: TaskId, deltaTs: number) {
|
postponeTask(id: TaskId, deltaTs: number) {
|
||||||
this.taskQueue.postpone(id, timestamp() + deltaTs);
|
this.taskQueue.modify(
|
||||||
|
t => t.id === id,
|
||||||
|
t => withTime(t, timestamp() + deltaTs)
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
postponeBuildingsInVillage(villageId: number, seconds: number) {
|
postponeBuildingsInVillage(villageId: number, seconds: number) {
|
||||||
this.taskQueue.modify(
|
this.taskQueue.modify(
|
||||||
t => isBuildingTask(t.name) && sameVillage(villageId, t.args),
|
t => isBuildingTask(t.name) && sameVillage(villageId, t.args),
|
||||||
t => t.withTime(timestamp() + seconds)
|
t => withTime(t, timestamp() + seconds)
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -100,3 +103,29 @@ function isBuildingTask(taskName: string) {
|
|||||||
function sameVillage(villageId: number | undefined, args: Args) {
|
function sameVillage(villageId: number | undefined, args: Args) {
|
||||||
return villageId !== undefined && args.villageId === villageId;
|
return villageId !== undefined && args.villageId === villageId;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function withTime(task: Task, ts: number): Task {
|
||||||
|
return new Task(task.id, ts, task.name, task.args);
|
||||||
|
}
|
||||||
|
|
||||||
|
function calculateTimeToPushAfter(tasks: TaskList, predicate: (t: Task) => boolean, ts: number | undefined): number {
|
||||||
|
const normalizedTs = ts || timestamp();
|
||||||
|
const queuedTaskIndex = findLastIndex(tasks, predicate);
|
||||||
|
if (queuedTaskIndex === undefined) {
|
||||||
|
return normalizedTs;
|
||||||
|
}
|
||||||
|
const queuedTask = tasks[queuedTaskIndex];
|
||||||
|
return Math.max(normalizedTs, queuedTask.ts + 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
function findLastIndex(tasks: TaskList, predicate: (t: Task) => boolean): number | undefined {
|
||||||
|
const count = tasks.length;
|
||||||
|
const indexInReversed = tasks
|
||||||
|
.slice()
|
||||||
|
.reverse()
|
||||||
|
.findIndex(predicate);
|
||||||
|
if (indexInReversed < 0) {
|
||||||
|
return undefined;
|
||||||
|
}
|
||||||
|
return count - 1 - indexInReversed;
|
||||||
|
}
|
||||||
|
@ -23,10 +23,6 @@ export class Task {
|
|||||||
this.name = name;
|
this.name = name;
|
||||||
this.args = args;
|
this.args = args;
|
||||||
}
|
}
|
||||||
|
|
||||||
withTime(ts: number): Task {
|
|
||||||
return new Task(this.id, ts, this.name, this.args);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export type TaskList = Array<Task>;
|
export type TaskList = Array<Task>;
|
||||||
@ -50,15 +46,6 @@ export class TaskQueue {
|
|||||||
return task;
|
return task;
|
||||||
}
|
}
|
||||||
|
|
||||||
insertAfterLast(predicate: (t: Task) => boolean, name: string, args: Args, ts: number): Task {
|
|
||||||
const id = uniqTaskId();
|
|
||||||
const task = new Task(id, ts, name, args);
|
|
||||||
this.logger.log('INSERT AFTER TASK', id, ts, name, args);
|
|
||||||
const items = insertTaskAfter(task, this.getItems(), predicate);
|
|
||||||
this.flushItems(items);
|
|
||||||
return task;
|
|
||||||
}
|
|
||||||
|
|
||||||
get(ts: number): Task | undefined {
|
get(ts: number): Task | undefined {
|
||||||
const readyItems = this.getItems().filter(t => t.ts <= ts);
|
const readyItems = this.getItems().filter(t => t.ts <= ts);
|
||||||
if (readyItems.length === 0) {
|
if (readyItems.length === 0) {
|
||||||
@ -72,30 +59,12 @@ export class TaskQueue {
|
|||||||
return matched.length > 0;
|
return matched.length > 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
hasNamed(name: string): boolean {
|
|
||||||
return this.has(t => t.name === name);
|
|
||||||
}
|
|
||||||
|
|
||||||
modify(predicate: (t: Task) => boolean, modifier: (t: Task) => Task) {
|
modify(predicate: (t: Task) => boolean, modifier: (t: Task) => Task) {
|
||||||
const [matched, other] = this.split(predicate);
|
const [matched, other] = this.split(predicate);
|
||||||
const modified = matched.map(modifier);
|
const modified = matched.map(modifier);
|
||||||
this.flushItems(modified.concat(other));
|
this.flushItems(modified.concat(other));
|
||||||
}
|
}
|
||||||
|
|
||||||
complete(id: TaskId) {
|
|
||||||
const [_, items] = this.shiftTask(id);
|
|
||||||
this.flushItems(items);
|
|
||||||
}
|
|
||||||
|
|
||||||
postpone(id: TaskId, newTs: number) {
|
|
||||||
const [task, items] = this.shiftTask(id);
|
|
||||||
if (task) {
|
|
||||||
this.logger.log('POSTPONE', task);
|
|
||||||
items.push(task.withTime(newTs));
|
|
||||||
}
|
|
||||||
this.flushItems(items);
|
|
||||||
}
|
|
||||||
|
|
||||||
remove(id: TaskId) {
|
remove(id: TaskId) {
|
||||||
const [_, items] = this.shiftTask(id);
|
const [_, items] = this.shiftTask(id);
|
||||||
this.flushItems(items);
|
this.flushItems(items);
|
||||||
@ -142,27 +111,3 @@ export class TaskQueue {
|
|||||||
this.storage.set(QUEUE_NAME, normalized);
|
this.storage.set(QUEUE_NAME, normalized);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function insertTaskAfter(task: Task, tasks: TaskList, predicate: (t: Task) => boolean): TaskList {
|
|
||||||
const queuedTaskIndex = findLastIndex(tasks, predicate);
|
|
||||||
if (queuedTaskIndex === undefined) {
|
|
||||||
tasks.push(task);
|
|
||||||
return tasks;
|
|
||||||
}
|
|
||||||
const queuedTask = tasks[queuedTaskIndex];
|
|
||||||
let insertedTask = task.withTime(Math.max(task.ts, queuedTask.ts + 1));
|
|
||||||
tasks.splice(queuedTaskIndex, 0, insertedTask);
|
|
||||||
return tasks;
|
|
||||||
}
|
|
||||||
|
|
||||||
function findLastIndex(tasks: TaskList, predicate: (t: Task) => boolean): number | undefined {
|
|
||||||
const count = tasks.length;
|
|
||||||
const indexInReversed = tasks
|
|
||||||
.slice()
|
|
||||||
.reverse()
|
|
||||||
.findIndex(predicate);
|
|
||||||
if (indexInReversed < 0) {
|
|
||||||
return undefined;
|
|
||||||
}
|
|
||||||
return count - 1 - indexInReversed;
|
|
||||||
}
|
|
||||||
|
Loading…
Reference in New Issue
Block a user