Redis
 sql >> Base de Dados >  >> NoSQL >> Redis

Como devo me conectar a uma instância do Redis de uma função do AWS Lambda?


Agora resolvi meu próprio problema e espero poder ajudar alguém que esteja enfrentando esse problema no futuro.

Há duas considerações principais ao se conectar a um banco de dados como fiz no código acima de uma função do Lambda:
  1. Uma vez context.succeed() , context.fail() , ou context.done() é chamado, a AWS pode congelar todos os processos que ainda não foram concluídos. Isso é o que estava fazendo com que a AWS registrasse Connection closed na segunda chamada para o endpoint da minha API — o processo foi congelado pouco antes de o Redis terminar de fechar e, em seguida, descongelado na próxima chamada, quando continuou exatamente de onde parou, relatando que a conexão foi fechada. Dica:se você quiser fechar sua conexão com o banco de dados, certifique-se de que ela esteja totalmente fechada antes você chama um desses métodos. Você pode fazer isso colocando um retorno de chamada em um manipulador de eventos que é acionado por um fechamento de conexão (.on('end') , no meu caso).
  2. Se você dividir seu código em arquivos separados e require na parte superior de cada arquivo, como eu fiz, a Amazon armazenará em cache o maior número possível desses módulos na memória. Se isso estiver causando problemas, tente mover o require() chamadas dentro de uma função em vez de na parte superior do arquivo e, em seguida, exportando essa função. Esses módulos serão reimportados sempre que a função for executada.

Segue meu código atualizado. Observe que também coloquei minha configuração do Redis em um arquivo separado, para que possa importá-la para outras funções do Lambda sem duplicar o código.

O manipulador 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)
    }
  })
}

Configuração do 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))
}

A Função

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

Isso funciona exatamente como deveria - e é muito rápido também.