Redis
 sql >> Base de données >  >> NoSQL >> Redis

Comment dois-je me connecter à une instance Redis à partir d'une fonction AWS Lambda ?

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 :

  1. Une fois context.succeed() , context.fail() , ou context.done() est appelé, AWS peut geler tous les processus qui ne sont pas encore terminés. C'est ce qui faisait qu'AWS enregistrait Connection 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).
  2. 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 le require() 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.