Ik heb nu mijn eigen probleem opgelost en ik hoop dat ik in de toekomst iemand kan helpen die met dit probleem te maken heeft.
Er zijn twee belangrijke overwegingen bij het verbinden met een database zoals ik deed in de bovenstaande code vanuit een Lambda-functie:
- Eenmaal
context.succeed()
,context.fail()
, ofcontext.done()
wordt genoemd, kan AWS alle processen bevriezen die nog niet zijn voltooid. Dit zorgde ervoor dat AWSConnection closed
registreerde bij de tweede aanroep naar mijn API-eindpunt - het proces werd bevroren net voordat Redis klaar was met sluiten en vervolgens ontdooid bij de volgende aanroep, waarna het verder ging waar het was gebleven, met de melding dat de verbinding was verbroken. Afhaalmaaltijden:als u uw databaseverbinding wilt sluiten, zorg er dan voor dat deze voor volledig is gesloten noem je een van die methoden. U kunt dit doen door een callback in een gebeurtenishandler te plaatsen die wordt geactiveerd door het sluiten van een verbinding (.on('end')
, in mijn geval). - Als u uw code in afzonderlijke bestanden splitst en
require
ze bovenaan elk bestand, zoals ik deed, zal Amazon zoveel mogelijk van die modules in het geheugen cachen. Als dat problemen veroorzaakt, probeer dan derequire()
aanroepen in een functie in plaats van bovenaan het bestand, en vervolgens die functie exporteren. Die modules worden dan opnieuw geïmporteerd wanneer de functie wordt uitgevoerd.
Hier is mijn bijgewerkte code. Merk op dat ik mijn Redis-configuratie ook in een apart bestand heb gezet, zodat ik het in andere Lambda-functies kan importeren zonder code te dupliceren.
De gebeurtenishandler
'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-configuratie
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))
}
De Functie
'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
})
}
})
}
})
}
}
})
})
}
Dit werkt precies zoals het hoort, en het is ook nog eens razendsnel.