Jag har nu löst mitt eget problem, och jag hoppas att jag kan vara till hjälp för någon som upplever det här problemet i framtiden.
Det finns två viktiga överväganden när du ansluter till en databas som jag gjorde i koden ovan från en Lambda-funktion:
- När
context.succeed()
,context.fail()
, ellercontext.done()
anropas kan AWS frysa alla processer som inte har slutförts ännu. Det var detta som fick AWS att loggaConnection closed
vid det andra anropet till min API-slutpunkt – processen frystes precis innan Redis avslutade stängningen, tinades sedan vid nästa anrop, då den fortsatte precis där den slutade och rapporterade att anslutningen stängdes. Takeaway:om du vill stänga din databasanslutning, se till att den är helt stängd innan du kallar en av dessa metoder. Du kan göra detta genom att göra en återuppringning i en händelsehanterare som utlöses av att en anslutning stängs (.on('end')
, i mitt fall). - Om du delar upp din kod i separata filer och
require
dem överst i varje fil, precis som jag gjorde, kommer Amazon att cache så många av dessa moduler som möjligt i minnet. Om det orsakar problem, försök att flyttarequire()
anropar inuti en funktion istället för överst i filen och exporterar sedan den funktionen. Dessa moduler kommer sedan att återimporteras när funktionen körs.
Här är min uppdaterade kod. Observera att jag också har lagt in min Redis-konfiguration i en separat fil, så att jag kan importera den till andra Lambda-funktioner utan att duplicera kod.
Händelsehanteraren
'use strict'
const lib = require('../lib/related')
module.exports.handler = function (event, context) {
lib.respond(event, (err, res) => {
if (err) {
return context.fail(err)
} else {
return context.succeed(res)
}
})
}
Redis-konfiguration
module.exports = () => {
const redis = require('redis')
const jsonify = require('redis-jsonify')
const redisOptions = {
host: process.env.REDIS_URL,
port: process.env.REDIS_PORT,
password: process.env.REDIS_PASS
}
return jsonify(redis.createClient(redisOptions))
}
Funktionen
'use strict'
const rt = require('./ritetag')
module.exports.respond = function (event, callback) {
const redis = require('./redis')()
const tag = event.hashtag.replace(/^#/, '')
const key = 'related:' + tag
let error, response
redis.on('end', () => {
callback(error, response)
})
redis.on('ready', function () {
redis.get(key, (err, res) => {
if (err) {
redis.quit(() => {
error = err
})
} else {
if (res) {
// Tag is found in Redis, so send results directly.
redis.quit(() => {
response = res
})
} else {
// Tag is not yet in Redis, so query Ritetag.
rt.hashtagDirectory(tag, (err, res) => {
if (err) {
redis.quit(() => {
error = err
})
} else {
redis.set(key, res, (err) => {
if (err) {
redis.quit(() => {
error = err
})
} else {
redis.quit(() => {
response = res
})
}
})
}
})
}
}
})
})
}
Det här fungerar precis som det ska – och det går även fort.