Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

Redis Driver

“Redis stores time — QAIL decides.”

The qail-redis crate provides a unified Qail AST interface for Redis operations.

Installation

[dependencies]
qail-redis = "0.14"

Quick Start

use qail_redis::{RedisDriver, RedisExt};
use qail_core::prelude::*;

#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
    let mut driver = RedisDriver::connect("127.0.0.1", 6379).await?;
    
    // Unified Qail AST - same pattern as PostgreSQL/Qdrant
    driver.execute(&Qail::redis_set("session:123", b"data".to_vec()).redis_ex(3600)).await?;
    
    let value = driver.get_str("session:123").await?;
    println!("Value: {:?}", value);
    
    Ok(())
}

Unified API

Redis uses the same Qail type as PostgreSQL and Qdrant:

DatabaseConstructorPurpose
PostgreSQLQail::get("users")Query facts
QdrantQail::search("products")Search meaning
RedisQail::redis_get("session")Retrieve time-bound data

Available Commands

String Commands

#![allow(unused)]
fn main() {
// GET key
Qail::redis_get("mykey")

// SET key value
Qail::redis_set("mykey", b"value".to_vec())

// SET with TTL (seconds)
Qail::redis_set("mykey", b"value".to_vec()).redis_ex(3600)

// SET only if not exists
Qail::redis_set("mykey", b"value".to_vec()).redis_nx()

// SET only if exists
Qail::redis_set("mykey", b"value".to_vec()).redis_xx()
}

Counter Commands

#![allow(unused)]
fn main() {
// INCR key
Qail::redis_incr("counter")

// DECR key  
Qail::redis_decr("counter")
}

Key Commands

#![allow(unused)]
fn main() {
// DEL key
Qail::redis_del("mykey")

// EXISTS key
Qail::redis_exists("mykey")

// TTL key
Qail::redis_ttl("mykey")

// EXPIRE key seconds
Qail::redis_expire("mykey", 60)
}

Other Commands

#![allow(unused)]
fn main() {
// PING
Qail::redis_ping()
}

RedisExt Trait

The RedisExt trait provides fluent methods for Redis-specific options:

#![allow(unused)]
fn main() {
use qail_redis::RedisExt;

// Chain TTL onto SET
Qail::redis_set("key", b"value".to_vec())
    .redis_ex(3600)  // EX seconds
    .redis_nx()       // Only if not exists
}

Connection Pooling

#![allow(unused)]
fn main() {
use qail_redis::{RedisPool, PoolConfig};

let config = PoolConfig::new("127.0.0.1", 6379)
    .max_connections(10);

let pool = RedisPool::new(config);

// Get a connection from the pool
let mut conn = pool.get().await?;
conn.set("key", b"value").await?;
}

Native RESP3 Protocol

qail-redis implements native RESP3 protocol encoding/decoding:

  • Zero string parsing: Commands are encoded directly from AST
  • Full RESP3 support: Booleans, doubles, maps, nulls
  • Efficient: Direct wire protocol writes

The QAIL Vision

“Postgres stores facts, Qdrant stores meaning, Redis stores time — QAIL decides.”

With qail-redis, you now have a unified API across all three database paradigms:

#![allow(unused)]
fn main() {
// Facts (PostgreSQL)
Qail::get("users").filter("active", Eq, true)

// Meaning (Qdrant)
Qail::search("products").vector(&embedding).limit(10)

// Time (Redis)
Qail::redis_set("session:123", session_data).redis_ex(3600)
}

Same Qail type. Same philosophy. Different backends.