federer
Version:
Experiments in asynchronous federated learning and decentralized learning
56 lines • 2.21 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", { value: true });
exports.PrioritizedLockedTaskRunner = void 0;
const tslib_1 = require("tslib");
const await_lock_1 = tslib_1.__importDefault(require("await-lock"));
/**
* Abstraction for running asynchronous, locked, prioritized tasks.
*
* Tasks are *asynchronous*: they should return a `Promise<void>`.
*
* The tasks are *locked*: a lock is acquired before they are executed. They are
* still executed asynchronously, but not concurrently with each other. However,
* they can execute concurrently with unrelated `Promise`s.
*
* Finally, the tasks are *prioritized*: only the task with the highest priority
* is executed. Registering a task invalidates all not-yet-executed tasks with
* lower priorities.
*/
class PrioritizedLockedTaskRunner {
constructor() {
this.lock = new await_lock_1.default();
this.highestPriority = Number.MIN_SAFE_INTEGER;
}
/**
* Register a task to run when the lock is available, if not invalidated by a
* higher-priority task.
*
* @param priority Priority of the task. All registered but not-yet-executed
* tasks with lower priority will be invalidated.
* @param task Callback containing the task to run
*/
async run(priority, task) {
// If this new job is lower priority than a previous job, we don't need to
// run it.
if (priority < this.highestPriority) {
return Promise.reject("Lower priority than highest priority");
}
this.highestPriority = priority;
await this.lock.acquireAsync();
try {
// If the task has not been invalidated by a higher-priority request that
// was registered while we were awaiting the lock, we can run it.
if (priority === this.highestPriority) {
return task();
}
else {
return Promise.reject("Superseded by higher-priority task");
}
}
finally {
this.lock.release();
}
}
}
exports.PrioritizedLockedTaskRunner = PrioritizedLockedTaskRunner;
//# sourceMappingURL=PrioritizedLockedTaskRunner.js.map