wikiloop-doublecheck
wikiloop-doublecheck copied to clipboard
Fix: handle API:fetchOres has an unknown error of
[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