edan20-assignment3 / lib /worker_pool.js
lkmill's picture
implement worker pool
6305c92
Raw History Blame Contribute Delete
1.56 kB
const poolSize = Math.min(navigator.hardwareConcurrency || 4, 12)
const activeJobs = new Map()
const queue = []
const workers = []
function initWorker() {
const worker = new Worker(new URL('./worker.js', import.meta.url), { type: 'module' })
worker.id = workers.length
worker.isAvailable = true
worker.onmessage = handleMessage
worker.onerror = handleError
workers.push(worker)
return worker
}
function getAvailableWorker() {
let worker = workers.find((worker) => worker.isAvailable)
if (worker) return worker
if (workers.length < poolSize) return initWorker()
}
function assignJob(worker, job) {
worker.isAvailable = false
worker.postMessage(job.data)
activeJobs.set(worker.id, job)
}
function handleMessage(message) {
const job = activeJobs.get(this.id)
activeJobs.delete(this.id)
job.resolve(message.data)
this.isAvailable = true
processQueue()
}
function processQueue() {
const nextJob = queue.unshift()
if (!nextJob) return
const worker = getAvailableWorker()
if (!worker) return
assignJob(worker, job)
}
function handleError(error) {
const job = activeJobs.get(this.id)
delete activeJobs.get(this.id)
job.reject(error)
}
export default {
execute(data) {
return new Promise((resolve, reject) => {
const worker = getAvailableWorker()
const job = {
data,
resolve,
reject,
}
if (worker) {
assignJob(worker, job)
} else {
queue.push(job)
}
})
},
workerCount() {
return workers.length
},
}