File Explorer

/proc/4/task/7/root/var/lang/lib/node_modules/npm/node_modules/@gar/promise-retry/lib

This explorer reads the filesystem of the server it runs on, so /workspace/user isn't present here. Browsing and the terminal still work against this server's own disk from /.

retry.js2.4 KB · 110 lines
class RetryOperation {  #attempts = 1  #cachedTimeouts = null  #errors = []  #fn = null  #maxRetryTime  #operationStart = null  #originalTimeouts  #timeouts  #timer = null  #unref   constructor (timeouts, options = {}) {    this.#originalTimeouts = [...timeouts]    this.#timeouts = [...timeouts]    this.#unref = options.unref    this.#maxRetryTime = options.maxRetryTime || Infinity    if (options.forever) {      this.#cachedTimeouts = [...this.#timeouts]    }  }   get timeouts () {    return [...this.#timeouts]  }   get errors () {    return [...this.#errors]  }   get attempts () {    return this.#attempts  }   get mainError () {    let mainError = null    if (this.#errors.length) {      let mainErrorCount = 0      const counts = {}      for (let i = 0; i < this.#errors.length; i++) {        const error = this.#errors[i]        const { message } = error        if (!counts[message]) {          counts[message] = 0        }        counts[message]++         if (counts[message] >= mainErrorCount) {          mainError = error          mainErrorCount = counts[message]        }      }    }    return mainError  }   reset () {    this.#attempts = 1    this.#timeouts = [...this.#originalTimeouts]  }   stop () {    if (this.#timer) {      clearTimeout(this.#timer)    }     this.#timeouts = []    this.#cachedTimeouts = null  }   retry (err) {    this.#errors.push(err)    if (new Date().getTime() - this.#operationStart >= this.#maxRetryTime) {      // XXX This puts the timeout error first, meaning it will never show as mainError, there may be no way to ever see this      this.#errors.unshift(new Error('RetryOperation timeout occurred'))      return false    }     let timeout = this.#timeouts.shift()    if (timeout === undefined) {      // We're out of timeouts, clear the last error and repeat the final timeout      if (this.#cachedTimeouts) {        this.#errors.pop()        timeout = this.#cachedTimeouts.at(-1)      } else {        return false      }    }     // TODO what if there already is a timer?    this.#timer = setTimeout(() => {      this.#attempts++      this.#fn(this.#attempts)    }, timeout)     if (this.#unref) {      this.#timer.unref()    }     return true  }   attempt (fn) {    this.#fn = fn    this.#operationStart = new Date().getTime()    this.#fn(this.#attempts)  }}module.exports = { RetryOperation }