sql >> Base de Datos >  >> NoSQL >> Redis

¿Cómo debo conectarme a una instancia de Redis desde una función de AWS Lambda?

Ahora he resuelto mi propio problema y espero poder ayudar a alguien que experimente este problema en el futuro.

Hay dos consideraciones principales al conectarse a una base de datos como lo hice en el código anterior desde una función Lambda:

  1. Una vez context.succeed() , context.fail() , o context.done() se llama, AWS puede congelar cualquier proceso que aún no haya finalizado. Esto es lo que estaba causando que AWS registrara Connection closed en la segunda llamada a mi punto final de API:el proceso se congeló justo antes de que Redis terminara de cerrarse, luego se descongeló en la siguiente llamada, momento en el que continuó justo donde lo dejó, informando que la conexión se cerró. Conclusión:si desea cerrar la conexión de su base de datos, asegúrese de que esté completamente cerrada antes usted llama a uno de esos métodos. Puede hacer esto colocando una devolución de llamada en un controlador de eventos que se desencadena por el cierre de una conexión (.on('end') , en mi caso).
  2. Si divide su código en archivos separados y require en la parte superior de cada archivo, como hice yo, Amazon almacenará en caché tantos de esos módulos como sea posible en la memoria. Si eso está causando problemas, intente mover require() llama dentro de una función en lugar de en la parte superior del archivo, luego exporta esa función. Esos módulos se volverán a importar cada vez que se ejecute la función.

Aquí está mi código actualizado. Tenga en cuenta que también puse mi configuración de Redis en un archivo separado, por lo que puedo importarla a otras funciones de Lambda sin duplicar el código.

El controlador 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)
    }
  })
}

Configuración de 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 función

'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
                  })
                }
              })
            }
          })
        }
      }
    })
  })
}

Esto funciona exactamente como debería, y también es ultrarrápido.