* Adds a promise to a chain. * Promise description should be passed as first parameter. * * @param {string|function} taskName * @param {function} [fn] * @param {boolean} [force=false] * @param {boolean} [retry] * undefined: `add(fn)` -> `false` and `add('step',fn)` -> `true`
(taskName, fn = undefined, force = false, retry = undefined, timeout = undefined)
| 189 | * @inner |
| 190 | */ |
| 191 | add(taskName, fn = undefined, force = false, retry = undefined, timeout = undefined) { |
| 192 | if (typeof taskName === 'function') { |
| 193 | fn = taskName |
| 194 | taskName = fn.toString() |
| 195 | if (retry === undefined) retry = false |
| 196 | } |
| 197 | if (retry === undefined) retry = true |
| 198 | if (!running && !force) { |
| 199 | return Promise.resolve() |
| 200 | } |
| 201 | tasks.push(taskName) |
| 202 | debug(chalk.gray(`${currentQueue()} Queued | ${taskName}`)) |
| 203 | |
| 204 | return (promise = Promise.resolve(promise).then(res => { |
| 205 | // prefer options for non-conditional retries |
| 206 | const retryOpts = this.retries |
| 207 | .sort((r1, r2) => r1.when && !r2.when) |
| 208 | .slice(-1) |
| 209 | .pop() |
| 210 | // no retries or unnamed tasks |
| 211 | debug(`${currentQueue()} Running | ${taskName} | Timeout: ${timeout || 'None'}`) |
| 212 | if (retryOpts) debug(`${currentQueue()} Retry opts`, JSON.stringify(retryOpts)) |
| 213 | |
| 214 | if (!retryOpts || !taskName || !retry) { |
| 215 | const [promise, timer] = getTimeoutPromise(timeout, taskName) |
| 216 | return Promise.race([promise, Promise.resolve(res).then(fn)]).finally(() => clearTimeout(timer)) |
| 217 | } |
| 218 | |
| 219 | const retryRules = this.retries.slice().reverse() |
| 220 | return promiseRetry(Object.assign({}, defaultRetryOptions, retryOpts), (retry, number) => { |
| 221 | if (number > 1) output.log(`${currentQueue()}Retrying... Attempt #${number}`) |
| 222 | const [promise, timer] = getTimeoutPromise(timeout, taskName) |
| 223 | return Promise.race([promise, Promise.resolve(res).then(fn)]) |
| 224 | .finally(() => clearTimeout(timer)) |
| 225 | .catch(err => { |
| 226 | if (ignoredErrs.includes(err)) return |
| 227 | for (const retryObj of retryRules) { |
| 228 | if (!retryObj.when) return retry(err) |
| 229 | if (retryObj.when && retryObj.when(err)) return retry(err) |
| 230 | } |
| 231 | throw err |
| 232 | }) |
| 233 | }) |
| 234 | })) |
| 235 | }, |
| 236 | |
| 237 | /** |
| 238 | * @param {*} opts |
nothing calls this directly
no test coverage detected