Saltar a contenido

Redis

Redis es uno de los motores de almacenamiento de base de datos en memoria más populares, comúnmente utilizado como caché o intermediario de mensajes.

Esta biblioteca es una integración entre Vapor y RediStack, que es el controlador subyacente que se comunica con Redis.

Nota

La mayoría de las capacidades de Redis son proporcionadas por RediStack. Recomendamos encarecidamente familiarizarse con su documentación.

Se proporcionan enlaces donde corresponda.

Paquete

El primer paso para usar Redis es añadirlo como una dependencia a tu proyecto en tu manifiesto de paquete Swift.

Este ejemplo es para un paquete existente. Para obtener ayuda sobre cómo iniciar un nuevo proyecto, consulta la guía Comenzando.

dependencies: [
    // ...
    .package(url: "https://github.com/vapor/redis.git", from: "4.0.0")
]
// ...
targets: [
    .target(name: "App", dependencies: [
        // ...
        .product(name: "Redis", package: "redis")
    ])
]

Configurar

Vapor emplea una estrategia de agrupación para instancias de RedisConnection, y hay varias opciones para configurar las conexiones individuales así como los propios grupos.

El mínimo requerido para configurar Redis es proporcionar una URL para conectar:

let app = Application()

app.redis.configuration = try RedisConfiguration(hostname: "localhost")

Configuración de Redis

Documentación de la API: RedisConfiguration

serverAddresses

Si tienes varios puntos de conexión con Redis, como un grupo de instancias de Redis, querrás crear una colección de [SocketAddress] para pasar en el inicializador.

La forma más común de crear un SocketAddress es con el método estático makeAddressResolvingHost(_:port:).

let serverAddresses: [SocketAddress] = [
  try .makeAddressResolvingHost("localhost", port: RedisConnection.Configuration.defaultPort)
]

Para un único punto de conexión con Redis, puede ser más fácil trabajar con los inicializadores de conveniencia, ya que manejará la creación del SocketAddress por ti:

password

Si tu instancia de Redis está asegurada con una contraseña, deberás pasarla como el argumento password.

Cada conexión, según se crea, será autenticada usando la contraseña.

database

Este es el índice de la base de datos que deseas seleccionar cuando se crea cada conexión.

Esto te ahorra tener que enviar el comando SELECT a Redis tú mismo.

Advertencia

La selección de la base de datos no se mantiene. Ten cuidado al enviar el comando SELECT por tu cuenta.

Opciones del Grupo de Conexiones

Documentación de la API: RedisConfiguration.PoolOptions

Nota

Aquí solo se destacan las opciones que se cambian con más frecuencia. Para todas las opciones, consulta la documentación de la API.

minimumConnectionCount

Este es el valor que establece cuántas conexiones deseas que cada grupo mantenga en todo momento.

Si el valor es 0, entonces si las conexiones se pierden por cualquier motivo, el grupo no las recreará hasta que sea necesario.

Esto se conoce como una conexión de "inicio en frío" ("cold start"), y tiene cierta sobrecarga sobre el mantenimiento de un recuento mínimo de conexiones.

maximumConnectionCount

Esta opción determina el comportamiento de cómo se mantiene el recuento máximo de conexiones.

Ver También

Consulta la API RedisConnectionPoolSize para familiarizarte con las opciones disponibles.

Enviando un Comando

Puedes enviar comandos usando la propiedad .redis en cualquier instancia de Application o Request, lo que te dará acceso a un RedisClient.

Cualquier RedisClient tiene varias extensiones para todos los diversos comandos de Redis.

let value = try app.redis.get("my_key", as: String.self).wait()
print(value)
// Optional("my_value")

// o

let value = try await app.redis.get("my_key", as: String.self)
print(value)
// Optional("my_value")

Comandos no soportados

Si RediStack no soporta un comando con un método de extensión, aún puedes enviarlo manualmente.

// cada valor después del comando es el argumento posicional que Redis espera
try app.redis.send(command: "PING", with: ["hello"])
    .map {
        print($0)
    }
    .wait()
// "hello"

// o

let res = try await app.redis.send(command: "PING", with: ["hello"])
print(res)
// "hello"

Modo Pub/Sub

Redis admite la capacidad de entrar en un modo "Pub/Sub" donde una conexión puede escuchar "canales" específicos y ejecutar closures (métodos) específicos cuando los canales suscritos publican un "mensaje" (algún valor de datos).

Hay un ciclo de vida definido para una suscripción:

  1. subscribe: invocado una vez cuando la suscripción comienza por primera vez
  2. message: invocado 0 o más veces a medida que se publican mensajes en los canales suscritos
  3. unsubscribe: invocado una vez cuando la suscripción termina, ya sea por solicitud o por pérdida de conexión

Cuando creas una suscripción, debes proporcionar al menos un messageReceiver para manejar todos los mensajes que son publicados por el canal suscrito.

Opcionalmente, puedes proporcionar un RedisSubscriptionChangeHandler para onSubscribe y onUnsubscribe que maneje sus respectivos eventos del ciclo de vida.

// crea 2 suscripciones, una para cada canal
app.redis.subscribe
  to: "channel_1", "channel_2",
  messageReceiver: { channel, message in
    switch channel {
    case "channel_1": // haz algo con el mensaje
    default: break
    }
  },
  onUnsubscribe: { channel, subscriptionCount in
    print("unsubscribed from \(channel)")
    print("subscriptions remaining: \(subscriptionCount)")
  }