replace queue with worker

This commit is contained in:
Jon Staab
2024-03-26 11:35:30 -07:00
parent 0b5a4e8511
commit bc21228f04
7 changed files with 144 additions and 126 deletions
-57
View File
@@ -1,57 +0,0 @@
export class Queue {
timeout?: number
messages: any[] = []
clear() {
this.messages = []
}
push(message: any) {
this.messages.push(message)
this.enqueueWork()
}
handle(message: any) {
throw new Error("Not implemented")
}
shouldSend(message: any) {
return true
}
doWork() {
for (let i = 0; i < 10; i++) {
if (this.messages.length === 0) {
break
}
// Pop the messages one at a time so handle can modify the queue
const [message] = this.messages.splice(0, 1)
if (this.shouldSend(message)) {
this.handle(message)
} else {
this.messages.push(message)
}
}
this.timeout = undefined
this.enqueueWork()
}
enqueueWork() {
if (this.timeout) {
return
}
if (this.messages.length === 0) {
return
}
this.timeout = setTimeout(() => this.doWork(), 100)
}
stop() {
clearTimeout(this.timeout)
}
}
+71
View File
@@ -0,0 +1,71 @@
const ANY = Symbol("worker/ANY")
export type WorkerOpts<T> = {
getKey?: (x: T) => any
shouldDefer?: (x: T) => boolean
}
export class Worker<T> {
buffer: T[] = []
handlers: Map<any, Array<(x: T) => void>> = new Map()
timeout: number | undefined
constructor(readonly opts: WorkerOpts<T> = {}) {}
#doWork = async () => {
for (let i = 0; i < 50; i++) {
if (this.buffer.length === 0) {
break
}
// Pop the buffer one at a time so handle can modify the queue
const [message] = this.buffer.splice(0, 1)
if (this.opts.shouldDefer?.(message)) {
this.buffer.push(message)
} else {
for (const handler of this.handlers.get(ANY) || []) {
await handler(message)
}
if (this.opts.getKey) {
const k = this.opts.getKey(message)
for (const handler of this.handlers.get(k) || []) {
await handler(message)
}
}
}
}
this.timeout = undefined
this.#enqueueWork()
}
#enqueueWork = () => {
if (!this.timeout && this.buffer.length > 0) {
this.timeout = setTimeout(this.#doWork, 50)
}
}
push = (message: T) => {
this.buffer.push(message)
this.#enqueueWork()
}
addHandler = (k: any, handler: (message: T) => void) => {
this.handlers.set(k, (this.handlers.get(k) || []).concat(handler))
}
addGlobalHandler = (handler: (message: T) => void) => {
this.addHandler(ANY, handler)
}
clear() {
this.buffer = []
}
stop() {
clearTimeout(this.timeout)
}
}
+1 -1
View File
@@ -3,6 +3,6 @@ export * from './Deferred'
export * from './Emitter'
export * from './Fluent'
export * from './LRUCache'
export * from './Queue'
export * from './Worker'
export * from './Tools'
export {default as normalizeUrl} from './normalize-url'