[misc] wrap redis errors as tagging does not work with them

ioredis may reuse the error instance for multiple callbacks. E.g. when
 the connection to redis fails, the queue is flushed with the same
 MaxRetriesPerRequestError instance.
This commit is contained in:
Jakob Ackermann 2020-08-21 12:15:35 +01:00
parent 537e97be73
commit ee3d3b09ed
4 changed files with 19 additions and 16 deletions

View file

@ -23,12 +23,13 @@ module.exports = {
const channel = `${baseChannel}:${id}`
const actualSubscribe = function () {
// subscribe is happening in the foreground and it should reject
const p = rclient.subscribe(channel)
p.finally(function () {
if (clientChannelMap.get(channel) === subscribePromise) {
clientChannelMap.delete(channel)
}
})
return rclient
.subscribe(channel)
.finally(function () {
if (clientChannelMap.get(channel) === subscribePromise) {
clientChannelMap.delete(channel)
}
})
.then(function () {
logger.log({ channel }, 'subscribed to channel')
metrics.inc(`subscribe.${baseChannel}`)
@ -37,9 +38,10 @@ module.exports = {
logger.error({ channel, err }, 'failed to subscribe to channel')
metrics.inc(`subscribe.failed.${baseChannel}`)
// add context for the stack-trace at the call-site
OError.tag(err, 'failed to subscribe to channel', { channel })
throw new OError('failed to subscribe to channel', {
channel
}).withCause(err)
})
return p
}
const pendingActions = clientChannelMap.get(channel) || Promise.resolve()

View file

@ -68,7 +68,7 @@ module.exports = {
multi.exec(function (err) {
if (err) {
OError.tag(err, 'problem marking user as connected')
err = new OError('problem marking user as connected').withCause(err)
}
callback(err)
})
@ -104,7 +104,7 @@ module.exports = {
multi.del(Keys.connectedUser({ project_id, client_id }))
multi.exec(function (err) {
if (err) {
OError.tag(err, 'problem marking user as disconnected')
err = new OError('problem marking user as disconnected').withCause(err)
}
callback(err)
})
@ -116,9 +116,9 @@ module.exports = {
result
) {
if (err) {
OError.tag(err, 'problem fetching connected user details', {
err = new OError('problem fetching connected user details', {
other_client_id: client_id
})
}).withCause(err)
return callback(err)
}
if (!(result && result.user_id)) {
@ -154,7 +154,7 @@ module.exports = {
results
) {
if (err) {
OError.tag(err, 'problem getting clients in project')
err = new OError('problem getting clients in project').withCause(err)
return callback(err)
}
const jobs = results.map((client_id) => (cb) =>

View file

@ -136,12 +136,12 @@ const DocumentUpdaterManager = {
error
) {
if (error) {
OError.tag(error, 'error pushing update into redis')
error = new OError('error pushing update into redis').withCause(error)
return callback(error)
}
rclient.rpush('pending-updates-list', doc_key, function (error) {
if (error) {
OError.tag(error, 'error pushing doc_id into redis')
error = new OError('error pushing doc_id into redis').withCause(error)
}
callback(error)
})

View file

@ -91,7 +91,8 @@ describe('ChannelManager', function () {
)
p.then(() => done(new Error('should not subscribe but fail'))).catch(
(err) => {
err.message.should.equal('some redis error')
err.message.should.equal('failed to subscribe to channel')
err.cause.message.should.equal('some redis error')
this.ChannelManager.getClientMapEntry(this.rclient)
.has('applied-ops:1234567890abcdef')
.should.equal(false)