preview-glide-rust 0.2.0

Valkey GLIDE — native Rust client for Valkey and Redis OSS, built on glide-core.
docs.rs failed to build preview-glide-rust-0.2.0
Please check the build logs for more information.
See Builds for ideas on how to fix a failed build, or Metadata for how to configure docs.rs builds.
If you believe this is docs.rs' fault, open an issue.

Valkey GLIDE for Rust (glide)

CI License: Apache-2.0 Rust

A first-class, native Rust client for Valkey and Redis OSS, built directly on the shared glide-core engine that powers the official GLIDE clients for Python, Java, Node, and Go.

Because glide-core is itself written in Rust, this wrapper links to it directly — no FFI, no socket bridge — making it the thinnest and fastest GLIDE binding.

Highlights

  • Async firstGlideClient (standalone) and GlideClusterClient (cluster) built on Tokio.
  • Blocking API — a sync layer mirrors the async surface for non-async code (enabled by the default sync feature).
  • Broad command coverage — typed methods across strings, generic/key, hash, list, set, sorted-set, HyperLogLog, bitmap, geo, stream, scripting, connection- and server-management, plus batches/transactions.
  • custom_command escape hatch — run any command (with optional cluster routing) even where a typed wrapper is not provided, guaranteeing 100% functional coverage.
  • Batchingpipe() pipelines and MULTI/EXEC transactions, executed typed via query_glide (zero extra payload copies) or with GLIDE execution controls (PipelineOptions: per-call timeout and pipeline retry strategy) via execute_pipeline.
  • Dynamic authentication — rotate the connection password at runtime with update_connection_password, or use AWS IAM auth (ElastiCache / MemoryDB) via ServerCredentials::iam.
  • Runtime Pub/Subsubscribe/psubscribe/ssubscribe (and the matching unsubscribes) in addition to connect-time subscriptions; messages arrive via get_pubsub_message.
  • OpenTelemetry — export traces and metrics via the glide::telemetry module (gRPC / HTTP / file exporters).
  • Feature parity with the Python GLIDE wrapper as the baseline for both the API surface and the test suite.

Installation

Prerequisites

  • Rust 1.85+ (the crate and glide-core use edition 2024).
  • Network access on the first build — the crate links glide-core and its redis-rs fork as crates.io dependencies (the experimentally-published experimental-glide-* crates), which Cargo fetches automatically (see Status & publishing).
  • A running Valkey (or Redis OSS) server to connect to — e.g. valkey-server locally, docker run -p 6379:6379 valkey/valkey, or an ElastiCache/MemoryDB endpoint.

1. Add the dependency

The crate is not yet on crates.io (see Status & publishing), so depend on it via git. The package is named glide-rust and the library is imported as glide:

# Cargo.toml
[dependencies]
glide-rust = { git = "https://github.com/omerrubi-amzn/glide-rust", branch = "main" }
# Async runtime (the async client is built on Tokio):
tokio = { version = "1", features = ["rt-multi-thread", "macros"] }

Pin to a specific commit for reproducible builds with rev = "<sha>" instead of branch = "main".

2. Provide the required build-time environment (important)

The vendored redis-rs fork reads two variables at compile time (via env!), so any crate that builds it — including yours — must define them, or the build fails with environment variable GLIDE_VERSION not defined. Add a .cargo/config.toml at your project (or workspace) root:

# .cargo/config.toml
[env]
GLIDE_NAME = "GlideRust"
GLIDE_VERSION = "0.2.0"
# Optional: avoids an aws-lc-rs CPU-jitter-entropy connection-latency regression.
AWS_LC_SYS_NO_JITTER_ENTROPY = "1"

(These identify the client library/version reported to the server on the connection handshake.)

3. Build

cargo build

The first build fetches and compiles glide-core and its dependency tree, so it takes a few minutes; subsequent builds are incremental.

Contributor setup

Cloning this repository to develop the client? See DEVELOPER.md for the full workflow (build, run the unit + live integration tests — which spawn a valkey-server, set VALKEY_SERVER_PATH to point at your binary — lint, coverage, and benchmarks).

Quick start (async)

use glide::{AsyncCommands, GlideClient, GlideClientConfiguration};

#[tokio::main]
async fn main() -> glide::RedisResult<()> {
    let config = GlideClientConfiguration::with_address("localhost", 6379);
    let client = GlideClient::connect(config).await.expect("connect");

    client.set::<_, _, ()>("hello", "world").await?;
    let value: Option<String> = client.get("hello").await?;
    assert_eq!(value.as_deref(), Some("world"));
    Ok(())
}

Quick start (sync)

use glide::sync::SyncGlideClient;
use glide::{Commands, GlideClientConfiguration};

fn main() -> glide::RedisResult<()> {
    let client = SyncGlideClient::connect(
        GlideClientConfiguration::with_address("localhost", 6379),
    ).expect("connect");
    client.set::<_, _, ()>("hello", "world")?;
    let value: Option<String> = client.get("hello")?;
    assert_eq!(value.as_deref(), Some("world"));
    Ok(())
}

Cluster & routing

use glide::{GlideClusterClient, GlideClusterClientConfiguration, Route, CustomCommand};

# async fn demo() -> glide::Result<()> {
let client = GlideClusterClient::connect(
    GlideClusterClientConfiguration::with_address("localhost", 7000),
).await?;

