RediStack: Asynchronous Redis client for Swift (iOS/macOS)
RediStack is a modern, fully asynchronous client for working with Redis, written in Swift. The library is built on the SwiftNIO framework, ensuring high performance and low memory consumption. RediStack is ideal for iOS and macOS applications requiring fast caching, session management, message queues, or Pub/Sub functionality.
Key Features
- Full asynchrony based on Swift Concurrency (async/await) and Combine
- Support for all major Redis data types: strings, lists, sets, hashes, streams
- Built-in Pub/Sub support with automatic reconnection
- Automatic connection pooling
- Support for Redis Cluster and Sentinel
- SSL/TLS encryption for secure connections
- Type-safe commands with autocompletion in Xcode
Installation via Swift Package Manager
Add RediStack to your Package.swift or through Xcode:
// Package.swiftdependencies: [ .package(url: "https://github.com/RediStack/RediStack.git", from: "1.6.0")],targets: [ .target(name: "YourApp", dependencies: ["RediStack"])]Quick Start: Connecting to Redis
To get started, create a connection pool and execute simple commands:
import RediStackimport NIO
// Create an EventLoopGrouplet eventLoopGroup = MultiThreadedEventLoopGroup(numberOfThreads: 1)
// Configure the connection poollet pool = RedisConnectionPool( configuration: .init( initialServerConnectionAddresses: [try .init(hostname: "localhost", port: 6379)], maximumConnectionCount: .maximumActiveConnections(5) ), boundEventLoop: eventLoopGroup.next())
// Asynchronous work with RedisTask { do { // Set and get a string try await pool.set("greeting", to: "Hello from Swift!") let value = try await pool.get("greeting", as: String.self) print("Received: \\(value ?? "nil")") // "Received: Hello from Swift!" // Working with lists try await pool.lpush(["apple", "banana", "cherry"], into: "fruits") let fruits = try await pool.lrange(from: "fruits", firstIndex: 0, lastIndex: -1, as: [String].self) print("Fruits: \\(fruits)") // ["cherry", "banana", "apple"] } catch { print("Redis error: \\(error)") }}Example: Pub/Sub (Publisher-Subscriber)
RediStack supports full Pub/Sub with automatic subscription recovery:
import RediStackimport NIO
let eventLoopGroup = MultiThreadedEventLoopGroup(numberOfThreads: 2)let pool = RedisConnectionPool(...)
// SubscriberTask { let subscriber = pool.makeSubscriber(eventLoop: eventLoopGroup.next()) // Subscribe to a channel await subscriber.subscribe(to: "notifications") { channel, message in print("Received on channel \\(channel): \\(message.string ?? "")") } // Handle subscription errors subscriber.onError = { error in print("Pub/Sub error: \\(error)") }}
// Publisher (sending a message)Task { try await pool.publish("New notification", to: "notifications")}Working with Hashes and Transactions
Example of using hashes and atomic operations with transactions:
// Set hash fieldstry await pool.hmset("user:1001", with: [ "name": "Ivan Petrov", "email": "ivan@example.com", "age": "30"])
// Get all fieldslet user = try await pool.hgetall(from: "user:1001")print("Name: \\(user["name"]?.string ?? "")") // "Name: Ivan Petrov"
// Transaction (atomic execution)try await pool.transaction { transaction in transaction.inc