| 110 | } |
| 111 | |
| 112 | private _process(workerId: number): Farm { |
| 113 | if (this._isLocked(workerId)) { |
| 114 | return this; |
| 115 | } |
| 116 | |
| 117 | const task = this._taskQueue.dequeue(workerId); |
| 118 | |
| 119 | if (!task) { |
| 120 | return this; |
| 121 | } |
| 122 | |
| 123 | if (task.request[1]) { |
| 124 | throw new Error('Queue implementation returned processed task'); |
| 125 | } |
| 126 | |
| 127 | // Reference the task object outside so it won't be retained by onEnd, |
| 128 | // and other properties of the task object, such as task.request can be |
| 129 | // garbage collected. |
| 130 | let taskOnEnd: OnEnd | null = task.onEnd; |
| 131 | const onEnd: OnEnd = (error, result) => { |
| 132 | if (taskOnEnd) { |
| 133 | taskOnEnd(error, result); |
| 134 | } |
| 135 | taskOnEnd = null; |
| 136 | |
| 137 | this._unlock(workerId); |
| 138 | this._process(workerId); |
| 139 | }; |
| 140 | |
| 141 | task.request[1] = true; |
| 142 | |
| 143 | this._lock(workerId); |
| 144 | this._callback( |
| 145 | workerId, |
| 146 | task.request, |
| 147 | task.onStart, |
| 148 | onEnd, |
| 149 | task.onCustomMessage, |
| 150 | ); |
| 151 | |
| 152 | return this; |
| 153 | } |
| 154 | |
| 155 | private _push(task: QueueChildMessage): Farm { |
| 156 | this._taskQueue.enqueue(task); |