Ora ho risolto il mio problema e spero di poter essere d'aiuto a qualcuno che avrà questo problema in futuro.
Ci sono due considerazioni principali quando ci si connette a un database come ho fatto nel codice sopra da una funzione Lambda:
- Una volta
context.succeed()
,context.fail()
ocontext.done()
viene chiamato, AWS potrebbe bloccare tutti i processi che non sono ancora terminati. Questo è il motivo per cui AWS registravaConnection closed
alla seconda chiamata al mio endpoint API:il processo è stato bloccato appena prima che Redis terminasse la chiusura, quindi si è scongelato alla chiamata successiva, a quel punto è continuato da dove si era interrotto, segnalando che la connessione era chiusa. Takeaway:se vuoi chiudere la connessione al database, assicurati che sia completamente chiusa prima chiami uno di quei metodi. Puoi farlo inserendo un callback in un gestore eventi attivato da una chiusura della connessione (.on('end')
, nel mio caso). - Se dividi il codice in file separati e
require
nella parte superiore di ogni file, come ho fatto io, Amazon memorizzerà nella cache quanti più moduli possibile in memoria. Se ciò causa problemi, prova a spostarerequire()
chiama all'interno di una funzione invece che nella parte superiore del file, quindi esporta quella funzione. Tali moduli verranno quindi reimportati ogni volta che viene eseguita la funzione.
Ecco il mio codice aggiornato. Tieni presente che ho anche inserito la mia configurazione Redis in un file separato, così posso importarla in altre funzioni Lambda senza duplicare il codice.
Il gestore dell'evento
'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)
}
})
}
Configurazione 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 funzione
'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
})
}
})
}
})
}
}
})
})
}
Funziona esattamente come dovrebbe e anche velocissimo.