Agora resolvi meu próprio problema e espero poder ajudar alguém que esteja enfrentando esse problema no futuro.
Há duas considerações principais ao se conectar a um banco de dados como fiz no código acima de uma função do Lambda:
- Uma vez
context.succeed()
,context.fail()
, oucontext.done()
é chamado, a AWS pode congelar todos os processos que ainda não foram concluídos. Isso é o que estava fazendo com que a AWS registrasseConnection closed
na segunda chamada para o endpoint da minha API — o processo foi congelado pouco antes de o Redis terminar de fechar e, em seguida, descongelado na próxima chamada, quando continuou exatamente de onde parou, relatando que a conexão foi fechada. Dica:se você quiser fechar sua conexão com o banco de dados, certifique-se de que ela esteja totalmente fechada antes você chama um desses métodos. Você pode fazer isso colocando um retorno de chamada em um manipulador de eventos que é acionado por um fechamento de conexão (.on('end')
, no meu caso). - Se você dividir seu código em arquivos separados e
require
na parte superior de cada arquivo, como eu fiz, a Amazon armazenará em cache o maior número possível desses módulos na memória. Se isso estiver causando problemas, tente mover orequire()
chamadas dentro de uma função em vez de na parte superior do arquivo e, em seguida, exportando essa função. Esses módulos serão reimportados sempre que a função for executada.
Segue meu código atualizado. Observe que também coloquei minha configuração do Redis em um arquivo separado, para que possa importá-la para outras funções do Lambda sem duplicar o código.
O manipulador de eventos
'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)
}
})
}
Configuração do Redis
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))
}
A Função
'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
})
}
})
}
})
}
}
})
})
}
Isso funciona exatamente como deveria - e é muito rápido também.