// Broadcast PING to all primaries.
client.custom_command_with_route(&["PING"], Route::AllPrimaries).await?;
# Ok(()) }

See DESIGN.md for architecture, and DEVELOPER.md for how to build, test, and benchmark.

Migrating from redis-rs

GLIDE's command API is source-compatible with the redis-rs fork (v0.25.2, predating the upstream license change): method names, signatures, and wire encoding match, so existing typed call sites compile unchanged with RedisResult errors. Everything you need is re-exported from glide.

Every command is executed by glide-core (multiplexing, cluster routing, reconnection, IAM auth), handed over by value on GLIDE's zero-extra-copy path. Parity is deliberately a command-surface contract, not a connection-plumbing one: the clients are not redis connection objects (ConnectionLike), because that interop layer forced a full payload copy per command. The migrations that follow from this are mechanical:

redis-rs call site GLIDE call site
pipe()….query_async(&mut c) pipe()….query_glide(&c) (PipelineExt)
sync pipe()….query(&mut c) pipe()….query_glide(&c) (sync::PipelineExt)
cmd("X")….query_async(&mut c) c.glide_send(cmd) (typed, by value)
con.scan_match(pat) iterators same call — GLIDE-owned iterator, same next_item() / Iterator shape
use glide::{AsyncCommands, GlideClient, GlideClientConfiguration, PipelineExt, Script, pipe};

# async fn demo() -> glide::RedisResult<()> {
// Standard connection-URL semantics, including rediss:// and database selection:
let config = GlideClientConfiguration::from_url("redis://user:pass@localhost:6379/2")
    .expect("valid URL");
# let client = GlideClient::connect(config).await.unwrap();

// Typed commands, unchanged from redis-rs call sites:
client.set::<_, _, ()>("key", 42).await?;
let value: i64 = client.get("key").await?;

// Pipelines and transactions (zero extra payload copies):
let (a, b): (i64, i64) = pipe()
    .atomic()
    .incr("counter", 1)
    .incr("counter", 1)
    .query_glide(&client)
    .await?;

// Lua scripts with EVALSHA caching:
let script = Script::new("return tonumber(ARGV[1]) + 1");
let n: i64 = script.arg(41).invoke_async(&client).await?;
# Ok(()) }

Notes:

  • glide::AsyncCommands / glide::Commands are GLIDE's command API. Extension traits (streams, geo, Search FT.*, JSON.*, hash field-TTL, …) cover the rest of the command surface; names never collide, so import both freely.
  • Cluster: GlideClusterClientConfiguration::from_urls([...]) accepts seed-node URLs; commands are routed automatically.
  • Mutual TLS: config.client_identity(cert_pem, key_pem).
  • Raw commands: build a redis::Cmd and send it typed with client.glide_send(cmd) (or untyped with glide_send_owned / custom_command) — this replaces cmd().query_async(), without the connection-object copy.
  • Accepted gaps: no Sentinel / unix sockets / async-std (unsupported by glide-core); Pub/Sub stays client-integrated by design; generic code bounded on the fork's ConnectionLike-based traits should re-bound on glide::AsyncCommands (performance-motivated deviation).

Testing

The suite has three layers (all run in CI and are currently green):

  • Unit tests (server-free, ~260) — pure logic with no server: config → ConnectionRequest lowering, route → RoutingInfo mapping, option/argument encoding, value conversion, and error mapping; plus a command-family mock suite that drives every typed command through an in-process executor to assert exact request encoding and response decoding.
  • Integration tests (live server, ~900 executions across 31 files) — real round-trips against a spawned valkey-server, one tests/it_<family>.rs per command family with edge/error cases (wrong-type, missing key, bounds, expiry conditions), parametrized over RESP2 and RESP3, plus suites for batches, scan, pub/sub, auth, TLS, and a native multi-shard cluster harness. Each test boots its own ephemeral server and tears it down on drop; suites needing unavailable infra (cluster/TLS/auth) skip gracefully rather than fail.
  • Doctests — the examples in this README and the API docs are compiled.
cargo test --lib     # fast unit + mock tests only (no server needed)
cargo test           # everything, incl. live integration tests + doctests

Integration tests auto-discover a valkey-server/redis-server on PATH; point them at a specific binary with VALKEY_SERVER_PATH=/path/to/valkey-server. See DEVELOPER.md for coverage and benchmarks.

Status & publishing

This crate consumes glide-core and its redis-rs fork from crates.io, via the experimentally-published packages experimental-glide-core-lib (lib name glide_core) and experimental-glide-core-rs-dependency (lib name redis, v0.25.2 — the fork predating the upstream license change), pinned to exact versions in Cargo.toml. Consequences:

  • Builds fetch dependencies automatically from crates.io — no monorepo checkout, no git fetches.
  • The crates.io-publish blocker is gone: with no git/path dependencies, cargo publish (and docs.rs builds) of this crate are now possible.
  • Caveat — the core crates are explicitly experimental: brand-new, experimental- prefixed, and not (yet) the Valkey project's official stable publication channel. That's why the pins are exact (=x.y.z); bump them deliberately and re-run the parity guard (cargo test --test it_parity_guard), which flags any command-surface drift.

License

Licensed under the Apache License, Version 2.0. See the LICENSE file at the repository root for the full text.