diff --git a/docs/redis/overview.es.md b/docs/redis/overview.es.md new file mode 100644 index 00000000..a2c99436 --- /dev/null +++ b/docs/redis/overview.es.md @@ -0,0 +1,169 @@ +# Redis + +[Redis](https://redis.io/) 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**](https://github.com/swift-server/RediStack), que es el controlador subyacente que se comunica con Redis. + +!!! note "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](../getting-started/hello-world.md). + +```swift +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`](https://swiftpackageindex.com/swift-server/RediStack/main/documentation/redistack/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: + +```swift +let app = Application() + +app.redis.configuration = try RedisConfiguration(hostname: "localhost") +``` + +### Configuración de Redis + +> Documentación de la API: [`RedisConfiguration`](https://api.vapor.codes/redis/documentation/redis/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]`](https://swiftpackageindex.com/apple/swift-nio/main/documentation/niocore/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:)`](https://swiftpackageindex.com/apple/swift-nio/main/documentation/niocore/socketaddress/makeaddressresolvinghost(_:port:)). + +```swift +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: + +- [`.init(url:pool)`](https://api.vapor.codes/redis/documentation/redis/redisconfiguration/init(url:tlsconfiguration:pool:)-o9lf) (con `String` o [`Foundation.URL`](https://developer.apple.com/documentation/foundation/url)) +- [`.init(hostname:port:password:database:pool:)`](https://api.vapor.codes/redis/documentation/redis/redisconfiguration/init(hostname:port:password:tlsconfiguration:database:pool:)) + +#### 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. + +!!! warning "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`](https://api.vapor.codes/redis/documentation/redis/redisconfiguration/pooloptions) + +!!! note "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. + +!!! seealso "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`](https://api.vapor.codes/vapor/documentation/vapor/application) o [`Request`](https://api.vapor.codes/vapor/documentation/vapor/request), lo que te dará acceso a un [`RedisClient`](https://swiftpackageindex.com/swift-server/RediStack/main/documentation/redistack/redisclient). + +Cualquier `RedisClient` tiene varias extensiones para todos los diversos [comandos de Redis](https://redis.io/commands). + +```swift +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. + +```swift +// 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"](https://redis.io/topics/pubsub) 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`](https://swiftpackageindex.com/swift-server/RediStack/main/documentation/redistack/redissubscriptionmessagereceiver) 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. + +```swift +// 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)") + } +```