wikiloop-doublecheck icon indicating copy to clipboard operation
wikiloop-doublecheck copied to clipboard

Fix: handle API:fetchOres has an unknown error of

Open xinbenlv opened this issue 4 years ago • 0 comments

[error] API:fetchOres has an unknown error of  name=StatusCodeError statusCode=404 message="404 - {\"error\":{\"code\":\"not found\",\"message\":\"No scorers available for bgwiki\"}}" error#error#code="not found" error#error#message="No scorers available for bgwiki" options#json=true options#uri="https://ores.wikimedia.org/v3/scores/bgwiki/?models=damaging|goodfaith&revids=10381661" options#method=GET options#callback="function RP$callback(err, response, body) {
            plumbing.callback.call(self, err, response, body);
        }" options#transform= options#simple=true options#resolveWithFullResponse=false options#transform2xxOnly=false response#_readableState#objectMode=false response#_readableState#highWaterMark=16384 response#_readableState#buffer#head= response#_readableState#buffer#tail= response#_readableState#buffer#length=0 response#_readableState#length=0 response#_readableState#pipes= response#_readableState#pipesCount=0 response#_readableState#flowing=true response#_readableState#ended=true response#_readableState#endEmitted=true response#_readableState#reading=false response#_readableState#sync=false response#_readableState#needReadable=false response#_readableState#emittedReadable=false response#_readableState#readableListening=false response#_readableState#resumeScheduled=false response#_readableState#emitClose=true response#_readableState#autoDestroy=false response#_readableState#destroyed=false response#_readableState#defaultEncoding=utf8 response#_readableState#awaitDrainWriters= response#_readableState#multiAwaitDrain=false response#_readableState#readingMore=false response#_readableState#decoder= response#_readableState#encoding= response#readable=false response#_events#end#0="function responseOnEnd() {
  const req = this.req;

  if (req.socket && req.timeoutCb) {
    req.socket.removeListener('timeout', emitRequestTimeout);
  }

  req._ended = true;

  if (!req.shouldKeepAlive) {
    const socket = req.socket;
    if (socket.writable) {
      debug('AGENT socket.destroySoon()');
      if (typeof socket.destroySoon === 'function')
        socket.destroySoon();
      else
        socket.end();
    }
    assert(!socket.writable);
  } else if (req.finished) {
    // We can assume `req.finished` means all data has been written since:
    // - `'responseOnEnd'` means we have been assigned a socket.
    // - when we have a socket we write directly to it without buffering.
    // - `req.finished` means `end()` has been called and no further data.
    //   can be written
    responseKeepAlive(req);
  }
}" response#_events#end#1="function () {
    if (self.timing) {
      self.timings.end = now() - self.startTimeNow
      response.timingStart = self.startTime

      // fill in the blanks for any periods that didn't trigger, such as
      // no lookup or connect due to keep alive
      if (!self.timings.socket) {
        self.timings.socket = 0
      }
      if (!self.timings.lookup) {
        self.timings.lookup = self.timings.socket
      }
      if (!self.timings.connect) {
        self.timings.connect = self.timings.lookup
      }
      if (!self.timings.response) {
        self.timings.response = self.timings.connect
      }

      debug('elapsed time', self.timings.end)

      // elapsedTime includes all redirects
      self.elapsedTime += Math.round(self.timings.end)

      // NOTE: elapsedTime is deprecated in favor of .timings
      response.elapsedTime = self.elapsedTime

      // timings is just for the final fetch
      response.timings = self.timings

      // pre-calculate phase timings as well
      response.timingPhases = {
        wait: self.timings.socket,
        dns: self.timings.lookup - self.timings.socket,
        tcp: self.timings.connect - self.timings.lookup,
        firstByte: self.timings.response - self.timings.connect,
        download: self.timings.end - self.timings.response,
        total: self.timings.end
      }
    }
    debug('response end', self.uri.href, response.statusCode, response.headers)
  }" response#_events#close#0="function () {
      if (!self._ended) {
        self.response.emit('end')
      }
    }" response#_events#close#1="function () { self.emit('close') }" response#_events#data="function (chunk) {
      if (self.timing && !self.responseStarted) {
        self.responseStartTime = (new Date()).getTime()

        // NOTE: responseStartTime is deprecated in favor of .timings
        response.responseStartTime = self.responseStartTime
      }
      self._destdata = true
      self.emit('data', chunk)
    }" response#_events#error="function (error) {
      self.emit('error', error)
    }" response#_eventsCount=4 response#_maxListeners= response#socket#_tlsOptions#allowHalfOpen= response#socket#_tlsOptions#pipe=false response#socket#_tlsOptions#secureContext#context="[object Object]" response#socket#_tlsOptions#secureContext#singleUse=true response#socket#_tlsOptions#isServer=false response#socket#_tlsOptions#requestCert=true response#socket#_tlsOptions#rejectUnauthorized=true response#socket#_tlsOptions#session= response#socket#_tlsOptions#ALPNProtocols= response#socket#_tlsOptions#requestOCSP= response#socket#_tlsOptions#enableTrace= response#socket#_tlsOptions#pskCallback= response#socket#_secureEstablished=true response#socket#_securePending=false response#socket#_newSessionPending=false response#socket#_controlReleased=true response#socket#secureConnecting=true response#socket#_SNICallback= response#socket#servername=ores.wikimedia.org response#socket#alpnProtocol=false response#socket#authorized=true response#socket#authorizationError= response#socket#encrypted=true response#socket#_events#close#0="function onSocketCloseDestroySSL() {
  // Make sure we are not doing it on OpenSSL's stack
  setImmediate(destroySSL, this);
  this[kRes] = null;
}" response#socket#_events#close#1="function () { [native code] }" response#socket#_events#close#2="function onClose(err) {
    debug('CLIENT socket onClose');
    // This is the only place where sockets get removed from the Agent.
    // If you want to remove a socket from the pool, just close it.
    // All socket errors end in a close event anyway.
    agent.removeSocket(s, options);
  }" response#socket#_events#close#3="function socketCloseListener() {
  const socket = this;
  const req = socket._httpMessage;
  debug('HTTP socket close');

  // Pull through final chunk, if anything is buffered.
  // the ondata function will handle it properly, and this
  // is a no-op if no final chunk remains.
  socket.read();

  // NOTE: It's important to get parser here, because it could be freed by
  // the `socketOnData`.
  const parser = socket.parser;
  const res = req.res;
  if (res) {
    // Socket closed before we emitted 'end' below.
    if (!res.complete) {
      res.aborted = true;
      res.emit('aborted');
    }
    req.emit('close');
    if (res.readable) {
      res.on('end', function() {
        this.emit('close');
      });
      res.push(null);
    } else {
      res.emit('close');
    }
  } else {
    if (!req.socket._hadError) {
      // This socket error fired before we started to
      // receive a response. The error needs to
      // fire on the request.
      req.socket._hadError = true;
      req.emit('error', connResetException('socket hang up'));
    }
    req.emit('close');
  }

  // Too bad.  That output wasn't getting written.
  // This is pretty terrible that it doesn't raise an error.
  // Fixed better in v0.10
  if (req.outputData)
    req.outputData.length = 0;

  if (parser) {
    parser.finish();
    freeParser(parser, req, socket);
  }
}" response#socket#_events#end="function onReadableStreamEnd() {
  if (!this.allowHalfOpen) {
    this.write = writeAfterFIN;
    if (this.writable)
      this.end();
    else if (!this.writableLength)
      this.destroy();
  } else if (!this.destroyed && !this.writable && !this.writableLength)
    this.destroy();
}" response#socket#_events#newListener="function keylogNewListener(event) {
      if (event !== 'keylog')
        return;

      ssl.enableKeylogCallback();

      // Remove this listener since it's no longer needed.
      this.removeListener('newListener', keylogNewListener);
    }" response#socket#_events#secure="function onConnectSecure() {
  const options = this[kConnectOptions];

  // Check the size of DHE parameter above minimum requirement
  // specified in options.
  const ekeyinfo = this.getEphemeralKeyInfo();
  if (ekeyinfo.type === 'DH' && ekeyinfo.size < options.minDHSize) {
    const err = new ERR_TLS_DH_PARAM_SIZE(ekeyinfo.size);
    debug('client emit:', err);
    this.emit('error', err);
    this.destroy();
    return;
  }

  let verifyError = this._handle.verifyError();

  // Verify that server's identity matches it's certificate's names
  // Unless server has resumed our existing session
  if (!verifyError && !this.isSessionReused()) {
    const hostname = options.servername ||
                   options.host ||
                   (options.socket && options.socket._host) ||
                   'localhost';
    const cert = this.getPeerCertificate(true);
    verifyError = options.checkServerIdentity(hostname, cert);
  }

  if (verifyError) {
    this.authorized = false;
    this.authorizationError = verifyError.code || verifyError.message;

    if (options.rejectUnauthorized) {
      this.destroy(verifyError);
      return;
    } else {
      debug('client emit secureConnect. rejectUnauthorized: %s, ' +
            'authorizationError: %s', options.rejectUnauthorized,
            this.authorizationError);
      this.emit('secureConnect');
    }
  } else {
    this.authorized = true;
    debug('client emit secureConnect. authorized:', this.authorized);
    this.emit('secureConnect');
  }

  this[kIsVerified] = true;
  const session = this[kPendingSession];
  this[kPendingSession] = null;
  if (session)
    this.emit('session', session);

  this.removeListener('end', onConnectEnd);
}" response#socket#_events#session="(session) => {
      this._cacheSession(options._agentKey, session);
    }" response#socket#_events#free="function onFree() {
    debug('CLIENT socket onFree');
    agent.emit('free', s, options);
  }" response#socket#_events#timeout="function onTimeout() {
    debug('CLIENT socket onTimeout');

    // Destroy if in free list.
    // TODO(ronag): Always destroy, even if not in free list.
    const sockets = agent.freeSockets;
    for (const name of ObjectKeys(sockets)) {
      if (sockets[name].includes(s)) {
        return s.destroy();
      }
    }
  }" response#socket#_events#agentRemove="function onRemove() {
    // We need this function for cases like HTTP 'upgrade'
    // (defined by WebSockets) where we need to remove a socket from the
    // pool because it'll be locked up indefinitely
    debug('CLIENT socket onRemove');
    agent.removeSocket(s, options);
    s.removeListener('close', onClose);
    s.removeListener('free', onFree);
    s.removeListener('timeout', onTimeout);
    s.removeListener('agentRemove', onRemove);
  }" response#socket#_events#error="function socketErrorListener(err) {
  const socket = this;
  const req = socket._httpMessage;
  debug('SOCKET ERROR:', err.message, err.stack);

  if (req) {
    // For Safety. Some additional errors might fire later on
    // and we need to make sure we don't double-fire the error event.
    req.socket._hadError = true;
    req.emit('error', err);
  }

  // Handle any pending data
  socket.read();

  const parser = socket.parser;
  if (parser) {
    parser.finish();
    freeParser(parser, req, socket);
  }

  // Ensure that no further data will come out of the socket
  socket.removeListener('data', socketOnData);
  socket.removeListener('end', socketOnEnd);
  socket.destroy();
}" response#socket#_events#finish="function () { [native code] }" response#socket#_eventsCount=10 response#socket#connecting=false response#socket#_hadError=false response#socket#_parent= response#socket#_host=ores.wikimedia.org response#socket#_readableState#objectMode=false response#socket#_readableState#highWaterMark=16384 response#socket#_readableState#buffer#head= response#socket#_readableState#buffer#tail= response#socket#_readableState#buffer#length=0 response#socket#_readableState#length=0 response#socket#_readableState#pipes= response#socket#_readableState#pipesCount=0 response#socket#_readableState#flowing=true response#socket#_readableState#ended=true response#socket#_readableState#endEmitted=true response#socket#_readableState#reading=false response#socket#_readableState#sync=false response#socket#_readableState#needReadable=false response#socket#_readableState#emittedReadable=false response#socket#_readableState#readableListening=false response#socket#_readableState#resumeScheduled=false response#socket#_readableState#emitClose=false response#socket#_readableState#autoDestroy=false response#socket#_readableState#destroyed=true response#socket#_readableState#defaultEncoding=utf8 response#socket#_readableState#awaitDrainWriters= response#socket#_readableState#multiAwaitDrain=false response#socket#_readableState#readingMore=false response#socket#_readableState#decoder= response#socket#_readableState#encoding= response#socket#readable=false response#socket#_maxListeners= response#socket#_writableState#objectMode=false response#socket#_writableState#highWaterMark=16384 response#socket#_writableState#finalCalled=true response#socket#_writableState#needDrain=false response#socket#_writableState#ending=true response#socket#_writableState#ended=true response#socket#_writableState#finished=false response#socket#_writableState#destroyed=true response#socket#_writableState#decodeStrings=false response#socket#_writableState#defaultEncoding=utf8 response#socket#_writableState#length=0 response#socket#_writableState#writing=false response#socket#_writableState#corked=0 response#socket#_writableState#sync=false response#socket#_writableState#bufferProcessing=false response#socket#_writableState#onwrite="function () { [native code] }" response#socket#_writableState#writecb= response#socket#_writableState#writelen=0 response#socket#_writableState#afterWriteTickInfo= response#socket#_writableState#bufferedRequest= response#socket#_writableState#lastBufferedRequest= response#socket#_writableState#pendingcb=1 response#socket#_writableState#prefinished=false response#socket#_writableState#errorEmitted=false response#socket#_writableState#emitClose=false response#socket#_writableState#autoDestroy=false response#socket#_writableState#bufferedRequestCount=0 response#socket#_writableState#corkedRequestsFree#next= response#socket#_writableState#corkedRequestsFree#entry= response#socket#_writableState#corkedRequestsFree#finish="function () { [native code] }" response#socket#writable=false response#socket#allowHalfOpen=false response#socket#_sockname= response#socket#_pendingData= response#socket#_pendingEncoding="" response#socket#server= response#socket#_server= response#socket#ssl= response#socket#_requestCert=true response#socket#_rejectUnauthorized=true response#socket#parser= response#socket#_httpMessage#_events#socket="function (socket) {
    // `._connecting` was the old property which was made public in node v6.1.0
    var isConnecting = socket._connecting || socket.connecting
    if (self.timing) {
      self.timings.socket = now() - self.startTimeNow

      if (isConnecting) {
        var onLookupTiming = function () {
          self.timings.lookup = now() - self.startTimeNow
        }

        var onConnectTiming = function () {
          self.timings.connect = now() - self.startTimeNow
        }

        socket.once('lookup', onLookupTiming)
        socket.once('connect', onConnectTiming)

        // clean up timing event listeners if needed on error
        self.req.once('error', function () {
          socket.removeListener('lookup', onLookupTiming)
          socket.removeListener('connect', onConnectTiming)
        })
      }
    }

    var setReqTimeout = function () {
      // This timeout sets the amount of time to wait *between* bytes sent
      // from the server once connected.
      //
      // In particular, it's useful for erroring if the server fails to send
      // data halfway through streaming a response.
      self.req.setTimeout(timeout, function () {
        if (self.req) {
          self.abort()
          var e = new Error('ESOCKETTIMEDOUT')
          e.code = 'ESOCKETTIMEDOUT'
          e.connect = false
          self.emit('error', e)
        }
      })
    }
    if (timeout !== undefined) {
      // Only start the connection timer if we're actually connecting a new
      // socket, otherwise if we're already connected (because this is a
      // keep-alive connection) do not bother. This is important since we won't
      // get a 'connect' event for an already connected socket.
      if (isConnecting) {
        var onReqSockConnect = function () {
          socket.removeListener('connect', onReqSockConnect)
          clearTimeout(self.timeoutTimer)
          self.timeoutTimer = null
          setReqTimeout()
        }

        socket.on('connect', onReqSockConnect)

        self.req.on('error', function (err) { // eslint-disable-line handle-callback-err
          socket.removeListener('connect', onReqSockConnect)
        })

        // Set a timeout in memory - this block will throw if the server takes more
        // than `timeout` to write the HTTP status and headers (corresponding to
        // the on('response') event on the client). NB: this measures wall-clock
        // time, not the time between bytes sent by the server.
        self.timeoutTimer = setTimeout(function () {
          socket.removeListener('connect', onReqSockConnect)
          self.abort()
          var e = new Error('ETIMEDOUT')
          e.code = 'ETIMEDOUT'
          e.connect = true
          self.emit('error', e)
        }, timeout)
      } else {
        // We're already connected
        setReqTimeout()
      }
    }
    self.emit('socket', socket)
  }" response#socket#_httpMessage#_events#response="function () { [native code] }" response#socket#_httpMessage#_events#error="function () { [native code] }" response#socket#_httpMessage#_events#drain="function () {
    self.emit('drain')
  }" response#socket#_httpMessage#_events#prefinish="function requestOnPrefinish() {
  const req = this;

  if (req.shouldKeepAlive && req._ended)
    responseKeepAlive(req);
}" response#socket#_httpMessage#_eventsCount=5 response#socket#_httpMessage#_maxListeners= response#socket#_httpMessage#outputData="" response#socket#_httpMessage#outputSize=0 response#socket#_httpMessage#writable=true response#socket#_httpMessage#_last=true response#socket#_httpMessage#chunkedEncoding=false response#socket#_httpMessage#shouldKeepAlive=false response#socket#_httpMessage#useChunkedEncodingByDefault=false response#socket#_httpMessage#sendDate=false response#socket#_httpMessage#_removedConnection=false response#socket#_httpMessage#_removedContLen=false response#socket#_httpMessage#_removedTE=false response#socket#_httpMessage#_contentLength=0 response#socket#_httpMessage#_hasBody=true response#socket#_httpMessage#_trailer="" response#socket#_httpMessage#finished=true response#socket#_httpMessage#_headerSent=true response#socket#_httpMessage#socket=[Circular] response#socket#_httpMessage#connection=[Circular] response#socket#_httpMessage#_header="GET /v3/scores/bgwiki/?models=damaging%7Cgoodfaith&revids=10381661 HTTP/1.1
host: ores.wikimedia.org
accept: application/json
Connection: close

xinbenlv avatar Jul 06 '20 19:07 xinbenlv