J'ai maintenant résolu mon propre problème et j'espère que je pourrai aider quelqu'un qui rencontrera ce problème à l'avenir.
Il y a deux considérations majeures lors de la connexion à une base de données comme je l'ai fait dans le code ci-dessus à partir d'une fonction Lambda :
- Une fois
context.succeed()
,context.fail()
, oucontext.done()
est appelé, AWS peut geler tous les processus qui ne sont pas encore terminés. C'est ce qui faisait qu'AWS enregistraitConnection closed
lors du deuxième appel à mon point de terminaison API, le processus a été gelé juste avant la fin de la fermeture de Redis, puis dégelé lors de l'appel suivant, auquel cas il a continué là où il s'était arrêté, signalant que la connexion était fermée. À retenir :si vous souhaitez fermer votre connexion à la base de données, assurez-vous qu'elle est complètement fermée avant vous appelez l'une de ces méthodes. Vous pouvez le faire en plaçant un rappel dans un gestionnaire d'événements déclenché par une fermeture de connexion (.on('end')
, dans mon cas). - Si vous divisez votre code en fichiers séparés et
require
placez-les en haut de chaque fichier, comme je l'ai fait, Amazon mettra en cache autant de ces modules que possible en mémoire. Si cela cause des problèmes, essayez de déplacer lerequire()
appelle à l'intérieur d'une fonction plutôt qu'en haut du fichier, puis exporte cette fonction. Ces modules seront ensuite réimportés à chaque exécution de la fonction.
Voici mon code mis à jour. Notez que j'ai également placé ma configuration Redis dans un fichier séparé, afin de pouvoir l'importer dans d'autres fonctions Lambda sans dupliquer le code.
Le gestionnaire d'événements
'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)
}
})
}
Configuration 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))
}
La fonction
'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
})
}
})
}
})
}
}
})
})
}
Cela fonctionne exactement comme il se doit, et c'est aussi très rapide.